#Requires -Version 5.1 <# .SYNOPSIS Pregateste exportul zilnic al bazei: D:\ROA\EXPORT_ORADMP cu backupora.exe, setari.ini, schema.txt si task-ul zilnic din Windows Task Scheduler. .DESCRIPTION Ce face, in ordine: 1. Creeaza D:\ROA\EXPORT_ORADMP (+ subdirectorul LOG). 2. Copiaza backupora.exe si config.fpw din kit (backup\). 3. Genereaza setari.ini din backup\setari.ini.template, inlocuind marcajele {{...}} cu valorile reale ale instalarii. 4. Genereaza schema.txt cu schemele de exportat, in formatul cerut de backupora.exe: SCHEMA;PAROLA@SERVICIU, cate una pe linie. CONTAFIN_ORACLE + firmele active din CONTAFIN_ORACLE.NOM_FIRME (parolele se citesc din NOM_FIRME.parola). Alternativ, il copiaza de pe serverul vechi (-SchemaFromPath). 5. Creeaza obiectul Oracle DIRECTORY BACKUP_ORACLE catre acelasi director, ca Data Pump sa poata scrie acolo, si da drepturi serviciului Oracle pe folder. 6. Inregistreaza un task zilnic in Windows Task Scheduler. Formatul lui setari.ini NU e cimentat in cod: sablonul e un fisier de date, iar scriptul doar substituie marcajele. ATENTIE la doua capcane ale lui backupora.exe, verificate in sursa lui (main.prg): - programul SCRIE in ini-ul implicit cheia "delete_backups_olther_xdays" (cu typo) dar CITESTE "delete_backups_older_xdays". Sablonul o are pe cea corecta. Nu o "corecta" inapoi. - alege intre exportul clasic si Data Pump dupa NUMELE executabilului din oracleexpfile. Ca sa foloseasca expdp, fisierul trebuie sa se cheme "expdp.exe"; de aceea aratam catre \bin\expdp.exe. Dump-urile ajung in \\ - backupora.exe creeaza singur subdirectorul pe zi. .PARAMETER ExportPath Directorul in care sta backupora.exe. Implicit D:\ROA\EXPORT_ORADMP. .PARAMETER BackupPath Unde ajung dump-urile. Implicit acelasi cu ExportPath, deci D:\ROA\EXPORT_ORADMP\\. Pe instalarile mai vechi de la clienti valoarea uzuala e C:\BACKUP_ORACLE - daca vrei sa pastrezi conventia aia, da-o explicit. .PARAMETER ContafinPassword Parola CONTAFIN_ORACLE, pentru linia lui din schema.txt. Implicit ROMFASTSOFT. .PARAMETER OracleHome Oracle home. Autodetectat daca lipseste. .PARAMETER ServiceName Serviciul bazei. Implicit XEPDB1. .PARAMETER SystemPassword Parola SYSTEM/SYS. Implicit romfastsoft. .PARAMETER SchemaFromPath Cale (locala sau UNC) catre un schema.txt existent, de regula de pe serverul vechi: \\server-vechi\d$\ROA\EXPORT_ORADMP\schema.txt Daca e dat si fisierul e citibil, se copiaza in loc sa se genereze. .PARAMETER RetentionDays Cate zile se pastreaza dump-urile. Ajunge in setari.ini. Implicit 7. .PARAMETER TaskTime Ora rularii zilnice, format HH:mm. Implicit 22:30. .PARAMETER TaskName Numele task-ului din Task Scheduler. Implicit "ROA Export Oracle". .PARAMETER TaskUser Contul sub care ruleaza task-ul. Implicit SYSTEM. .PARAMETER SkipTask Nu crea task-ul zilnic; doar directorul, fisierele si obiectul DIRECTORY. .PARAMETER SkipSchema Nu genera si nu copia schema.txt (il completezi manual dupa). .PARAMETER SchemaOnly Regenereaza doar schema.txt si iese. Nu atinge setari.ini, backupora.exe sau task-ul. Asa se reia pasul dupa faza 2, cand firmele exista in NOM_FIRME, fara sa pierzi corecturile facute manual in setari.ini. .EXAMPLE .\11-setup-backup-export.ps1 Varianta obisnuita, cu schema.txt generat din NOM_FIRME. .EXAMPLE .\11-setup-backup-export.ps1 -SchemaFromPath "\\10.0.0.5\d$\ROA\EXPORT_ORADMP\schema.txt" Preia schema.txt de pe serverul vechi, exact cum era acolo. .EXAMPLE .\11-setup-backup-export.ps1 -TaskTime "23:00" -RetentionDays 14 Alta ora si alta retentie. .NOTES File Name : 11-setup-backup-export.ps1 Prerequisite : drepturi de administrator; backup\backupora.exe prezent in kit Copyright 2026 : ROMFAST #> [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$ExportPath = "D:\ROA\EXPORT_ORADMP", [Parameter(Mandatory = $false)] [string]$BackupPath, [Parameter(Mandatory = $false)] [string]$ContafinPassword = "ROMFASTSOFT", [Parameter(Mandatory = $false)] [string]$OracleHome, [Parameter(Mandatory = $false)] [string]$ServiceName = "XEPDB1", [Parameter(Mandatory = $false)] [string]$SystemPassword = "romfastsoft", [Parameter(Mandatory = $false)] [string]$SchemaFromPath, [Parameter(Mandatory = $false)] [int]$RetentionDays = 7, [Parameter(Mandatory = $false)] [ValidatePattern('^\d{1,2}:\d{2}$')] [string]$TaskTime = "22:30", [Parameter(Mandatory = $false)] [string]$TaskName = "ROA Export Oracle", [Parameter(Mandatory = $false)] [string]$TaskUser = "SYSTEM", [Parameter(Mandatory = $false)] [switch]$SkipTask, [Parameter(Mandatory = $false)] [switch]$SkipSchema, [Parameter(Mandatory = $false)] [switch]$SchemaOnly ) $ErrorActionPreference = "Stop" . (Join-Path $PSScriptRoot "lib\logging-functions.ps1") . (Join-Path $PSScriptRoot "lib\oracle-functions.ps1") $configFile = Join-Path $PSScriptRoot "..\config.ps1" if (Test-Path $configFile) { . $configFile if (-not $PSBoundParameters.ContainsKey('OracleHome') -and $Config.OracleHome) { $OracleHome = $Config.OracleHome } if (-not $PSBoundParameters.ContainsKey('ServiceName') -and $Config.ServiceName) { $ServiceName = $Config.ServiceName } if (-not $PSBoundParameters.ContainsKey('SystemPassword') -and $Config.SystemPassword) { $SystemPassword = $Config.SystemPassword } } $stamp = Get-Date -Format 'yyyyMMdd_HHmmss' $logDir = Join-Path $PSScriptRoot "..\logs" if (-not (Test-Path $logDir)) { New-Item -ItemType Directory -Path $logDir -Force | Out-Null } Initialize-LogFile -LogPath (Join-Path $logDir "11-setup-backup-export_$stamp.log") -ScriptName "11-setup-backup-export.ps1" $kitBackupDir = Join-Path $PSScriptRoot "..\backup" function Test-Administrator { $identity = [Security.Principal.WindowsIdentity]::GetCurrent() $principal = New-Object Security.Principal.WindowsPrincipal($identity) return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) } <# Scrie schema.txt: lista schemelor pe care le exporta backupora.exe. Fie copiaza fisierul de pe serverul vechi, fie il genereaza din CONTAFIN_ORACLE.NOM_FIRME. Se apeleaza si din fluxul complet, si din -SchemaOnly (reluarea de dupa faza 2, cand firmele exista). #> function New-SchemaFile { param( [string]$SchemaFile, [string]$SourcePath, [string]$OraHome, [string]$Service, [string]$Password, [string]$ContafinPwd ) Write-LogSection "schema.txt" if ($SourcePath) { if (Test-Path $SourcePath) { Copy-Item -Path $SourcePath -Destination $SchemaFile -Force $n = @(Get-Content $SchemaFile | Where-Object { $_.Trim() -ne '' }).Count Write-LogSuccess "Copiat de pe serverul vechi: $n linii" Write-LogWarning "Verifica-l: parolele si numele serviciului din el sunt cele de pe" Write-LogWarning "serverul VECHI. Daca difera, corecteaza-le sau regenereaza cu -SchemaOnly." return } Write-LogWarning "Nu pot citi $SourcePath. Generez schema.txt din NOM_FIRME." } Write-Log "Citesc schemele si parolele din CONTAFIN_ORACLE.NOM_FIRME..." # Formatul cerut de backupora.exe (vezi schema.tmpl): # SCHEMA;PAROLA@SERVICIU # Delimitatorul e ';', nu '|' - alegem alt separator la SELECT ca sa nu se # confunde daca o parola ar contine ';'. $sql = @" SET PAGESIZE 10000 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500 SELECT schema || '~' || parola FROM CONTAFIN_ORACLE.NOM_FIRME WHERE sters = 0 AND schema IS NOT NULL ORDER BY schema; EXIT "@ $rez = Invoke-SqlPlus -OracleHome $OraHome -ServiceName $Service ` -Username "SYSTEM" -Password $Password -SqlCommand $sql -Silent $firme = @() foreach ($linie in ($rez -split "`n")) { $linie = $linie.Trim() if ($linie -match '^([A-Z0-9_]+)~(.*)$') { $schema = $Matches[1] $parola = $Matches[2].Trim() if (-not $parola) { $parola = "ROMFASTSOFT" } $firme += "$schema;$parola@$Service" } } # CONTAFIN_ORACLE nu e in NOM_FIRME, dar trebuie exportat primul: fara el, # dump-urile de firma nu se pot reimporta (NOM_FIRME tine parolele si # maparea firma -> schema). $linii = @("CONTAFIN_ORACLE;$ContafinPwd@$Service") + ($firme | Sort-Object -Unique) Set-Content -Path $SchemaFile -Value ($linii -join "`r`n") -Encoding ASCII Write-LogSuccess "Generat: $SchemaFile (CONTAFIN_ORACLE + $($firme.Count) firme)" Write-LogWarning "Fisierul contine parole in clar - asa il cere backupora.exe." Write-LogWarning "Nu il copia in afara serverului si nu il pune in kit." if ($firme.Count -eq 0) { Write-LogWarning "NOM_FIRME nu are nicio firma activa." Write-LogWarning "In faza 1 e normal - reia cu -SchemaOnly dupa faza 2." } } try { Write-LogSection "Export zilnic Oracle (EXPORT_ORADMP)" # -SchemaOnly nu scrie in Task Scheduler, deci nu cere administrator. if (-not $SchemaOnly -and -not (Test-Administrator)) { throw "Scriptul are nevoie de drepturi de administrator (creeaza un task in Task Scheduler)." } $oraHome = Get-OracleHome -OracleHome $OracleHome Write-LogSuccess "Oracle Home: $oraHome" if (-not $BackupPath) { $BackupPath = $ExportPath } Write-Log "Director program: $ExportPath" Write-Log "Dump-uri in: $BackupPath\\" # ------------------------------------------------------------------ # Reluare doar pentru schema.txt (dupa faza 2, cand firmele exista). # Nu atinge setari.ini, backupora.exe sau task-ul. # ------------------------------------------------------------------ if ($SchemaOnly) { if (-not (Test-Path $ExportPath)) { throw "$ExportPath nu exista. Ruleaza intai scriptul fara -SchemaOnly." } New-SchemaFile -SchemaFile (Join-Path $ExportPath "schema.txt") -SourcePath $SchemaFromPath ` -OraHome $oraHome -Service $ServiceName -Password $SystemPassword ` -ContafinPwd $ContafinPassword Write-LogSection "Gata (SchemaOnly)" Close-LogFile exit 0 } # ------------------------------------------------------------------ # 1. Directoare # ------------------------------------------------------------------ Write-LogSection "Directoare" $drive = Split-Path -Qualifier $ExportPath if ($drive -and -not (Test-Path $drive)) { throw "Discul $drive nu exista. Da alta cale cu -ExportPath." } $logSubDir = Join-Path $ExportPath "LOG" foreach ($d in @($ExportPath, $logSubDir, $BackupPath)) { if (-not (Test-Path $d)) { New-Item -ItemType Directory -Path $d -Force | Out-Null Write-LogSuccess "Creat: $d" } else { Write-Log "Exista: $d" } } # Data Pump scrie cu contul serviciului Oracle, nu cu al tau. Fara # dreptul asta, expdp da ORA-39002 la deschiderea fisierului. $oracleServices = @(Get-Service -Name "Oracle*XE*" -ErrorAction SilentlyContinue | Where-Object { $_.Name -like "OracleService*" }) foreach ($svc in $oracleServices) { $cont = "NT SERVICE\$($svc.Name)" foreach ($tinta in (@($ExportPath, $BackupPath) | Select-Object -Unique)) { $null = & icacls.exe $tinta /grant "${cont}:(OI)(CI)F" /T /Q 2>&1 if ($LASTEXITCODE -eq 0) { Write-LogSuccess "Drepturi depline pentru $cont pe $tinta" } else { Write-LogWarning "icacls pentru $cont pe $tinta a returnat codul $LASTEXITCODE" } } } if ($oracleServices.Count -eq 0) { Write-LogWarning "Nu am gasit niciun serviciu OracleService*. Verifica manual drepturile pe $ExportPath." } # ------------------------------------------------------------------ # 2. backupora.exe + config.fpw # ------------------------------------------------------------------ # config.fpw e configul runtime VFP (SCREEN=OFF, RESOURCE=OFF). Fara el, # backupora.exe ar deschide o fereastra si ar astepta - inacceptabil # pentru un task programat care ruleaza fara sesiune interactiva. Write-LogSection "backupora.exe" $tintaExe = Join-Path $ExportPath "backupora.exe" foreach ($fis in @('backupora.exe', 'config.fpw', 'setari.ini.tmpl', 'schema.tmpl', 'changelog_backupora.txt')) { $sursa = Join-Path $kitBackupDir $fis $tinta = Join-Path $ExportPath $fis if (Test-Path $sursa) { Copy-Item -Path $sursa -Destination $tinta -Force $dim = [math]::Round((Get-Item $tinta).Length / 1KB, 1) Write-LogSuccess "Copiat: $fis ($dim KB)" } elseif ($fis -eq 'backupora.exe') { if (Test-Path $tinta) { Write-LogWarning "backup\backupora.exe lipseste din kit, dar exista deja $tinta. Il las cum e." } else { Write-LogError "Lipseste backup\backupora.exe din kit SI din $ExportPath." Write-LogError "Fara el, task-ul zilnic nu are ce rula." Write-LogError "Pune backupora.exe in kit, in directorul backup\, si reconstruieste kitul." throw "backupora.exe lipseste." } } else { Write-LogDebug "backup\$fis lipseste din kit - optional, se continua." } } # ------------------------------------------------------------------ # 3. setari.ini # ------------------------------------------------------------------ Write-LogSection "setari.ini" $sablon = Join-Path $kitBackupDir "setari.ini.template" $tintaIni = Join-Path $ExportPath "setari.ini" if (-not (Test-Path $sablon)) { throw "Lipseste backup\setari.ini.template din kit." } if (Test-Path $tintaIni) { $backupIni = Join-Path $ExportPath "setari.ini.bak_$stamp" Copy-Item -Path $tintaIni -Destination $backupIni -Force Write-LogWarning "setari.ini exista deja; l-am salvat ca $(Split-Path -Leaf $backupIni) inainte sa il rescriu." } # backupora.exe alege exp vs expdp dupa numele executabilului, deci # aratam direct catre expdp.exe din Oracle home. Stub-ul de 0 octeti din # directorul programului (asa apare pe instalarile vechi) nu ar exporta nimic. $expdpExe = Join-Path $oraHome "bin\expdp.exe" if (-not (Test-Path $expdpExe)) { Write-LogWarning "Nu gasesc $expdpExe. Verifica manual cheia oracleexpfile din setari.ini." } # Calea fizica a directorului Oracle DMPDIR, pentru cheile datapumpdir*. $dmpDirPath = "C:\DMPDIR" $dmpDirName = "DMPDIR" try { $r = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName ` -Username "sys" -Password $SystemPassword -AsSysdba -Silent -SqlCommand @" SET PAGESIZE 0 FEEDBACK OFF HEADING OFF VERIFY OFF SELECT 'DMPDIR=' || directory_path FROM dba_directories WHERE directory_name = 'DMPDIR'; EXIT "@ if ($r -match 'DMPDIR=(.+)') { $dmpDirPath = $Matches[1].Trim() } } catch { Write-LogDebug "Nu am putut citi DMPDIR: $($_.Exception.Message)" } $schemaFile = Join-Path $ExportPath "schema.txt" $inlocuiri = @{ '{{ORACLE_HOME}}' = $oraHome '{{DB_SERVICE}}' = $ServiceName '{{EXPORT_DIR}}' = $ExportPath '{{BACKUP_PATH}}' = $BackupPath '{{SCHEMA_FILE}}' = $schemaFile '{{RETENTION_DAYS}}' = "$RetentionDays" '{{EXPDP_EXE}}' = $expdpExe '{{DMPDIR_PATH}}' = $dmpDirPath '{{DMPDIR_NAME}}' = $dmpDirName '{{DATA_GENERARII}}' = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') } $continut = Get-Content -Path $sablon -Raw foreach ($cheie in $inlocuiri.Keys) { $continut = $continut.Replace($cheie, $inlocuiri[$cheie]) } Set-Content -Path $tintaIni -Value $continut -Encoding ASCII Write-LogSuccess "Generat: $tintaIni" $ramase = [regex]::Matches($continut, '\{\{[A-Z_]+\}\}') if ($ramase.Count -gt 0) { $lista = ($ramase | ForEach-Object { $_.Value } | Select-Object -Unique) -join ", " Write-LogWarning "Marcaje nesubstituite in setari.ini: $lista" Write-LogWarning "Completeaza-le manual sau adauga-le in tabelul de inlocuiri din scriptul asta." } # ------------------------------------------------------------------ # 4. schema.txt # ------------------------------------------------------------------ if (-not $SkipSchema) { New-SchemaFile -SchemaFile $schemaFile -SourcePath $SchemaFromPath ` -OraHome $oraHome -Service $ServiceName -Password $SystemPassword ` -ContafinPwd $ContafinPassword } else { Write-Log "Sar peste schema.txt (-SkipSchema). Completeaza-l manual in $ExportPath." } # ------------------------------------------------------------------ # 5. Obiectul Oracle DIRECTORY # ------------------------------------------------------------------ Write-LogSection "Obiectul DIRECTORY BACKUP_ORACLE" $dirSql = @" SET FEEDBACK ON SERVEROUTPUT ON VERIFY OFF CREATE OR REPLACE DIRECTORY BACKUP_ORACLE AS '$ExportPath'; GRANT READ, WRITE ON DIRECTORY BACKUP_ORACLE TO SYSTEM; GRANT READ, WRITE ON DIRECTORY BACKUP_ORACLE TO CONTAFIN_ORACLE; SET PAGESIZE 0 HEADING OFF FEEDBACK OFF SELECT 'DIRECTORY=' || directory_path FROM dba_directories WHERE directory_name = 'BACKUP_ORACLE'; EXIT "@ $rezDir = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName ` -Username "sys" -Password $SystemPassword -AsSysdba -SqlCommand $dirSql if ($rezDir -match "DIRECTORY=(.+)") { Write-LogSuccess "BACKUP_ORACLE -> $($Matches[1].Trim())" } else { Write-LogWarning "Nu am putut confirma obiectul DIRECTORY BACKUP_ORACLE." Write-LogDebug $rezDir } # ------------------------------------------------------------------ # 6. Task zilnic # ------------------------------------------------------------------ if (-not $SkipTask) { Write-LogSection "Task zilnic in Windows Task Scheduler" $existent = $null try { $existent = Get-ScheduledTask -TaskName $TaskName -ErrorAction Stop } catch { } if ($existent) { Write-LogWarning "Task-ul '$TaskName' exista deja; il inlocuiesc." Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false } $actiune = New-ScheduledTaskAction -Execute $tintaExe -WorkingDirectory $ExportPath $declansator = New-ScheduledTaskTrigger -Daily -At $TaskTime $principal = New-ScheduledTaskPrincipal -UserId $TaskUser -LogonType ServiceAccount -RunLevel Highest $setari = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries ` -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 6) Register-ScheduledTask -TaskName $TaskName -Action $actiune -Trigger $declansator ` -Principal $principal -Settings $setari ` -Description "Export zilnic al schemelor ROA in $ExportPath (backupora.exe)" | Out-Null Write-LogSuccess "Task '$TaskName' creat, zilnic la $TaskTime, sub contul $TaskUser" Write-Log "Rulare de proba: Start-ScheduledTask -TaskName ""$TaskName""" Write-Log "Stare: Get-ScheduledTaskInfo -TaskName ""$TaskName""" } else { Write-Log "Sar peste task-ul zilnic (-SkipTask)" } # ------------------------------------------------------------------ Write-LogSection "Gata" Write-Log "Director program: $ExportPath" Write-Log "Executabil: $tintaExe" Write-Log "Config: $tintaIni" if (-not $SkipSchema) { Write-Log "Scheme: $schemaFile" } Write-Log "Dump-uri in: $BackupPath\\" Write-Log "DIRECTORY: BACKUP_ORACLE" if (-not $SkipTask) { Write-Log "Task zilnic: $TaskName la $TaskTime" } Write-Log "" Write-LogWarning "Verifica manual prima rulare inainte sa pleci de la client:" Write-LogWarning " Start-ScheduledTask -TaskName ""$TaskName""" Write-LogWarning "apoi uita-te in $logSubDir si vezi ca s-au scris dump-urile." Close-LogFile exit 0 } catch { Write-LogError $_.Exception.Message Write-LogDebug $_.ScriptStackTrace Close-LogFile exit 1 }