Public Access
174 lines
6.7 KiB
PowerShell
174 lines
6.7 KiB
PowerShell
# Collects everything needed to diagnose "it isn't working" into one text file
|
|||
|
|
# on the Desktop. Passwords are masked. Called by report.bat.
|
||
|
|
|
||
|
|
$scriptRoot = Split-Path -Parent $PSCommandPath
|
||
|
|
$stamp = Get-Date -Format "yyyyMMdd-HHmm"
|
||
|
|
$desktop = [Environment]::GetFolderPath("Desktop")
|
||
|
|
if (-not $desktop) { $desktop = $scriptRoot }
|
||
|
|
$outFile = Join-Path $desktop "MelissaUploader-Report-$stamp.txt"
|
||
|
|
|
||
|
|
$lines = New-Object System.Collections.ArrayList
|
||
|
|
function Add-Line($text) { [void]$lines.Add([string]$text) }
|
||
|
|
function Add-Head($text) {
|
||
|
|
Add-Line ""
|
||
|
|
Add-Line ("=" * 60)
|
||
|
|
Add-Line " $text"
|
||
|
|
Add-Line ("=" * 60)
|
||
|
|
}
|
||
|
|
|
||
|
|
Add-Line "Melissa Uploader report"
|
||
|
|
Add-Line "Taken : $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
||
|
|
Add-Line "PC : $env:COMPUTERNAME"
|
||
|
|
Add-Line "User : $env:USERNAME"
|
||
|
|
Add-Line "Folder : $scriptRoot"
|
||
|
|
Add-Line "Windows : $([Environment]::OSVersion.VersionString)"
|
||
|
|
Add-Line "PowerShell: $($PSVersionTable.PSVersion)"
|
||
|
|
|
||
|
|
# -- Which version of the tool is installed -----------------------------------
|
||
|
|
Add-Head "Version"
|
||
|
|
$versionFile = Join-Path $scriptRoot "VERSION.txt"
|
||
|
|
if (Test-Path $versionFile) {
|
||
|
|
Add-Line "VERSION.txt: $((Get-Content $versionFile -Raw).Trim())"
|
||
|
|
} else {
|
||
|
|
Add-Line "VERSION.txt: MISSING"
|
||
|
|
Add-Line ">> This copy is older than 2026-08-26. It does not have the setup"
|
||
|
|
Add-Line ">> wizard. Whoever maintains this needs to copy the new files over."
|
||
|
|
}
|
||
|
|
|
||
|
|
# -- Which files are present --------------------------------------------------
|
||
|
|
Add-Head "Files in the folder"
|
||
|
|
$expected = @("engine.ps1", "run-all.bat", "run-all.ps1", "run.bat", "setup.bat",
|
||
|
|
"setup-entity.bat", "Setup-Entity.ps1", "Get-WinSCP.ps1", "Get-Report.ps1")
|
||
|
|
foreach ($name in $expected) {
|
||
|
|
$path = Join-Path $scriptRoot $name
|
||
|
|
if (Test-Path $path) {
|
||
|
|
$item = Get-Item $path
|
||
|
|
Add-Line (" {0,-20} {1} {2,8} bytes" -f $name, $item.LastWriteTime.ToString("yyyy-MM-dd HH:mm"), $item.Length)
|
||
|
|
} else {
|
||
|
|
Add-Line (" {0,-20} MISSING" -f $name)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# -- WinSCP -------------------------------------------------------------------
|
||
|
|
Add-Head "WinSCP"
|
||
|
|
$winscpDll = Join-Path $scriptRoot "WinSCP\WinSCPnet.dll"
|
||
|
|
if (-not (Test-Path $winscpDll)) {
|
||
|
|
Add-Line "WinSCPnet.dll MISSING - setup.bat has not been run (or it failed)."
|
||
|
|
} else {
|
||
|
|
$dll = Get-Item $winscpDll
|
||
|
|
Add-Line "WinSCPnet.dll found: $($dll.Length) bytes, $($dll.LastWriteTime)"
|
||
|
|
$zone = Get-Item $winscpDll -Stream Zone.Identifier -ErrorAction SilentlyContinue
|
||
|
|
if ($zone) {
|
||
|
|
Add-Line "BLOCKED by Windows (Mark of the Web) - engine.ps1 unblocks this itself on every run."
|
||
|
|
} else {
|
||
|
|
Add-Line "Not blocked."
|
||
|
|
}
|
||
|
|
try {
|
||
|
|
Add-Type -Path $winscpDll -ErrorAction Stop
|
||
|
|
Add-Line "Loads OK."
|
||
|
|
} catch {
|
||
|
|
Add-Line "WILL NOT LOAD: $($_.Exception.Message)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# -- Entities -----------------------------------------------------------------
|
||
|
|
Add-Head "Entities"
|
||
|
|
$entitiesDir = Join-Path $scriptRoot "Entities"
|
||
|
|
if (-not (Test-Path $entitiesDir)) {
|
||
|
|
Add-Line "No Entities\ folder at all."
|
||
|
|
} else {
|
||
|
|
$entities = @(Get-ChildItem -Path $entitiesDir -Directory | Where-Object { $_.Name -ne "EXAMPLE" })
|
||
|
|
if ($entities.Count -eq 0) { Add-Line "Entities\ exists but is empty." }
|
||
|
|
|
||
|
|
foreach ($entity in $entities) {
|
||
|
|
Add-Line ""
|
||
|
|
Add-Line ("-- $($entity.Name) " + ("-" * 40))
|
||
|
|
$configFile = Join-Path $entity.FullName "entity.json"
|
||
|
|
if (-not (Test-Path $configFile)) {
|
||
|
|
Add-Line " entity.json MISSING - this entity is skipped by run-all."
|
||
|
|
} else {
|
||
|
|
$raw = Get-Content $configFile -Raw
|
||
|
|
# Mask anything that looks like a password before this leaves the PC.
|
||
|
|
$masked = $raw -replace '("password"\s*:\s*")[^"]*(")', '$1********$2'
|
||
|
|
Add-Line " entity.json:"
|
||
|
|
foreach ($l in ($masked -split "`r?`n")) { Add-Line " $l" }
|
||
|
|
|
||
|
|
try {
|
||
|
|
$raw | ConvertFrom-Json | Out-Null
|
||
|
|
Add-Line " Reads as valid JSON."
|
||
|
|
} catch {
|
||
|
|
Add-Line " *** THIS FILE IS NOT VALID JSON *** $($_.Exception.Message)"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$export1 = Join-Path $entity.FullName "Export1"
|
||
|
|
if (-not (Test-Path $export1)) {
|
||
|
|
Add-Line " No Export1\ folder."
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
|
||
|
|
$today = Get-Date -Format "yyyyMMdd"
|
||
|
|
foreach ($practice in (Get-ChildItem -Path $export1 -Directory)) {
|
||
|
|
$dateDir = Join-Path $practice.FullName $today
|
||
|
|
if (Test-Path $dateDir) {
|
||
|
|
$files = @(Get-ChildItem -Path $dateDir -File)
|
||
|
|
$byExt = ($files | Group-Object Extension |
|
||
|
|
ForEach-Object { "$($_.Count)x $($_.Name)" }) -join ", "
|
||
|
|
if (-not $byExt) { $byExt = "empty" }
|
||
|
|
Add-Line " $($practice.Name): $today\ has $($files.Count) file(s) - $byExt"
|
||
|
|
} else {
|
||
|
|
Add-Line " $($practice.Name): no $today\ folder"
|
||
|
|
}
|
||
|
|
$pj = Join-Path $practice.FullName "practice.json"
|
||
|
|
if (Test-Path $pj) {
|
||
|
|
$pmasked = (Get-Content $pj -Raw) -replace '("password"\s*:\s*")[^"]*(")', '$1********$2'
|
||
|
|
Add-Line " practice.json: $($pmasked -replace '\s+', ' ')"
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# -- Logs ---------------------------------------------------------------------
|
||
|
|
Add-Head "Most recent log"
|
||
|
|
$logsDir = Join-Path $scriptRoot "Logs"
|
||
|
|
if (-not (Test-Path $logsDir)) {
|
||
|
|
Add-Line "No Logs\ folder - engine.ps1 has never completed a run here."
|
||
|
|
} else {
|
||
|
|
$log = Get-ChildItem -Path $logsDir -Filter "*.log" |
|
||
|
|
Where-Object { $_.Name -notmatch "winscp_debug" } |
|
||
|
|
Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||
|
|
if (-not $log) {
|
||
|
|
Add-Line "Logs\ is empty."
|
||
|
|
} else {
|
||
|
|
Add-Line "$($log.Name) (last written $($log.LastWriteTime))"
|
||
|
|
Add-Line ""
|
||
|
|
$content = Get-Content $log.FullName -Tail 120
|
||
|
|
foreach ($l in $content) { Add-Line " $l" }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Add-Head "End of report"
|
||
|
|
|
||
|
|
# -- Write it out -------------------------------------------------------------
|
||
|
|
$text = $lines -join "`r`n"
|
||
|
|
try {
|
||
|
|
Set-Content -Path $outFile -Value $text -Encoding UTF8
|
||
|
|
$saved = $true
|
||
|
|
} catch {
|
||
|
|
$outFile = Join-Path $scriptRoot "MelissaUploader-Report-$stamp.txt"
|
||
|
|
Set-Content -Path $outFile -Value $text -Encoding UTF8
|
||
|
|
$saved = $true
|
||
|
|
}
|
||
|
|
|
||
|
|
Write-Host $text
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host ("=" * 60) -ForegroundColor Cyan
|
||
|
|
if ($saved) {
|
||
|
|
Write-Host "Report saved to:" -ForegroundColor Green
|
||
|
|
Write-Host " $outFile" -ForegroundColor Green
|
||
|
|
Write-Host ""
|
||
|
|
Write-Host "Send that file to Brad - it has everything needed to work out" -ForegroundColor Cyan
|
||
|
|
Write-Host "what went wrong. Passwords are replaced with ******** in it." -ForegroundColor Cyan
|
||
|
|
}
|
||
|
|
Write-Host ("=" * 60) -ForegroundColor Cyan
|