PowerShell脚本求助:修复无效计算机名捕获与输出优化问题
问题描述
我正尝试捕获MachineName.txt中输入错误的计算机名,目前第一个脚本无法正常工作,但第二个脚本可以。请问如何修复第一个脚本?此外,当前Out-File仅输出计算机名,我希望每次运行脚本时覆盖bad_names.txt内容并添加日期,同时能输出机器离线的提示信息。
失效的脚本
$computers = Get-Content "D:\MachineNames.txt" foreach ($computer in $computers) { If (Test-Path -Path "\\$computer\c$\Users") { try { Remove-Item -Path "\\$computer\d$\Folder1\*" -Recurse -Force -ErrorAction SilentlyContinue -Verbose Start-Sleep -Seconds 1 New-Item -Path "\\$computer\d$\" -Name Folder1 -ItemType Directory -Force -ErrorAction SilentlyContinue -Verbose Start-Sleep -Seconds 1 #Transfer files... Start-Sleep -Seconds 1 #Start-BitsTransfer -Source "\\$env:COMPUTERNAME\d$\1.exe" -Destination "\\$computer\d$\" -ErrorAction SilentlyContinue -Verbose #Start-BitsTransfer -Source "\\$env:COMPUTERNAME\d$\Folder1\*" -Destination "\\$computer\d$\Folder1\" -ErrorAction SilentlyContinue -Verbose } catch { "Bad name: $computer" | Out-File 'D:\bad_names.txt' -Append } } }
可用的脚本
$computers = Get-Content "D:\MachineNames.txt" foreach ($computer in $computers) { try { Copy-Item -Path "\\$env:COMPUTERNAME\d$\1.exe" -Destination "\\$computer\d$\" -ErrorAction SilentlyContinue -Verbose #Copy-Item -Path "\\$env:COMPUTERNAME\d$\Folder1\*" -Destination "\\$computer\d$\Folder1\" -ErrorAction SilentlyContinue -Verbose } catch { "Bad name: $computer" | Out-File 'D:\bad_names.txt' -Append } }
解决方案
一、修复第一个脚本的核心问题
第一个脚本失效的原因有两个,对应修复如下:
ErrorAction SilentlyContinue屏蔽了异常捕获:你给Remove-Item、New-Item加了这个参数,会让错误被静默忽略,根本触发不了catch块。要改成-ErrorAction Stop,强制把非终止错误转为终止错误,确保异常能被捕获。Test-Path的分支逻辑遗漏错误场景:如果计算机名错误,Test-Path访问共享目录会直接失败,但你只在Test-Path返回$true时才进入try,错误的机器名根本走不到catch里,自然不会被记录。
修复后的完整脚本:
$computers = Get-Content "D:\MachineNames.txt" # 初始化输出文件:写入当前日期并覆盖原有内容 "=== 扫描日期:$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ===" | Out-File 'D:\bad_names.txt' -Force foreach ($computer in $computers) { try { # 强制捕获Test-Path的错误 if (Test-Path -Path "\\$computer\c$\Users" -ErrorAction Stop) { Remove-Item -Path "\\$computer\d$\Folder1\*" -Recurse -Force -ErrorAction Stop -Verbose New-Item -Path "\\$computer\d$\" -Name Folder1 -ItemType Directory -Force -ErrorAction Stop -Verbose #Transfer files... #Start-BitsTransfer -Source "\\$env:COMPUTERNAME\d$\1.exe" -Destination "\\$computer\d$\" -ErrorAction Stop -Verbose #Start-BitsTransfer -Source "\\$env:COMPUTERNAME\d$\Folder1\*" -Destination "\\$computer\d$\Folder1\" -ErrorAction Stop -Verbose } } catch { # 区分错误类型,生成精准提示 $errorMsg = if ($_.Exception.Message -match "network path was not found") { "[$(Get-Date -Format 'HH:mm:ss')] 机器离线或无法解析:$computer" } else { "[$(Get-Date -Format 'HH:mm:ss')] 操作失败/无效计算机名:$computer" } # 追加到文件 $errorMsg | Out-File 'D:\bad_names.txt' -Append # 控制台同步输出红色提示 Write-Host $errorMsg -ForegroundColor Red } }
二、实现输出需求的关键点
- 覆盖文件并添加日期:脚本开头用
Out-File -Force写入扫描日期,-Force会直接清空原有文件内容,后续用-Append追加错误记录。 - 区分离线提示:通过捕获异常的消息内容,判断是“网络路径找不到”(机器离线或名错)还是其他操作错误,输出对应提示。
- 控制台实时输出:用
Write-Host将错误信息同步输出到控制台,方便实时查看运行状态。
额外优化建议
- 去掉不必要的
Start-Sleep:除非必须等待系统操作完成,否则可以删除,提升脚本运行效率。 - 提前检测机器在线状态:在
Test-Path前用Test-Connection快速过滤离线设备,减少等待时间:if (Test-Connection -ComputerName $computer -Count 1 -Quiet -ErrorAction Stop) { # 再执行Test-Path和后续操作 }
内容的提问来源于stack exchange,提问作者RunnerXdays
相关产品推荐
相关产品推荐

