如何通过PowerShell获取与「更改或删除程序」一致的软件清单?
如何用PowerShell获取与「更改或删除程序」完全一致的软件清单
Windows的「更改或删除程序」可以展示已安装软件的名称、发布者、安装日期、大小及版本信息。目前通过读取注册表的PowerShell脚本获取清单时,部分软件的安装日期字段缺失,但该字段在控制面板中是存在的。已尝试过不推荐的Get-WmiObject -Class Win32_Product和Get-Package,需要找到能完全匹配控制面板清单的方法。
原脚本:
$uninstallPath = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" $uninstallWow6432Path = "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" @( if (Test-Path "HKLM:$uninstallWow6432Path" ) { Get-ChildItem "HKLM:$uninstallWow6432Path"} if (Test-Path "HKLM:$uninstallPath" ) { Get-ChildItem "HKLM:$uninstallPath" } if (Test-Path "HKCU:$uninstallWow6432Path") { Get-ChildItem "HKCU:$uninstallWow6432Path"} if (Test-Path "HKCU:$uninstallPath" ) { Get-ChildItem "HKCU:$uninstallPath" } ) | ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_.DisplayName -and !$_.SystemComponent -and !$_.ReleaseType -and !$_.ParentKeyName -and ($_.UninstallString -or $_.NoRemove) } | Sort-Object DisplayName | ForEach-Object -Process { echo "$($_.DisplayName);$($_.DisplayVersion);$($_.InstallDate)" }
核心问题分析
部分软件的注册表Uninstall项中没有InstallDate值,但「更改或删除程序」会读取该注册表项的创建时间来填充安装日期,这是原脚本缺失的关键逻辑。
优化后的脚本
以下脚本保留原注册表筛选逻辑,同时补全缺失的安装日期,还会匹配控制面板的所有核心字段:
$uninstallPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\", "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\", "HKCU:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" ) # 遍历所有注册表路径,收集有效项 $installedSoftware = foreach ($path in $uninstallPaths) { if (Test-Path $path) { Get-ChildItem $path | ForEach-Object { $regItem = Get-ItemProperty $_.PSPath # 筛选条件和控制面板一致:排除系统组件、更新、父项等 if ($regItem.DisplayName -and !$regItem.SystemComponent -and !$regItem.ReleaseType -and !$regItem.ParentKeyName -and ($regItem.UninstallString -or $regItem.NoRemove)) { # 处理安装日期:优先用注册表的InstallDate,否则用注册表项的创建时间 $installDate = if ($regItem.InstallDate) { [DateTime]::ParseExact($regItem.InstallDate, "yyyyMMdd", $null).ToString("yyyy-MM-dd") } else { $_.CreationTime.ToString("yyyy-MM-dd") } # 处理大小:注册表的EstimatedSize是KB,转换为MB(保留1位小数) $size = if ($regItem.EstimatedSize) { [math]::Round($regItem.EstimatedSize / 1024, 1) } else { "N/A" } # 输出匹配控制面板的字段 [PSCustomObject]@{ 名称 = $regItem.DisplayName 发布者 = $regItem.Publisher ?? "N/A" 安装日期 = $installDate 大小(MB) = $size 版本 = $regItem.DisplayVersion ?? "N/A" } } } } } # 按名称排序并输出 $installedSoftware | Sort-Object 名称 | Format-Table -AutoSize # 如果需要导出为CSV,取消下面注释 # $installedSoftware | Sort-Object 名称 | Export-Csv -Path "已安装软件清单.csv" -Encoding UTF8 -NoTypeInformation
关键优化点说明
- 安装日期补全:当注册表无
InstallDate时,读取注册表项的创建时间,和「更改或删除程序」的显示逻辑完全一致。 - 字段匹配:包含控制面板的所有核心字段,大小字段将注册表的KB值转换为MB,符合日常认知。
- 筛选逻辑对齐:保留原脚本的筛选条件,确保只显示控制面板中可见的软件(排除系统组件、更新包、嵌套安装的父项等)。
为什么不推荐其他方法
Get-WmiObject -Class Win32_Product:仅识别MSI安装的软件,且会触发MSI的自动修复流程,可能导致系统问题。Get-Package:数据源和「更改或删除程序」不完全一致,会包含一些控制面板不显示的组件(如Windows功能、更新包),且部分字段缺失。
内容的提问来源于stack exchange,提问作者Fran
相关产品推荐
相关产品推荐

