Add UpdateEMxInfo task for remote DNC eMxInfo.txt updates

- New task to update eMxInfo.txt on shopfloor PCs via WinRM
- Pushes file from local workstation to avoid double-hop auth issues
- Checks both Program Files (x86) and Program Files paths
- Backs up existing file with date stamp before replacing
- Kills DNCMain.exe before copy, restarts LDnc.exe after success
- Reports per-path success/failure with detailed error messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-01-07 16:59:01 -05:00
parent 7c30939234
commit 7ed9f42f44

View File

@@ -37,6 +37,9 @@
- SetTimezone : Set timezone to Eastern Standard Time - SetTimezone : Set timezone to Eastern Standard Time
- SyncTime : Force time sync with domain controller - SyncTime : Force time sync with domain controller
DNC:
- UpdateEMxInfo : Update eMxInfo.txt from network share (backs up old file first)
.PARAMETER Credential .PARAMETER Credential
PSCredential for remote authentication. Prompts if not provided. PSCredential for remote authentication. Prompts if not provided.
@@ -87,7 +90,7 @@ param(
[ValidateSet( [ValidateSet(
'DISM', 'SFC', 'OptimizeDisk', 'DiskCleanup', 'ClearUpdateCache', 'DISM', 'SFC', 'OptimizeDisk', 'DiskCleanup', 'ClearUpdateCache',
'RestartSpooler', 'FlushDNS', 'ClearBrowserCache', 'RestartWinRM', 'RestartSpooler', 'FlushDNS', 'ClearBrowserCache', 'RestartWinRM',
'SetTimezone', 'SyncTime' 'SetTimezone', 'SyncTime', 'UpdateEMxInfo'
)] )]
[string]$Task, [string]$Task,
@@ -680,6 +683,181 @@ $TaskScripts = @{
return $result return $result
} }
# -------------------------------------------------------------------------
# UpdateEMxInfo - Backup and prepare for file copy (runs on remote PC)
# The actual file is pushed via Copy-Item -ToSession from the caller
# -------------------------------------------------------------------------
'UpdateEMxInfo' = {
param($SourceFileContent)
$result = @{
Success = $false
Task = 'UpdateEMxInfo'
Hostname = $env:COMPUTERNAME
Output = ""
Error = $null
FailReason = ""
PathsUpdated = @()
PathsFailed = @()
BackupsCreated = @()
TempFile = ""
DNCKilled = $false
DNCRestarted = $false
}
$destFile = "eMxInfo.txt"
$tempPath = "C:\Windows\Temp\eMxInfo-2026.txt"
# Check both possible DNC installation paths
$destDirs = @(
"C:\Program Files (x86)\DNC\Server Files",
"C:\Program Files\DNC\Server Files"
)
try {
# Check if temp file was pushed
if (-not (Test-Path $tempPath)) {
$result.FailReason = "Source file not found at $tempPath - file push may have failed"
$result.Error = $result.FailReason
Write-Output $result.FailReason
return $result
}
# Track which paths exist
$validPaths = @()
foreach ($destDir in $destDirs) {
if (Test-Path $destDir) {
$validPaths += $destDir
}
}
if ($validPaths.Count -eq 0) {
$result.FailReason = "No DNC Server Files directory found in Program Files or Program Files (x86)"
$result.Error = $result.FailReason
Write-Output $result.FailReason
# Clean up temp file
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
return $result
}
Write-Output "Found $($validPaths.Count) DNC installation(s)"
# Kill DNCMain.exe before copying
Write-Output "Stopping DNCMain.exe..."
$dncProcess = Get-Process -Name "DNCMain" -ErrorAction SilentlyContinue
if ($dncProcess) {
try {
taskkill /IM DNCMain.exe /F 2>&1 | Out-Null
Start-Sleep -Seconds 2
$result.DNCKilled = $true
Write-Output " DNCMain.exe stopped"
} catch {
Write-Output " Warning: Could not stop DNCMain.exe - $($_.Exception.Message)"
}
} else {
Write-Output " DNCMain.exe not running"
}
# Process each valid path
foreach ($destDir in $validPaths) {
$destPath = Join-Path $destDir $destFile
$pathLabel = if ($destDir -like "*x86*") { "x86" } else { "x64" }
Write-Output "Processing $pathLabel path: $destDir"
# Check if destination file exists and back it up
if (Test-Path $destPath) {
$dateStamp = Get-Date -Format "yyyyMMdd"
$backupName = "eMxInfo-old-$dateStamp.txt"
$backupPath = Join-Path $destDir $backupName
Write-Output " File exists, renaming to $backupName..."
try {
# Remove existing backup if same date
if (Test-Path $backupPath) {
Remove-Item $backupPath -Force -ErrorAction Stop
}
Rename-Item -Path $destPath -NewName $backupName -Force -ErrorAction Stop
$result.BackupsCreated += "$pathLabel`:$backupName"
} catch {
$result.PathsFailed += "$pathLabel`: Failed to rename - $($_.Exception.Message)"
Write-Output " FAILED to rename: $($_.Exception.Message)"
continue
}
} else {
Write-Output " File does not exist, creating new..."
}
# Copy from temp location to destination
try {
Copy-Item -Path $tempPath -Destination $destPath -Force -ErrorAction Stop
# Verify the copy
if (Test-Path $destPath) {
$result.PathsUpdated += $pathLabel
Write-Output " SUCCESS"
} else {
$result.PathsFailed += "$pathLabel`: Copy succeeded but file not found"
Write-Output " FAILED: File not found after copy"
}
} catch {
$result.PathsFailed += "$pathLabel`: Failed to copy - $($_.Exception.Message)"
Write-Output " FAILED to copy: $($_.Exception.Message)"
}
}
# Clean up temp file
Remove-Item $tempPath -Force -ErrorAction SilentlyContinue
# Determine overall success
if ($result.PathsUpdated.Count -gt 0) {
$result.Success = $true
$result.Output = "Updated: $($result.PathsUpdated -join ', ')"
if ($result.BackupsCreated.Count -gt 0) {
$result.Output += " | Backups: $($result.BackupsCreated -join ', ')"
}
if ($result.PathsFailed.Count -gt 0) {
$result.Output += " | Failed: $($result.PathsFailed.Count)"
}
# Restart DNC - find LDnc.exe in one of the valid paths
Write-Output "Starting LDnc.exe..."
$ldncStarted = $false
foreach ($destDir in $validPaths) {
$ldncPath = Join-Path $destDir "LDnc.exe"
if (Test-Path $ldncPath) {
try {
Start-Process -FilePath $ldncPath -ErrorAction Stop
$result.DNCRestarted = $true
$ldncStarted = $true
Write-Output " LDnc.exe started from $destDir"
break
} catch {
Write-Output " Warning: Could not start LDnc.exe from $destDir - $($_.Exception.Message)"
}
}
}
if (-not $ldncStarted) {
Write-Output " Warning: LDnc.exe not found or could not be started"
}
$result.Output += " | DNC restarted: $($result.DNCRestarted)"
} else {
$result.FailReason = "All paths failed: $($result.PathsFailed -join '; ')"
$result.Error = $result.FailReason
}
} catch {
$result.FailReason = "Unexpected error: $($_.Exception.Message)"
$result.Error = $result.FailReason
Write-Output $result.FailReason
}
return $result
}
} }
# ============================================================================= # =============================================================================
@@ -744,6 +922,79 @@ $tasksToRun = @($Task)
# Create session options # Create session options
$sessionOption = New-PSSessionOption -OpenTimeout 30000 -OperationTimeout 600000 -NoMachineProfile $sessionOption = New-PSSessionOption -OpenTimeout 30000 -OperationTimeout 600000 -NoMachineProfile
# Special handling for UpdateEMxInfo - requires pushing file first
if ($Task -eq 'UpdateEMxInfo') {
$sourcePath = "\\tsgwp00525.rd.ds.ge.com\shared\cameron\eMxInfo-2026.txt"
$remoteTempPath = "C:\Windows\Temp\eMxInfo-2026.txt"
Write-Log "UpdateEMxInfo: Checking source file..." -Level "INFO"
if (-not (Test-Path $sourcePath)) {
Write-Log "Source file not found: $sourcePath" -Level "ERROR"
exit 1
}
Write-Log "Source file found. Will push to each PC before executing." -Level "INFO"
$successCount = 0
$failCount = 0
foreach ($fqdn in $targetFQDNs) {
Write-Host ""
Write-Log "Processing: $fqdn" -Level "TASK"
try {
# Create session
$session = New-PSSession -ComputerName $fqdn -Credential $Credential -SessionOption $sessionOption -Authentication Negotiate -ErrorAction Stop
# Push the file to remote temp location
Write-Log " Pushing file to remote PC..." -Level "INFO"
Copy-Item -Path $sourcePath -Destination $remoteTempPath -ToSession $session -Force -ErrorAction Stop
# Execute the scriptblock
Write-Log " Executing update task..." -Level "INFO"
$result = Invoke-Command -Session $session -ScriptBlock $TaskScripts['UpdateEMxInfo'] -ErrorAction Stop
# Close session
Remove-PSSession $session -ErrorAction SilentlyContinue
# Process result
if ($result.Success) {
Write-Log "[OK] $($result.Hostname)" -Level "SUCCESS"
Write-Host " $($result.Output)" -ForegroundColor Gray
if ($result.PathsFailed.Count -gt 0) {
foreach ($fail in $result.PathsFailed) {
Write-Host " [!] $fail" -ForegroundColor Yellow
}
}
$successCount++
} else {
$errorMsg = if ($result.FailReason) { $result.FailReason } else { $result.Error }
Write-Log "[FAIL] $($result.Hostname): $errorMsg" -Level "ERROR"
$failCount++
}
} catch {
Write-Log "[FAIL] ${fqdn}: $($_.Exception.Message)" -Level "ERROR"
$failCount++
# Clean up session if it exists
if ($session) { Remove-PSSession $session -ErrorAction SilentlyContinue }
}
}
# Summary
Write-Host ""
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host " SUMMARY" -ForegroundColor Cyan
Write-Host ("=" * 70) -ForegroundColor Cyan
Write-Host " Task: $Task" -ForegroundColor White
Write-Host " Successful: $successCount" -ForegroundColor Green
Write-Host " Failed: $failCount" -ForegroundColor $(if ($failCount -gt 0) { "Red" } else { "White" })
Write-Host ("=" * 70) -ForegroundColor Cyan
exit 0
}
# Process each task # Process each task
foreach ($currentTask in $tasksToRun) { foreach ($currentTask in $tasksToRun) {
@@ -802,6 +1053,14 @@ foreach ($currentTask in $tasksToRun) {
'DiskCleanup' { 'DiskCleanup' {
Write-Host " Space freed: $($result.SpaceFreed) GB" -ForegroundColor Gray Write-Host " Space freed: $($result.SpaceFreed) GB" -ForegroundColor Gray
} }
'UpdateEMxInfo' {
Write-Host " $($result.Output)" -ForegroundColor Gray
if ($result.PathsFailed.Count -gt 0) {
foreach ($fail in $result.PathsFailed) {
Write-Host " [!] $fail" -ForegroundColor Yellow
}
}
}
default { default {
if ($result.Output) { if ($result.Output) {
Write-Host " $($result.Output)" -ForegroundColor Gray Write-Host " $($result.Output)" -ForegroundColor Gray
@@ -812,7 +1071,8 @@ foreach ($currentTask in $tasksToRun) {
$successCount++ $successCount++
} else { } else {
Write-Log "[FAIL] $($result.Hostname): $($result.Error)" -Level "ERROR" $errorMsg = if ($result.FailReason) { $result.FailReason } else { $result.Error }
Write-Log "[FAIL] $($result.Hostname): $errorMsg" -Level "ERROR"
$failCount++ $failCount++
} }
} }