远程计算机软件编目PowerShell脚本故障排查求助
问题排查与修正方案
首先,你的脚本在远程执行时生成空CSV的核心问题集中在远程目标引用错误、权限/服务启动失败未处理以及缺少32位软件检测这几个方面。以下是具体问题分析和修正后的脚本:
核心问题分析
- 远程计算机名引用错误:取消注释foreach循环后,
$sysname=hostname仍然获取本地主机名,而非CSV中的远程计算机名,导致始终查询本地注册表。 - 服务操作参数错误:
Get-Service -ComputerName $system中的$system是CSV对象,需指定具体列名(假设CSV列名为ComputerName),否则无法识别远程主机。 - 缺少错误处理:远程连接失败、服务启动失败时没有捕获异常,导致脚本静默失败且无日志。
- 未检测32位软件:仅查询64位注册表路径,遗漏安装在Wow6432Node下的32位软件。
修正后的脚本
$computers = Import-Csv "C:\Temp\AssetList.csv" -Delimiter "," $results = @() $errorLog = @() foreach ($system in $computers) { $computerName = $system.ComputerName # 确保CSV包含ComputerName列 Write-Host "正在处理计算机: $computerName" try { # 尝试启动RemoteRegistry服务 $remoteRegService = Get-Service -ComputerName $computerName -Name RemoteRegistry -ErrorAction Stop if ($remoteRegService.Status -ne 'Running') { Set-Service -InputObject $remoteRegService -StartupType Manual -ErrorAction Stop Start-Service -InputObject $remoteRegService -ErrorAction Stop $serviceChanged = $true } # 定义需要查询的注册表路径(64位+32位) $registryPaths = @( "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" ) foreach ($path in $registryPaths) { $regBase = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computerName, [Microsoft.Win32.RegistryView]::Registry64) $regKey = $regBase.OpenSubKey($path) if ($regKey) { foreach ($subKeyName in $regKey.GetSubKeyNames()) { $subKey = $regKey.OpenSubKey($subKeyName) $displayName = $subKey.GetValue("DisplayName") if ($displayName) { # 过滤无显示名称的条目 $results += [PSCustomObject]@{ ComputerName = $computerName DisplayName = $displayName DisplayVersion = $subKey.GetValue("DisplayVersion") Publisher = $subKey.GetValue("Publisher") InstallLocation = $subKey.GetValue("InstallLocation") RegistryPath = $path # 标记是64位还是32位软件 } } } $regKey.Close() } $regBase.Close() } # 如果修改了服务状态,恢复为Disabled if ($serviceChanged) { Set-Service -InputObject $remoteRegService -StartupType Disabled -ErrorAction Stop Stop-Service -InputObject $remoteRegService -ErrorAction Stop } } catch { $errorLog += [PSCustomObject]@{ ComputerName = $computerName ErrorMessage = $_.Exception.Message TimeStamp = Get-Date } Write-Warning "处理$computerName失败: $($_.Exception.Message)" } } # 导出结果 $results | Export-CSV "C:\Temp\CatalogedSoftware.csv" -NoTypeInformation -Encoding UTF8 $errorLog | Export-CSV "C:\Temp\SoftwareCatalog_Errors.csv" -NoTypeInformation -Encoding UTF8 Write-Host "处理完成,结果已导出到C:\Temp\CatalogedSoftware.csv,错误日志在C:\Temp\SoftwareCatalog_Errors.csv"
关键修正点说明
- 正确引用远程计算机名:使用
$system.ComputerName获取CSV中的目标主机名,确保查询远程注册表。 - 添加错误处理:用
try/catch捕获连接失败、服务操作失败等异常,并生成错误日志,便于排查问题。 - 包含32位软件检测:新增
Wow6432Node路径查询,避免遗漏32位应用。 - 优化服务操作:先检查服务状态,仅在未运行时启动,处理完成后恢复原状态(如果修改过)。
- 过滤无效条目:仅保留有
DisplayName的软件条目,减少无效数据。 - 编码与格式优化:导出CSV时指定UTF8编码,避免中文乱码,使用
PSCustomObject替代New-Object提升效率。
前置要求
- 执行脚本的账号需具备远程计算机的管理员权限。
- 远程计算机需开启RemoteRegistry服务(脚本会尝试临时启动)。
- 网络需允许远程注册表访问(防火墙需放行Remote Registry服务端口)。
- CSV文件需包含
ComputerName列,每行对应一个目标计算机名或IP地址。
内容的提问来源于stack exchange,提问作者mc3mcintyre
相关产品推荐
相关产品推荐

