You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }
}

解决方案

一、修复第一个脚本的核心问题

第一个脚本失效的原因有两个,对应修复如下:

  1. ErrorAction SilentlyContinue 屏蔽了异常捕获:你给Remove-Item、New-Item加了这个参数,会让错误被静默忽略,根本触发不了catch块。要改成-ErrorAction Stop,强制把非终止错误转为终止错误,确保异常能被捕获。
  2. 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
    }
}

二、实现输出需求的关键点

  1. 覆盖文件并添加日期:脚本开头用Out-File -Force写入扫描日期,-Force会直接清空原有文件内容,后续用-Append追加错误记录。
  2. 区分离线提示:通过捕获异常的消息内容,判断是“网络路径找不到”(机器离线或名错)还是其他操作错误,输出对应提示。
  3. 控制台实时输出:用Write-Host将错误信息同步输出到控制台,方便实时查看运行状态。

额外优化建议

  • 去掉不必要的Start-Sleep:除非必须等待系统操作完成,否则可以删除,提升脚本运行效率。
  • 提前检测机器在线状态:在Test-Path前用Test-Connection快速过滤离线设备,减少等待时间:
    if (Test-Connection -ComputerName $computer -Count 1 -Quiet -ErrorAction Stop) {
        # 再执行Test-Path和后续操作
    }
    

内容的提问来源于stack exchange,提问作者RunnerXdays

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:20:33