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

如何正确导出多台服务器的指定应用及其版本信息至Excel?

解决PowerShell远程应用信息导出CSV的问题

你的脚本主要存在两个核心问题,导致导出结果不符合预期,我一步步给你拆解并修正:

问题分析

  1. CSV文件被重复覆盖:你在foreach循环里直接调用Export-Csv,每次执行都会清空并覆盖之前的文件内容,最终只会保留最后一台服务器的查询结果。
  2. 应用名称匹配逻辑失效:$list是从文件读取的数组(每行对应一个应用名),直接用$_.Name -like "*$list*"不会正确匹配数组里的每个应用——PowerShell会把数组转换成逗号分隔的字符串,导致匹配规则完全错误。
  3. 额外优化点:Get-WmiObject是较老旧的命令,建议用Get-CimInstance替代,性能更好且避免Win32_Product自带的MSI自动修复触发;默认Export-Csv会添加类型信息行,会干扰Excel的列解析。

修正后的完整脚本

# 读取目标应用列表和服务器列表
$appList = Get-Content -Path C:\Users\bob\AppList.txt
$serverList = Get-Content -Path C:\Users\bob\ServerList.txt

# 定义输出路径,先清空原有文件(避免旧内容干扰)
$outputPath = "C:\Users\bob\ServerListResults.csv"
if (Test-Path $outputPath) { Remove-Item $outputPath }

# 遍历每台服务器
foreach ($server in $serverList) {
    Write-Host "正在查询服务器: $server"
    try {
        # 使用Get-CimInstance替代Get-WmiObject,更高效且避免MSI自动修复触发
        Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Product -ComputerName $server -ErrorAction Stop |
            # 过滤匹配应用列表的项:检查当前应用名是否匹配列表中任意一个关键词
            Where-Object { 
                $currentAppName = $_.Name
                $appList | Where-Object { $currentAppName -like "*$_*" }
            } |
            # 选择需要的属性列
            Select-Object Name, Version, PSComputerName |
            # 追加到CSV文件,-NoTypeInformation去掉类型注释行,-Encoding确保Excel兼容
            Export-Csv -Path $outputPath -Append -NoTypeInformation -Encoding UTF8
    }
    catch {
        Write-Warning "服务器 $server 查询失败: $_"
    }
}

Write-Host "查询完成,结果已导出至: $outputPath"

关键改进说明

  • 避免文件覆盖:添加-Append参数让每次循环的结果追加到CSV,而不是覆盖;提前清空旧文件确保结果干净。
  • 正确匹配应用:通过嵌套的Where-Object检查当前应用名称是否匹配$appList中的任意一项,解决数组匹配的逻辑问题。
  • 替换为Get-CimInstance:Win32_Product本身会触发MSI的自动修复检查,可能导致性能变慢甚至意外操作,Get-CimInstance是更安全高效的替代方案。
  • 错误处理:添加Try-Catch捕获服务器不可达、权限不足等错误,避免脚本中断,同时输出警告信息便于排查。
  • Excel兼容性优化:-NoTypeInformation去掉CSV第一行的类型注释,-Encoding UTF8确保中文等特殊字符能被Excel正确识别。

更高效的进阶写法(推荐)

如果不需要返回所有Win32_Product的属性,可以直接在远程服务器端过滤,减少数据传输量:

foreach ($server in $serverList) {
    Write-Host "正在查询服务器: $server"
    try {
        # 逐个查询应用列表中的应用,在远程端直接过滤,提升性能
        foreach ($app in $appList) {
            Get-CimInstance -Namespace ROOT\CIMV2 -Class Win32_Product -ComputerName $server -Filter "Name LIKE '%$app%'" -ErrorAction Stop |
                Select-Object Name, Version, PSComputerName |
                Export-Csv -Path $outputPath -Append -NoTypeInformation -Encoding UTF8
        }
    }
    catch {
        Write-Warning "服务器 $server 查询失败: $_"
    }
}

这种方式通过-Filter参数在远程服务器端直接完成过滤,不需要把所有应用数据传回本地再处理,在服务器数量较多时性能提升明显。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:22:47