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:
@@ -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++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user