You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何优化PowerShell批量计算机信息采集脚本以实现多线程并行执行提升效率?

如何优化PowerShell批量计算机信息采集脚本以实现多线程并行执行提升效率?

我太懂你这种每周跑脚本熬几小时的痛苦了!串行一台接一台处理确实效率拉胯,咱们直接改成并行执行就能把速度提升好几倍,下面给你拆解优化思路和修改后的脚本:

原脚本的核心问题

  • foreach串行循环,必须等一台电脑处理完才会开始下一台,完全浪费了网络和本地的空闲资源
  • 多次单独调用Invoke-Command,每一次都要建立新的远程连接,额外增加了不少耗时
  • 强制重启WinRM服务的操作有点粗暴,除非你确定每次都需要,不然这步其实可以优化甚至移除

优化方案:用PowerShell原生的并行能力

PowerShell本身就有很好的并行处理工具,最适合这个场景的是Invoke-Command(它默认就会并行处理多台计算机),或者PS7+的ForEach-Object -Parallel。下面给你两种可行的优化版本:


版本1:兼容性最好(支持PS5及以上)

Invoke-Command批量处理在线计算机,同时合并远程脚本块减少连接次数,再单独处理离线设备:

$localComputer = "MyComputerName"
$computers = Import-Csv "\\$localComputer\path\computers.csv"
$computerNames = $computers.name

# 第一步:先筛选出在线的计算机
$onlineComputers = $computerNames | Where-Object { Test-Connection $_ -Count 1 -Quiet }
$offlineComputers = $computerNames | Where-Object { $_ -notin $onlineComputers }

# 第二步:并行采集在线计算机的信息
$onlineResults = Invoke-Command -ComputerName $onlineComputers -ScriptBlock {
    # 合并所有需要的查询,一次完成减少远程交互
    $systemInfo = Get-CimInstance Win32_ComputerSystem
    $biosInfo = Get-CimInstance Win32_BIOS
    $osInfo = Get-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion"

    [PSCustomObject]@{
        computer    = $env:COMPUTERNAME
        ping        = "Online"
        model       = $systemInfo.Model
        serviceTag  = $biosInfo.SerialNumber
        osVersion   = $osInfo.DisplayVersion
    }
} | Select-Object computer, serviceTag, model, osVersion, ping

# 第三步:处理离线计算机的结果
$offlineResults = $offlineComputers | ForEach-Object {
    [PSCustomObject]@{
        computer    = $_
        ping        = "Offline"
        model       = "N/A"
        serviceTag  = "N/A"
        osVersion   = "N/A"
    }
}

# 合并所有结果并导出
$allResults = $onlineResults + $offlineResults
$allResults | Export-Csv "\\$localComputer\path\results.csv" -NoTypeInformation

版本2:PS7+专属(更简洁)

如果你的环境已经升级到PowerShell 7及以上,用ForEach-Object -Parallel可以更灵活地控制并行度:

$localComputer = "MyComputerName"
$computers = Import-Csv "\\$localComputer\path\computers.csv"

$allResults = $computers | ForEach-Object -Parallel {
    $computerName = $_.name
    $pingTest = Test-Connection $computerName -Count 1 -Quiet

    if (-not $pingTest) {
        [PSCustomObject]@{
            computer    = $computerName
            ping        = "Offline"
            model       = "N/A"
            serviceTag  = "N/A"
            osVersion   = "N/A"
        }
    }
    else {
        try {
            # 这里可以保留WinRM重启逻辑(如果确实需要),但建议先测试是否真的需要
            # Get-Service -ComputerName $computerName -Name winrm | Restart-Service -Force
            # Start-Sleep -Seconds 1

            $systemInfo = Get-CimInstance Win32_ComputerSystem -ComputerName $computerName
            $biosInfo = Get-CimInstance Win32_BIOS -ComputerName $computerName
            $osInfo = Invoke-Command -ComputerName $computerName -ScriptBlock {
                Get-ItemProperty -Path "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion"
            }

            [PSCustomObject]@{
                computer    = $computerName
                ping        = "Online"
                model       = $systemInfo.Model
                serviceTag  = $biosInfo.SerialNumber
                osVersion   = $osInfo.DisplayVersion
            }
        }
        catch {
            # 处理远程连接失败的情况(比如WinRM没开)
            [PSCustomObject]@{
                computer    = $computerName
                ping        = "Online但连接失败"
                model       = "N/A"
                serviceTag  = "N/A"
                osVersion   = "N/A"
            }
        }
    }
} -ThrottleLimit 20  # 控制并行数量,避免网络过载

$allResults | Select-Object computer, serviceTag, model, osVersion, ping | Export-Csv "\\$localComputer\path\results.csv" -NoTypeInformation

几个额外的优化小技巧

  • Test-Connection换成Test-NetConnection或者直接依赖Invoke-Command的错误处理,有时候ping禁用但WinRM能通的设备会被误判
  • 调整-ThrottleLimit参数(默认是32),根据你的网络情况设置合适的并行数量,太多可能会导致网络拥堵
  • 如果必须重启WinRM,建议只在Invoke-Command失败时再尝试,而不是每次都重启
  • Get-CimInstance代替Get-WmiObject,WMI已经被CIM取代,性能和兼容性更好

备注:内容来源于stack exchange,提问作者IT4Gov

火山引擎 最新活动