Adauga FAZA1.cmd/FAZA2.cmd, care despart migrarea in partea care se poate face in timpul programului (contafin, obiecte SYS, sinonime, licente, IIS) si partea de seara (schemele de firma). Scripturi noi: 09 pentru licentele din SYS.AUTH_SERII/AUTH_DETALII, 10 pentru publicarea D:\ROAUPDATE in IIS, 11 pentru exportul zilnic cu backupora.exe, drop-contafin pentru reimport. backupora.exe si sabloanele sale intra in repo ca sa fie kitul autonom. Pasul 07 primeste verificarile corespunzatoare pentru licente, IIS si task. Nerulat inca pe o baza reala - vezi docs/handoff_instalare-doua-faze.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
901 lines
34 KiB
PowerShell
901 lines
34 KiB
PowerShell
#Requires -Version 5.1
|
|
|
|
<#
|
|
.SYNOPSIS
|
|
Verify ROA Oracle installation.
|
|
|
|
.DESCRIPTION
|
|
Performs comprehensive verification of the ROA Oracle installation:
|
|
- Database info (version, CDB/non-CDB, service name)
|
|
- Tablespace ROA status
|
|
- User CONTAFIN_ORACLE status and object count
|
|
- SYS custom objects status
|
|
- Public synonyms count
|
|
- Invalid objects count
|
|
- Company schemas list with object counts
|
|
|
|
.PARAMETER OracleHome
|
|
Oracle home directory. If not specified, auto-detects.
|
|
|
|
.PARAMETER ServiceName
|
|
Database service name. Default: XEPDB1
|
|
|
|
.PARAMETER SystemPassword
|
|
SYSTEM user password. Default: romfastsoft
|
|
|
|
.PARAMETER Detailed
|
|
Show detailed object counts per schema.
|
|
|
|
.PARAMETER OutputFile
|
|
Optional path to save verification report.
|
|
|
|
.EXAMPLE
|
|
.\07-verify-installation.ps1
|
|
|
|
.EXAMPLE
|
|
.\07-verify-installation.ps1 -Detailed -OutputFile "C:\reports\verification.txt"
|
|
|
|
.EXAMPLE
|
|
.\07-verify-installation.ps1 -ServiceName "ROA" -SystemPassword "mypassword"
|
|
|
|
.NOTES
|
|
File Name : 07-verify-installation.ps1
|
|
Prerequisite : ROA Oracle installation completed
|
|
Copyright 2024 : ROMFAST
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$OracleHome,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ServiceName = "XEPDB1",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$SystemPassword = "romfastsoft",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[switch]$Detailed,
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$OutputFile,
|
|
|
|
# Folosite doar ca valoare de rezerva: caile reale se citesc din
|
|
# SERVER_INFO.ROAUPDATEPATH si din obiectul DIRECTORY BACKUP_ORACLE.
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$RoaUpdatePath = "D:\ROAUPDATE",
|
|
|
|
[Parameter(Mandatory = $false)]
|
|
[string]$ExportPath = "D:\ROA\EXPORT_ORADMP"
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
# Source library functions
|
|
. "$PSScriptRoot\lib\logging-functions.ps1"
|
|
. "$PSScriptRoot\lib\oracle-functions.ps1"
|
|
|
|
# Initialize logging
|
|
$logPath = Join-Path $PSScriptRoot "..\logs\07-verify-installation_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
|
Initialize-LogFile -LogPath $logPath -ScriptName "07-verify-installation.ps1"
|
|
|
|
# Initialize report
|
|
$report = [System.Text.StringBuilder]::new()
|
|
|
|
function Add-ReportLine {
|
|
param([string]$Line)
|
|
[void]$report.AppendLine($Line)
|
|
Write-Host $Line
|
|
}
|
|
|
|
function Add-ReportSection {
|
|
param([string]$Title)
|
|
Add-ReportLine ""
|
|
Add-ReportLine ("=" * 60)
|
|
Add-ReportLine " $Title"
|
|
Add-ReportLine ("=" * 60)
|
|
Add-ReportLine ""
|
|
}
|
|
|
|
try {
|
|
Add-ReportSection "ROA Oracle Installation Verification Report"
|
|
Add-ReportLine "Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
Add-ReportLine "Computer: $env:COMPUTERNAME"
|
|
|
|
# Validate Oracle installation
|
|
$oraHome = Get-OracleHome -OracleHome $OracleHome
|
|
Write-LogSuccess "Oracle Home: $oraHome"
|
|
|
|
# Test connection
|
|
Write-Log "Testing database connection..."
|
|
if (-not (Test-OracleConnection -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword)) {
|
|
throw "Cannot connect to database. Please verify ServiceName and SystemPassword."
|
|
}
|
|
Write-LogSuccess "Database connection successful"
|
|
|
|
# Database Information
|
|
Add-ReportSection "Database Information"
|
|
|
|
$dbInfoSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 500
|
|
SELECT 'VERSION:' || version_full FROM v`$instance;
|
|
SELECT 'EDITION:' || edition FROM v`$instance;
|
|
SELECT 'INSTANCE:' || instance_name FROM v`$instance;
|
|
SELECT 'HOST:' || host_name FROM v`$instance;
|
|
SELECT 'STARTUP:' || TO_CHAR(startup_time, 'YYYY-MM-DD HH24:MI:SS') FROM v`$instance;
|
|
SELECT 'STATUS:' || status FROM v`$instance;
|
|
SELECT 'CDB:' || CDB FROM v`$database;
|
|
SELECT 'DBNAME:' || name FROM v`$database;
|
|
SELECT 'OPEN_MODE:' || open_mode FROM v`$database;
|
|
EXIT;
|
|
"@
|
|
|
|
$dbInfo = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $dbInfoSql -Silent
|
|
|
|
$dbData = @{}
|
|
foreach ($line in $dbInfo -split "`n") {
|
|
if ($line -match "^([A-Z_]+):(.*)$") {
|
|
$dbData[$Matches[1]] = $Matches[2].Trim()
|
|
}
|
|
}
|
|
|
|
Add-ReportLine "Oracle Version: $($dbData['VERSION'])"
|
|
Add-ReportLine "Edition: $($dbData['EDITION'])"
|
|
Add-ReportLine "Instance Name: $($dbData['INSTANCE'])"
|
|
Add-ReportLine "Host Name: $($dbData['HOST'])"
|
|
Add-ReportLine "Database Name: $($dbData['DBNAME'])"
|
|
Add-ReportLine "CDB Mode: $($dbData['CDB'])"
|
|
Add-ReportLine "Open Mode: $($dbData['OPEN_MODE'])"
|
|
Add-ReportLine "Instance Status: $($dbData['STATUS'])"
|
|
Add-ReportLine "Startup Time: $($dbData['STARTUP'])"
|
|
Add-ReportLine "Service Name: $ServiceName"
|
|
Add-ReportLine "Oracle Home: $oraHome"
|
|
|
|
# Container Information
|
|
$containerInfo = Test-PDB -OracleHome $oraHome -ServiceName $ServiceName -Password $SystemPassword
|
|
Add-ReportLine "Container: $($containerInfo.ContainerName)"
|
|
Add-ReportLine "Container ID: $($containerInfo.ConId)"
|
|
|
|
# Tablespace ROA Status
|
|
Add-ReportSection "Tablespace ROA Status"
|
|
|
|
$tsSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
COLUMN tablespace_name FORMAT A20
|
|
COLUMN status FORMAT A10
|
|
COLUMN contents FORMAT A10
|
|
COLUMN allocation_type FORMAT A10
|
|
|
|
SELECT tablespace_name, status, contents, allocation_type
|
|
FROM dba_tablespaces
|
|
WHERE tablespace_name = 'ROA';
|
|
|
|
COLUMN file_name FORMAT A60
|
|
COLUMN size_mb FORMAT 999,999.99
|
|
COLUMN maxsize_mb FORMAT 999,999.99
|
|
COLUMN autoextensible FORMAT A5
|
|
|
|
SELECT file_name,
|
|
ROUND(bytes/1024/1024, 2) AS size_mb,
|
|
ROUND(maxbytes/1024/1024, 2) AS maxsize_mb,
|
|
autoextensible
|
|
FROM dba_data_files
|
|
WHERE tablespace_name = 'ROA';
|
|
EXIT;
|
|
"@
|
|
|
|
$tsResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $tsSql -Silent
|
|
|
|
Add-ReportLine $tsResult
|
|
|
|
# Check if ROA tablespace exists
|
|
if ($tsResult -notmatch "ROA") {
|
|
Add-ReportLine ""
|
|
Add-ReportLine "[WARNING] Tablespace ROA not found!"
|
|
}
|
|
|
|
# CONTAFIN_ORACLE Status
|
|
Add-ReportSection "CONTAFIN_ORACLE Schema Status"
|
|
|
|
$coExistsSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
|
|
SELECT 'USER_EXISTS' FROM dba_users WHERE username = 'CONTAFIN_ORACLE';
|
|
EXIT;
|
|
"@
|
|
|
|
$coExists = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $coExistsSql -Silent
|
|
|
|
if ($coExists -match "USER_EXISTS") {
|
|
Add-ReportLine "Status: EXISTS"
|
|
|
|
$coCounts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -SchemaName "CONTAFIN_ORACLE"
|
|
|
|
$coTotal = if ($coCounts['TOTAL']) { $coCounts['TOTAL'] } else { 0 }
|
|
$coInvalid = if ($coCounts['INVALID']) { $coCounts['INVALID'] } else { 0 }
|
|
|
|
Add-ReportLine "Total Objects: $coTotal"
|
|
Add-ReportLine "Invalid Objects: $coInvalid"
|
|
|
|
if ($Detailed) {
|
|
Add-ReportLine ""
|
|
Add-ReportLine "Object counts by type:"
|
|
foreach ($key in $coCounts.Keys | Sort-Object) {
|
|
if ($key -ne 'TOTAL' -and $key -ne 'INVALID') {
|
|
Add-ReportLine " $($key.PadRight(25)) $($coCounts[$key])"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
Add-ReportLine "Status: NOT FOUND"
|
|
Add-ReportLine "[WARNING] CONTAFIN_ORACLE user does not exist!"
|
|
}
|
|
|
|
# SYS Custom Objects
|
|
Add-ReportSection "SYS Custom Objects"
|
|
|
|
$sysObjSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
COLUMN object_name FORMAT A30
|
|
COLUMN object_type FORMAT A15
|
|
COLUMN status FORMAT A10
|
|
|
|
SELECT object_name, object_type, status
|
|
FROM dba_objects
|
|
WHERE owner = 'SYS'
|
|
AND object_name IN (
|
|
'AUTH_PACK', 'AUTH_DETALII', 'AUTH_SERII', 'VAUTH_SERII',
|
|
'PACK_UPDATE', 'PACK_UTILS', 'NEWSCHEMA', 'NEWSCHEMAPOST',
|
|
'NEWSCHEMAPROGRESS', 'DMPDIR'
|
|
)
|
|
ORDER BY object_type, object_name;
|
|
EXIT;
|
|
"@
|
|
|
|
$sysResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $sysObjSql -AsSysdba -Silent
|
|
|
|
Add-ReportLine $sysResult
|
|
|
|
# Dictionary Grants required by PACK_DIAG_SPATIU
|
|
Add-ReportSection "Dictionary Grants (PACK_DIAG_SPATIU)"
|
|
|
|
$dictSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 200
|
|
SELECT 'GRANTED:' || table_name
|
|
FROM dba_tab_privs
|
|
WHERE grantee = 'CONTAFIN_ORACLE'
|
|
AND grantor = 'SYS'
|
|
AND privilege = 'SELECT'
|
|
ORDER BY table_name;
|
|
EXIT;
|
|
"@
|
|
|
|
$dictResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $dictSql -Silent
|
|
|
|
$granted = @()
|
|
foreach ($line in $dictResult -split "`n") {
|
|
if ($line -match "^GRANTED:(.+)$") { $granted += $Matches[1].Trim() }
|
|
}
|
|
|
|
# Lista din sql\sys-grants.sql, sectiunea [5/5]
|
|
$expectedDict = @(
|
|
'DBA_DATA_FILES', 'DBA_FREE_SPACE', 'DBA_TEMP_FILES', 'DBA_SEGMENTS',
|
|
'DBA_TAB_STATS_HISTORY', 'DBA_SCHEDULER_JOB_RUN_DETAILS', 'DBA_RECYCLEBIN',
|
|
'V_$INSTANCE', 'V_$DATABASE', 'V_$PARAMETER', 'V_$TRANSACTION',
|
|
'V_$TEMP_SPACE_HEADER', 'V_$FLASH_RECOVERY_AREA_USAGE',
|
|
'DBA_TABLESPACES', 'V_$VERSION',
|
|
'DBA_LOBS', 'DBA_LOB_PARTITIONS', 'DBA_INDEXES'
|
|
)
|
|
|
|
$missingDict = $expectedDict | Where-Object { $granted -notcontains $_ }
|
|
|
|
Add-ReportLine "Expected grants: $($expectedDict.Count)"
|
|
Add-ReportLine "Present grants: $($expectedDict.Count - $missingDict.Count)"
|
|
|
|
if ($missingDict.Count -eq 0) {
|
|
Add-ReportLine "Status: OK"
|
|
}
|
|
else {
|
|
Add-ReportLine "Status: INCOMPLETE"
|
|
Add-ReportLine ""
|
|
Add-ReportLine "Missing:"
|
|
foreach ($m in $missingDict) { Add-ReportLine " - $m" }
|
|
Add-ReportLine ""
|
|
Add-ReportLine "[WARNING] CONTAFIN_ORACLE.PACK_DIAG_SPATIU va ramane INVALID."
|
|
Add-ReportLine " Rolul DBA nu se aplica in pachetele cu drepturi de definitor."
|
|
Add-ReportLine " Rezolvare: sqlplus sys/<parola>@$ServiceName as sysdba @sql\sys-grants.sql"
|
|
}
|
|
|
|
# Public Synonyms Count
|
|
Add-ReportSection "Public Synonyms"
|
|
|
|
$synSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
|
|
SELECT 'TOTAL_SYNONYMS:' || COUNT(*) FROM dba_synonyms WHERE owner = 'PUBLIC';
|
|
SELECT 'CO_SYNONYMS:' || COUNT(*) FROM dba_synonyms WHERE owner = 'PUBLIC' AND table_owner = 'CONTAFIN_ORACLE';
|
|
SELECT 'SYS_SYNONYMS:' || COUNT(*) FROM dba_synonyms WHERE owner = 'PUBLIC' AND table_owner = 'SYS' AND table_name LIKE 'AUTH%';
|
|
EXIT;
|
|
"@
|
|
|
|
$synResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $synSql -Silent
|
|
|
|
$synData = @{}
|
|
foreach ($line in $synResult -split "`n") {
|
|
if ($line -match "^([A-Z_]+):(\d+)\s*$") {
|
|
$synData[$Matches[1]] = [int]$Matches[2]
|
|
}
|
|
}
|
|
|
|
Add-ReportLine "Total public synonyms: $($synData['TOTAL_SYNONYMS'])"
|
|
Add-ReportLine "CONTAFIN_ORACLE synonyms: $($synData['CO_SYNONYMS'])"
|
|
Add-ReportLine "SYS AUTH synonyms: $($synData['SYS_SYNONYMS'])"
|
|
|
|
# All Invalid Objects
|
|
Add-ReportSection "Invalid Objects Summary"
|
|
|
|
$invalidSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
COLUMN owner FORMAT A20
|
|
COLUMN invalid_count FORMAT 999,999
|
|
|
|
SELECT owner, COUNT(*) AS invalid_count
|
|
FROM dba_objects
|
|
WHERE status = 'INVALID'
|
|
AND owner NOT IN ('SYS', 'SYSTEM', 'OUTLN', 'DBSNMP', 'XDB', 'ORDSYS',
|
|
'ORDDATA', 'MDSYS', 'CTXSYS', 'WMSYS', 'APEX_PUBLIC_USER')
|
|
GROUP BY owner
|
|
ORDER BY invalid_count DESC;
|
|
EXIT;
|
|
"@
|
|
|
|
$invalidResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $invalidSql -Silent
|
|
|
|
if ($invalidResult.Trim() -eq "" -or $invalidResult -match "no rows selected") {
|
|
Add-ReportLine "No invalid objects found in application schemas."
|
|
}
|
|
else {
|
|
Add-ReportLine $invalidResult
|
|
}
|
|
|
|
# Company Schemas
|
|
Add-ReportSection "Company Schemas"
|
|
|
|
# Get company list from NOM_FIRME
|
|
$companySql = @"
|
|
SET PAGESIZE 1000 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 200
|
|
SELECT schema FROM CONTAFIN_ORACLE.NOM_FIRME WHERE sters = 0 AND schema IS NOT NULL ORDER BY schema;
|
|
EXIT;
|
|
"@
|
|
|
|
$companyList = @()
|
|
try {
|
|
$companyResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $companySql -Silent
|
|
|
|
foreach ($line in $companyResult -split "`n") {
|
|
$schema = $line.Trim()
|
|
if ($schema -match "^[A-Z0-9_]+$") {
|
|
$companyList += $schema
|
|
}
|
|
}
|
|
}
|
|
catch {
|
|
Add-ReportLine "[WARNING] Could not query NOM_FIRME table"
|
|
}
|
|
|
|
Add-ReportLine "Companies registered in NOM_FIRME: $($companyList.Count)"
|
|
Add-ReportLine ""
|
|
|
|
if ($companyList.Count -gt 0) {
|
|
# Check which schemas exist
|
|
$existingSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 200
|
|
SELECT username FROM dba_users WHERE username NOT IN (
|
|
'SYS', 'SYSTEM', 'OUTLN', 'DBSNMP', 'XDB', 'ORDSYS', 'ORDDATA', 'MDSYS',
|
|
'CTXSYS', 'WMSYS', 'APEX_PUBLIC_USER', 'CONTAFIN_ORACLE', 'ANONYMOUS',
|
|
'APEX_040200', 'APEX_050000', 'APPQOSSYS', 'AUDSYS', 'DIP', 'DVF', 'DVSYS',
|
|
'FLOWS_FILES', 'GGSYS', 'GSMADMIN_INTERNAL', 'GSMCATUSER', 'GSMUSER',
|
|
'LBACSYS', 'MDDATA', 'OJVMSYS', 'OLAPSYS', 'ORACLE_OCM', 'REMOTE_SCHEDULER_AGENT',
|
|
'SI_INFORMTN_SCHEMA', 'SPATIAL_CSW_ADMIN_USR', 'SPATIAL_WFS_ADMIN_USR',
|
|
'SYSBACKUP', 'SYSDG', 'SYSKM', 'SYSRAC', 'XS`$NULL'
|
|
) ORDER BY username;
|
|
EXIT;
|
|
"@
|
|
|
|
$existingResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $existingSql -Silent
|
|
|
|
$existingSchemas = @()
|
|
foreach ($line in $existingResult -split "`n") {
|
|
$schema = $line.Trim()
|
|
if ($schema -match "^[A-Z0-9_]+$") {
|
|
$existingSchemas += $schema
|
|
}
|
|
}
|
|
|
|
Add-ReportLine "Existing company schemas: $($existingSchemas.Count)"
|
|
Add-ReportLine ""
|
|
|
|
# Show details
|
|
Add-ReportLine ("Schema".PadRight(25) + "Status".PadRight(12) + "Objects".PadRight(10) + "Invalid")
|
|
Add-ReportLine ("-" * 60)
|
|
|
|
foreach ($schema in $companyList) {
|
|
$status = if ($existingSchemas -contains $schema) { "EXISTS" } else { "MISSING" }
|
|
|
|
if ($status -eq "EXISTS") {
|
|
$counts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -SchemaName $schema
|
|
|
|
$total = if ($counts['TOTAL']) { $counts['TOTAL'] } else { 0 }
|
|
$invalid = if ($counts['INVALID']) { $counts['INVALID'] } else { 0 }
|
|
|
|
Add-ReportLine ("$schema".PadRight(25) + "$status".PadRight(12) + "$total".PadRight(10) + "$invalid")
|
|
}
|
|
else {
|
|
Add-ReportLine ("$schema".PadRight(25) + "$status".PadRight(12) + "-".PadRight(10) + "-")
|
|
}
|
|
}
|
|
|
|
# Check for orphan schemas (exist in DB but not in NOM_FIRME)
|
|
$orphanSchemas = $existingSchemas | Where-Object { $companyList -notcontains $_ }
|
|
if ($orphanSchemas.Count -gt 0) {
|
|
Add-ReportLine ""
|
|
Add-ReportLine "Orphan schemas (not in NOM_FIRME):"
|
|
foreach ($schema in $orphanSchemas) {
|
|
$counts = Get-SchemaObjectCount -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Password $SystemPassword -SchemaName $schema
|
|
|
|
$total = if ($counts['TOTAL']) { $counts['TOTAL'] } else { 0 }
|
|
Add-ReportLine " - $schema ($total objects)"
|
|
}
|
|
}
|
|
}
|
|
|
|
# Company Template + SMTP
|
|
# ------------------------------------------------------------------------
|
|
# SYS.NEWSCHEMA (si 06-add-company.ps1) creeaza o firma noua importand
|
|
# sablonul FIRMANOUA.dmp din directorul Oracle DMPDIR. Daca fisierul nu e
|
|
# acolo, adaugarea de firme noi pica in DBMS_DATAPUMP.ADD_FILE - dar abia
|
|
# peste luni, cand clientul chiar adauga o firma. Il verificam la instalare.
|
|
Add-ReportSection "Company Template + SMTP"
|
|
|
|
# Lipsa sablonului e un defect real (blocheaza adaugarea de firme), deci
|
|
# intra in $issues si in codul de iesire. SMTP nesetat ramane doar o nota:
|
|
# nu toti clientii folosesc notificarile pe email.
|
|
$extraIssues = @()
|
|
|
|
$tmplSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 200
|
|
SELECT 'DMPDIR_PATH:' || directory_path FROM dba_directories WHERE directory_name = 'DMPDIR';
|
|
SELECT 'SMTP_OUT:' || NVL(value, '<nesetat>') FROM v`$parameter WHERE name = 'smtp_out_server';
|
|
EXIT;
|
|
"@
|
|
|
|
$tmplResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $tmplSql -AsSysdba -Silent
|
|
|
|
$dmpDirPath = $null
|
|
$smtpOut = $null
|
|
foreach ($line in $tmplResult -split "`n") {
|
|
$line = $line.Trim()
|
|
if ($line -match "^DMPDIR_PATH:(.+)$") { $dmpDirPath = $Matches[1].Trim() }
|
|
if ($line -match "^SMTP_OUT:(.+)$") { $smtpOut = $Matches[1].Trim() }
|
|
}
|
|
|
|
if (-not $dmpDirPath) {
|
|
Add-ReportLine "[WARNING] Directorul Oracle DMPDIR nu exista."
|
|
$extraIssues += "Oracle directory DMPDIR missing"
|
|
}
|
|
else {
|
|
Add-ReportLine "DMPDIR: $dmpDirPath"
|
|
$tmplPath = Join-Path $dmpDirPath "FIRMANOUA.dmp"
|
|
if (Test-Path $tmplPath) {
|
|
$sizeMb = [math]::Round((Get-Item $tmplPath).Length / 1MB, 1)
|
|
Add-ReportLine "FIRMANOUA.dmp: OK ($sizeMb MB)"
|
|
}
|
|
else {
|
|
Add-ReportLine "FIRMANOUA.dmp: LIPSA"
|
|
Add-ReportLine ""
|
|
Add-ReportLine "[WARNING] Fara sablonul FIRMANOUA.dmp in DMPDIR, adaugarea unei firme"
|
|
Add-ReportLine " noi (SYS.NEWSCHEMA / 06-add-company.ps1) va esua la"
|
|
Add-ReportLine " DBMS_DATAPUMP.ADD_FILE. Copiaza-l in $dmpDirPath."
|
|
Add-ReportLine " Sursa: LXC 108, container oracle-xe,"
|
|
Add-ReportLine " /tmp/oracle-import-roa2/firmanoua.dmp"
|
|
$extraIssues += "FIRMANOUA.dmp missing from DMPDIR (adding new companies will fail)"
|
|
}
|
|
}
|
|
|
|
Add-ReportLine ""
|
|
if ($smtpOut -and $smtpOut -ne '<nesetat>') {
|
|
Add-ReportLine "SMTP_OUT_SERVER: $smtpOut"
|
|
}
|
|
else {
|
|
Add-ReportLine "SMTP_OUT_SERVER: NESETAT"
|
|
Add-ReportLine "[NOTA] UTL_MAIL.SEND va da ORA-29278/29279 pana cand e setat."
|
|
Add-ReportLine " Ruleaza 08-post-install-config.ps1 -EmailSmtp <server>."
|
|
}
|
|
|
|
# Network ACL Status
|
|
Add-ReportSection "Network ACL Status"
|
|
|
|
$aclSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
COLUMN acl FORMAT A30
|
|
COLUMN principal FORMAT A20
|
|
COLUMN privilege FORMAT A15
|
|
COLUMN is_grant FORMAT A8
|
|
|
|
SELECT acl, principal, privilege, is_grant
|
|
FROM dba_network_acl_privileges
|
|
WHERE principal = 'CONTAFIN_ORACLE';
|
|
EXIT;
|
|
"@
|
|
|
|
$aclResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $aclSql -AsSysdba -Silent
|
|
|
|
if ($aclResult.Trim() -eq "" -or $aclResult -match "no rows selected") {
|
|
Add-ReportLine "No ACL configured for CONTAFIN_ORACLE"
|
|
}
|
|
else {
|
|
Add-ReportLine $aclResult
|
|
}
|
|
|
|
# Context Status
|
|
Add-ReportSection "Context Status"
|
|
|
|
$ctxSql = @"
|
|
SET PAGESIZE 100 FEEDBACK OFF VERIFY OFF HEADING ON ECHO OFF LINESIZE 200
|
|
COLUMN namespace FORMAT A20
|
|
COLUMN schema FORMAT A25
|
|
COLUMN package FORMAT A25
|
|
|
|
SELECT namespace, schema, package
|
|
FROM dba_context
|
|
WHERE namespace = 'SESIUNE';
|
|
EXIT;
|
|
"@
|
|
|
|
$ctxResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $ctxSql -Silent
|
|
|
|
if ($ctxResult.Trim() -eq "" -or $ctxResult -match "no rows selected") {
|
|
Add-ReportLine "SESIUNE context not found"
|
|
}
|
|
else {
|
|
Add-ReportLine $ctxResult
|
|
}
|
|
|
|
# ------------------------------------------------------------------------
|
|
# Licente
|
|
# ------------------------------------------------------------------------
|
|
# AUTH_DETALII tine Id-ul de client, AUTH_SERII seriile propriu-zise pe
|
|
# care AUTH_PACK le decripteaza. Pasul 08 scrie doar Id-ul; seriile vin
|
|
# de pe serverul vechi prin 09-copy-licenses.ps1. O baza cu Id de client
|
|
# dar fara serii e cazul tipic de migrare facuta pe jumatate: aplicatia
|
|
# porneste si apoi refuza fiecare modul.
|
|
Add-ReportSection "Licente"
|
|
|
|
$licSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 300
|
|
SELECT 'SERII:' || COUNT(*) FROM sys.auth_serii;
|
|
SELECT 'SERII_ACTIVE:' || COUNT(*) FROM sys.auth_serii WHERE sters = 0;
|
|
SELECT 'IDCLIENT:' || NVL(MAX(detalii), '<nesetat>') FROM sys.auth_detalii;
|
|
SELECT 'EXPIRA:' || nume || '|' || TO_CHAR(data_val, 'YYYY-MM-DD')
|
|
FROM sys.vauth_serii
|
|
WHERE data_val IS NOT NULL AND data_val < SYSDATE + 60
|
|
ORDER BY data_val;
|
|
EXIT;
|
|
"@
|
|
|
|
$licResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $licSql -AsSysdba -Silent
|
|
|
|
$nrSerii = 0
|
|
$nrSeriiActive = 0
|
|
$idClient = '<nesetat>'
|
|
$expiraCurand = @()
|
|
foreach ($line in $licResult -split "`n") {
|
|
$line = $line.Trim()
|
|
if ($line -match "^SERII:(\d+)$") { $nrSerii = [int]$Matches[1] }
|
|
if ($line -match "^SERII_ACTIVE:(\d+)$") { $nrSeriiActive = [int]$Matches[1] }
|
|
if ($line -match "^IDCLIENT:(.+)$") { $idClient = $Matches[1].Trim() }
|
|
if ($line -match "^EXPIRA:(.+)\|(.+)$") { $expiraCurand += "$($Matches[1].Trim()) expira la $($Matches[2].Trim())" }
|
|
}
|
|
|
|
Add-ReportLine "Id client (AUTH_DETALII): $idClient"
|
|
Add-ReportLine "Serii de licenta: $nrSerii ($nrSeriiActive active)"
|
|
|
|
if ($nrSeriiActive -eq 0) {
|
|
Add-ReportLine ""
|
|
Add-ReportLine "[WARNING] Nicio serie activa in SYS.AUTH_SERII."
|
|
Add-ReportLine " La un client NOU e normal - licentele se adauga ulterior."
|
|
Add-ReportLine " La o MIGRARE inseamna ca pasul 09 nu a rulat sau a esuat:"
|
|
Add-ReportLine " Run.cmd 09-copy-licenses.ps1 -OldHost <gazda> -OldSysPassword <parola> -Replace"
|
|
$extraIssues += "No active license series in SYS.AUTH_SERII"
|
|
}
|
|
|
|
if ($expiraCurand.Count -gt 0) {
|
|
Add-ReportLine ""
|
|
Add-ReportLine "[NOTA] Licente care expira in urmatoarele 60 de zile:"
|
|
foreach ($e in $expiraCurand) { Add-ReportLine " - $e" }
|
|
}
|
|
|
|
# ------------------------------------------------------------------------
|
|
# Oglinda de update + IIS
|
|
# ------------------------------------------------------------------------
|
|
# Doua etaje: serverul trage modulele de la ROMFAST in ROAUPDATE (jobul
|
|
# UPDATEROA_ZILNIC), statiile le iau de la serverul clientului prin IIS.
|
|
# Daca al doilea etaj lipseste, primul merge si nu se vede nimic - statiile
|
|
# raman pe versiunile vechi la nesfarsit.
|
|
Add-ReportSection "Actualizarea aplicatiilor"
|
|
|
|
$caleRoaUpdate = $RoaUpdatePath
|
|
$siSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 300
|
|
SELECT 'ROAUPDATEPATH:' || value FROM contafin_oracle.server_info WHERE name = 'ROAUPDATEPATH';
|
|
SELECT 'UPD_URL_APP:' || value FROM contafin_oracle.server_info WHERE name = 'UPD_URL_APP';
|
|
EXIT;
|
|
"@
|
|
$siResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYSTEM" -Password $SystemPassword -SqlCommand $siSql -Silent
|
|
|
|
$urlApp = $null
|
|
foreach ($line in $siResult -split "`n") {
|
|
$line = $line.Trim()
|
|
if ($line -match "^ROAUPDATEPATH:(.+)$") { $caleRoaUpdate = $Matches[1].Trim() }
|
|
if ($line -match "^UPD_URL_APP:(.+)$") { $urlApp = $Matches[1].Trim() }
|
|
}
|
|
|
|
Add-ReportLine "SERVER_INFO.ROAUPDATEPATH: $caleRoaUpdate"
|
|
Add-ReportLine "SERVER_INFO.UPD_URL_APP: $(if ($urlApp) { $urlApp } else { '<nesetat>' })"
|
|
|
|
if (-not $urlApp) {
|
|
$extraIssues += "SERVER_INFO.UPD_URL_APP not set (server cannot pull updates)"
|
|
}
|
|
|
|
if (-not (Test-Path $caleRoaUpdate)) {
|
|
Add-ReportLine "Directorul fizic: LIPSA"
|
|
Add-ReportLine "[WARNING] $caleRoaUpdate nu exista. Ruleaza 10-setup-roaupdate-iis.ps1."
|
|
$extraIssues += "ROAUPDATE directory missing: $caleRoaUpdate"
|
|
}
|
|
else {
|
|
$caleArhiva = Join-Path $caleRoaUpdate "_ARHIVE"
|
|
$dirModule = @(Get-ChildItem -Path $caleRoaUpdate -Directory -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Name -notlike "_*" })
|
|
$dirArhiva = @(Get-ChildItem -Path $caleArhiva -Directory -ErrorAction SilentlyContinue)
|
|
|
|
Add-ReportLine "Directorul fizic: OK"
|
|
Add-ReportLine "Directoare de modul: $($dirModule.Count)"
|
|
Add-ReportLine "Directoare _ARHIVE: $($dirArhiva.Count)"
|
|
|
|
if ($dirModule.Count -eq 0) {
|
|
Add-ReportLine "[WARNING] Nu exista directoare de modul in $caleRoaUpdate."
|
|
Add-ReportLine " Ruleaza 10-setup-roaupdate-iis.ps1."
|
|
$extraIssues += "No module directories under $caleRoaUpdate"
|
|
}
|
|
|
|
# Cate module au macar un ZIP si cat de proaspata e oglinda. Asta e
|
|
# masura practica a "aplicatiile sunt actualizate": daca nu s-a
|
|
# descarcat nimic, sau ce e acolo e vechi de luni, actualizarea nu
|
|
# merge indiferent ce spune jobul.
|
|
$moduleCuZip = 0
|
|
$celMaiNou = $null
|
|
foreach ($d in $dirArhiva) {
|
|
$zips = @(Get-ChildItem -Path $d.FullName -Filter "*.zip" -File -ErrorAction SilentlyContinue)
|
|
if ($zips.Count -gt 0) {
|
|
$moduleCuZip++
|
|
$max = ($zips | Sort-Object LastWriteTime -Descending | Select-Object -First 1).LastWriteTime
|
|
if (-not $celMaiNou -or $max -gt $celMaiNou) { $celMaiNou = $max }
|
|
}
|
|
}
|
|
|
|
Add-ReportLine "Module cu ZIP-uri in arhiva: $moduleCuZip"
|
|
if ($celMaiNou) {
|
|
$zile = [math]::Round(((Get-Date) - $celMaiNou).TotalDays)
|
|
Add-ReportLine "Cel mai recent ZIP: $($celMaiNou.ToString('yyyy-MM-dd')) (acum $zile zile)"
|
|
if ($zile -gt 30) {
|
|
Add-ReportLine "[NOTA] Oglinda nu s-a mai improspatat de peste 30 de zile."
|
|
Add-ReportLine " Verifica jobul UPDATEROA_ZILNIC si accesul la $urlApp."
|
|
}
|
|
}
|
|
else {
|
|
Add-ReportLine "Cel mai recent ZIP: niciunul"
|
|
Add-ReportLine "[NOTA] Oglinda e goala. La o instalare noua e normal - se umple"
|
|
Add-ReportLine " la prima rulare a jobului UPDATEROA_ZILNIC."
|
|
}
|
|
}
|
|
|
|
# Publicarea in IIS
|
|
$urlLocal = "http://localhost/roaupdate/"
|
|
try {
|
|
$respIis = Invoke-WebRequest -Uri $urlLocal -UseBasicParsing -TimeoutSec 10
|
|
Add-ReportLine "IIS $($urlLocal): OK ($($respIis.StatusCode))"
|
|
}
|
|
catch {
|
|
Add-ReportLine "IIS $($urlLocal): NU RASPUNDE"
|
|
Add-ReportLine "[WARNING] Statiile de lucru nu pot lua actualizari de la serverul asta."
|
|
Add-ReportLine " Ruleaza 10-setup-roaupdate-iis.ps1."
|
|
$extraIssues += "IIS mirror at $urlLocal not responding"
|
|
}
|
|
|
|
# Joburile de actualizare
|
|
$jobSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 300
|
|
SELECT 'JOB:' || job_name || '|' || enabled || '|' || state ||
|
|
'|' || NVL(TO_CHAR(last_start_date, 'YYYY-MM-DD HH24:MI'), 'niciodata')
|
|
FROM dba_scheduler_jobs
|
|
WHERE owner = 'CONTAFIN_ORACLE'
|
|
AND job_name IN ('UPDATEROA_ZILNIC', 'UPDATERTVAI_ZILNIC')
|
|
ORDER BY job_name;
|
|
EXIT;
|
|
"@
|
|
$jobResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $jobSql -AsSysdba -Silent
|
|
|
|
Add-ReportLine ""
|
|
$joburiGasite = 0
|
|
foreach ($line in $jobResult -split "`n") {
|
|
if ($line.Trim() -match "^JOB:([^|]+)\|([^|]+)\|([^|]+)\|(.+)$") {
|
|
$joburiGasite++
|
|
Add-ReportLine ("{0,-20} activat={1,-6} stare={2,-10} ultima rulare: {3}" -f `
|
|
$Matches[1].Trim(), $Matches[2].Trim(), $Matches[3].Trim(), $Matches[4].Trim())
|
|
}
|
|
}
|
|
if ($joburiGasite -eq 0) {
|
|
Add-ReportLine "Joburile de actualizare: LIPSA"
|
|
Add-ReportLine "[WARNING] Ruleaza 08-post-install-config.ps1."
|
|
$extraIssues += "Update scheduler jobs missing"
|
|
}
|
|
|
|
# ------------------------------------------------------------------------
|
|
# Exportul zilnic
|
|
# ------------------------------------------------------------------------
|
|
Add-ReportSection "Export zilnic (EXPORT_ORADMP)"
|
|
|
|
$expSql = @"
|
|
SET PAGESIZE 0 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF LINESIZE 300
|
|
SELECT 'BACKUPDIR:' || directory_path FROM dba_directories WHERE directory_name = 'BACKUP_ORACLE';
|
|
EXIT;
|
|
"@
|
|
$expResult = Invoke-SqlPlus -OracleHome $oraHome -ServiceName $ServiceName `
|
|
-Username "SYS" -Password $SystemPassword -SqlCommand $expSql -AsSysdba -Silent
|
|
|
|
$caleExport = $ExportPath
|
|
if ($expResult -match "BACKUPDIR:(.+)") { $caleExport = $Matches[1].Trim() }
|
|
|
|
Add-ReportLine "DIRECTORY BACKUP_ORACLE: $(if ($expResult -match 'BACKUPDIR:') { $caleExport } else { 'LIPSA' })"
|
|
|
|
if ($expResult -notmatch "BACKUPDIR:") {
|
|
$extraIssues += "Oracle directory BACKUP_ORACLE missing"
|
|
}
|
|
|
|
if (-not (Test-Path $caleExport)) {
|
|
Add-ReportLine "Directorul fizic: LIPSA ($caleExport)"
|
|
Add-ReportLine "[WARNING] Ruleaza 11-setup-backup-export.ps1."
|
|
$extraIssues += "Export directory missing: $caleExport"
|
|
}
|
|
else {
|
|
Add-ReportLine "Directorul fizic: OK"
|
|
|
|
foreach ($f in @('backupora.exe', 'setari.ini', 'schema.txt')) {
|
|
$cale = Join-Path $caleExport $f
|
|
if (Test-Path $cale) {
|
|
if ($f -eq 'schema.txt') {
|
|
$nrScheme = @(Get-Content $cale | Where-Object { $_.Trim() -ne '' }).Count
|
|
Add-ReportLine ("{0,-28} OK ({1} scheme)" -f "${f}:", $nrScheme)
|
|
} else {
|
|
Add-ReportLine ("{0,-28} OK" -f "${f}:")
|
|
}
|
|
}
|
|
else {
|
|
Add-ReportLine ("{0,-28} LIPSA" -f "${f}:")
|
|
$extraIssues += "$f missing from $caleExport"
|
|
}
|
|
}
|
|
|
|
$dumpuri = @(Get-ChildItem -Path $caleExport -Filter "*.dmp" -File -ErrorAction SilentlyContinue)
|
|
if ($dumpuri.Count -gt 0) {
|
|
$celMaiNouDmp = ($dumpuri | Sort-Object LastWriteTime -Descending | Select-Object -First 1)
|
|
$zileDmp = [math]::Round(((Get-Date) - $celMaiNouDmp.LastWriteTime).TotalDays)
|
|
Add-ReportLine "Dump-uri prezente: $($dumpuri.Count), cel mai recent acum $zileDmp zile"
|
|
if ($zileDmp -gt 2) {
|
|
Add-ReportLine "[NOTA] Ultimul export e vechi de $zileDmp zile. Verifica task-ul."
|
|
}
|
|
}
|
|
else {
|
|
Add-ReportLine "Dump-uri prezente: niciunul (exportul nu a rulat inca)"
|
|
}
|
|
}
|
|
|
|
# Task-ul din Windows
|
|
$task = $null
|
|
try { $task = Get-ScheduledTask -TaskName "ROA Export Oracle" -ErrorAction Stop } catch { }
|
|
if ($task) {
|
|
$info = Get-ScheduledTaskInfo -TaskName "ROA Export Oracle"
|
|
$ultima = if ($info.LastRunTime -and $info.LastRunTime.Year -gt 1999) {
|
|
$info.LastRunTime.ToString('yyyy-MM-dd HH:mm')
|
|
} else { 'niciodata' }
|
|
Add-ReportLine "Task 'ROA Export Oracle': $($task.State), ultima rulare: $ultima (cod $($info.LastTaskResult))"
|
|
}
|
|
else {
|
|
Add-ReportLine "Task 'ROA Export Oracle': LIPSA"
|
|
Add-ReportLine "[WARNING] Nu exista task zilnic de export. Ruleaza 11-setup-backup-export.ps1."
|
|
$extraIssues += "Scheduled task 'ROA Export Oracle' missing"
|
|
}
|
|
|
|
# Final Summary
|
|
Add-ReportSection "Verification Summary"
|
|
|
|
$issues = @()
|
|
|
|
# Check for issues
|
|
if ($tsResult -notmatch "ROA") {
|
|
$issues += "Tablespace ROA not found"
|
|
}
|
|
|
|
if ($coExists -notmatch "USER_EXISTS") {
|
|
$issues += "CONTAFIN_ORACLE user not found"
|
|
}
|
|
elseif ($coCounts -and $coCounts['INVALID'] -gt 0) {
|
|
$issues += "CONTAFIN_ORACLE has $($coCounts['INVALID']) invalid objects"
|
|
}
|
|
|
|
if ($synData['CO_SYNONYMS'] -eq 0) {
|
|
$issues += "No public synonyms for CONTAFIN_ORACLE"
|
|
}
|
|
|
|
$missingCompanies = $companyList | Where-Object { $existingSchemas -notcontains $_ }
|
|
if ($missingCompanies.Count -gt 0) {
|
|
$issues += "$($missingCompanies.Count) company schemas are missing"
|
|
}
|
|
|
|
if ($extraIssues.Count -gt 0) {
|
|
$issues += $extraIssues
|
|
}
|
|
|
|
if ($issues.Count -eq 0) {
|
|
Add-ReportLine "[OK] All checks passed!"
|
|
Add-ReportLine ""
|
|
Add-ReportLine "The ROA Oracle installation appears to be complete and functional."
|
|
}
|
|
else {
|
|
Add-ReportLine "[WARNING] Issues found:"
|
|
Add-ReportLine ""
|
|
foreach ($issue in $issues) {
|
|
Add-ReportLine " - $issue"
|
|
}
|
|
}
|
|
|
|
Add-ReportLine ""
|
|
Add-ReportLine ("=" * 60)
|
|
Add-ReportLine " End of Verification Report"
|
|
Add-ReportLine ("=" * 60)
|
|
|
|
# Save report if requested
|
|
if ($OutputFile) {
|
|
Set-Content -Path $OutputFile -Value $report.ToString() -Encoding UTF8
|
|
Write-LogSuccess "Report saved to: $OutputFile"
|
|
}
|
|
|
|
Close-LogFile -Success ($issues.Count -eq 0)
|
|
exit $(if ($issues.Count -eq 0) { 0 } else { 1 })
|
|
}
|
|
catch {
|
|
Write-LogError "Verification failed: $_"
|
|
Write-LogError $_.ScriptStackTrace
|
|
Close-LogFile -Success $false
|
|
exit 1
|
|
}
|