You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PowerShell通过注册表获取已安装软件时部分条目无名称/版本

为什么你的PowerShell脚本会缺失部分软件名称/版本信息?

我来帮你拆解几个关键原因,以及对应的修复方案:

1. 漏掉了64位系统中的32位软件注册表路径

在64位Windows系统中,32位应用的卸载信息会存在HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall路径下,而你的脚本只读取了默认的HKLM\SOFTWARE\...路径,这直接导致所有32位软件的条目被遗漏。

2. 部分注册表键本身就没有必填字段

不是所有软件都会严格遵循Windows的安装规范写入DisplayNameDisplayVersion字段——比如一些绿色软件、自定义打包的程序,或者某些系统组件,可能只在Uninstall键下写入了卸载命令,但没填写名称/版本信息,这种情况脚本自然会返回空值。

3. 远程注册表访问的权限问题

当你远程读取其他电脑的注册表时,如果当前运行脚本的账号没有目标电脑的注册表读取权限,部分子键会无法打开,调用GetValue时就会返回空。


优化后的脚本

下面是修复了以上问题的版本:

  • 同时遍历32位和64位的Uninstall路径
  • 过滤掉没有DisplayName的无效条目
  • 添加了错误处理,避免权限问题导致脚本中断
# 导入计算机列表CSV
$computers = Import-Csv "C:\Users\P1334126\Documents\Test.CSV"
$array = @()

# 定义需要检查的两个注册表路径(64位+32位)
$uninstallPaths = @(
    "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
    "SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"
)

foreach($pc in $computers) {
    $computername = $pc.computername
    try {
        # 打开远程注册表的HKLM基键
        $reg = [microsoft.win32.registrykey]::OpenRemoteBaseKey('LocalMachine', $computername)
        
        foreach($uninstallPath in $uninstallPaths) {
            try {
                $regkey = $reg.OpenSubKey($uninstallPath)
                if(-not $regkey) { continue } # 如果路径不存在则跳过
                
                $subkeys = $regkey.GetSubKeyNames()
                foreach($key in $subkeys) {
                    try {
                        $thisKey = $uninstallPath + '\\' + $key
                        $thisSubKey = $reg.OpenSubKey($thisKey)
                        if(-not $thisSubKey) { continue }
                        
                        # 获取字段值,为空时显示"N/A"
                        $displayName = $thisSubKey.GetValue("DisplayName") ?? "N/A"
                        $displayVersion = $thisSubKey.GetValue("DisplayVersion") ?? "N/A"
                        $publisher = $thisSubKey.GetValue("Publisher") ?? "N/A"
                        
                        # 只保留有名称的条目(过滤无效键)
                        if($displayName -ne "N/A") {
                            $obj = [PSCustomObject]@{
                                ComputerName = $computername
                                DisplayName = $displayName
                                DisplayVersion = $displayVersion
                                Publisher = $publisher
                            }
                            $array += $obj
                        }
                    }
                    catch {
                        Write-Warning "无法读取 $computername 的注册表键 $thisKey : $_"
                    }
                }
            }
            catch {
                Write-Warning "无法访问 $computername 的注册表路径 $uninstallPath : $_"
            }
        }
    }
    catch {
        Write-Warning "无法连接到 $computername 的远程注册表: $_"
    }
}

# 输出结果到文件
$array | Select-Object ComputerName, DisplayName, DisplayVersion, Publisher | Sort-Object ComputerName | Out-File InstalledSoftware.txt

额外提示:

  • 确保运行脚本的账号在目标电脑上有Remote Registry服务的访问权限,且该服务已启动
  • 有些软件会把卸载信息存在HKCU(当前用户)的Uninstall路径下,如果需要获取当前用户的软件,还需要添加对应的路径遍历

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

火山引擎 最新活动