Windows PS:模仿CCleaner“;卸载";列出电脑上安装的程序的工具

Windows PS:模仿CCleaner“;卸载";列出电脑上安装的程序的工具,windows,powershell,registry,Windows,Powershell,Registry,CCleaner包含一个工具,可以列出电脑上的程序,然后卸载。这个列表似乎包含的应用程序比浏览网页更全面。其中一个例子是Atom(开源文本编辑器)。该程序不会出现在卸载注册表中,而是安装在用户的AppData文件夹中(我不知道如何在不构建自定义包的情况下运行) 我编写了一个脚本,定期安装和更新某些软件包。这使得我可以轻松地让它们保持最新,而无需每周或每次我想更新它们时访问十几个网站(它们不像Chrome或Firefox那样自动更新)。因此,我需要一个列表,我可以动态创建并使用它来检查更新以及是否

CCleaner包含一个工具,可以列出电脑上的程序,然后卸载。这个列表似乎包含的应用程序比浏览网页更全面。其中一个例子是Atom(开源文本编辑器)。该程序不会出现在卸载注册表中,而是安装在用户的AppData文件夹中(我不知道如何在不构建自定义包的情况下运行)

我编写了一个脚本,定期安装和更新某些软件包。这使得我可以轻松地让它们保持最新,而无需每周或每次我想更新它们时访问十几个网站(它们不像Chrome或Firefox那样自动更新)。因此,我需要一个列表,我可以动态创建并使用它来检查更新以及是否需要执行安装程序


所以我的问题是:当CCleaner创建要卸载的程序列表时,我如何模仿它的做法——以编程方式?我可以执行GUI并导航到卸载工具,然后单击“保存到文本文件”,但这不是动态的。任何允许我捕获(在Powershell脚本中)CCleaner在卸载工具中生成的相同应用程序列表的答案都是可以接受的。

您也可以使用
Get Package
列出已安装的程序。它将列出Atom。您可能需要将注册表方法与
Get Package
相结合,以防它没有显示所有内容

Get-Package | Where-Object name -like *atom*

Name       Version     Source      ProviderName                                                                                                 
----       -------      ------     ------------                                                                                                 
Atom       1.53.0                  Programs  

您所要求的内容过去是通过
获取CimInstance
完成的,但这是有代价的,正如您所指出的,不再准确。它过去是一个WMI命令。现在是CIM。这不是一个快速的命令,稍后再详细介绍

Get-CimInstance win32_product
成本是
获取CimInstance
可能返回不完整的数据。它还对所有应用程序运行一致性检查,并执行自动和静默修复。是的,当您运行此命令时,它会自动对所有应用程序运行一致性检查,并执行自动和静默修复。这就是为什么这个简单的命令如此缓慢地返回报告的原因。 Microsoft关于此的文档:

所以我们不再使用它了,现在呢?您要查找的是从32位和64位安装程序收集信息,这些信息看起来像这样,必须完成,我总是先完成

$installedApplications = @()
$installedApplications+= Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" # 32 Bit
$installedApplications+= Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"             # 64 Bit
上面的一个警告是,上述方法返回的元素将比
Win32\u Product
命令返回的元素多得多。它将包含诸如服务包、Office更新、语言包等内容。您很可能需要筛选出您不感兴趣的内容,尽管使用PowerShell筛选结果不应该有问题

为了完整回答您的问题,您如何量化来自安装程序的数据,而不考虑其安装位置?专门查找
userprofile\AppData
安装信息。好消息是,这些应用程序的安装信息也记录在注册表中,位于
HKEY\U CURRENT\U USER
下,而不是
HKEY\U LOCAL\U MACHINE
下。这意味着每个用户的安装位置信息都位于其配置文件下的注册表配置单元中,例如
c:\users\inet\NTUSER.DAT

关于这一点,还需要说些什么

  • 如果用户已登录,则系统上的任何其他管理员用户都可以使用
    HKEY\U USERS\$ACCOUNT\U SID
    键访问此页面
  • 如果用户未登录,则可以使用
    REG LOAD
  • 如果用户的注册表配置单元已加载,则无法再次加载,并将给您强制性的“此文件正由另一个进程使用”
那么,我们如何得到您所要求的,即复制设备的“完整安装数据”,而不仅仅是32位和64位目录中的数据

这就是我使用的,如果有人选择的话,你可以通过管道将信息传输到CSV/HTML/etc

    $installedApplications = @()
    $installedApplications+= Get-ItemProperty "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" 
    $installedApplications+= Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"  

    $32BitPath = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
    $64BitPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"

    $tigerStripes= Get-CimInstance Win32_UserProfile | Select LocalPath, SID, Loaded, Special | Where {$_.SID -like "S-1-5-21-*"}
    $unavailableProfiles = $tigerStripes| Where {$_.Loaded -eq $true}
    $availableProfiles = $tigerStripes| Where {$_.Loaded -eq $false}

    #Mounted
    $unavailableProfiles | % {
        $installedApplications += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$32BitPath"
        $installedApplications += Get-ItemProperty -Path "Registry::\HKEY_USERS\$($_.SID)\$64BitPath"
    }
    #Unmounted
    $availableProfiles | % {
        #Mount Hive
        $Hive = "$($_.LocalPath)\NTUSER.DAT"

        if (Test-Path $Hive) {
            REG LOAD HKU\temp $Hive
            $installedApplications += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$32BitPath"
            $installedApplications += Get-ItemProperty -Path "Registry::\HKEY_USERS\temp\$64BitPath"

            #This lets the hive be unmounted, using a manual Get-Content
            [GC]::Collect()
            [GC]::WaitForPendingFinalizers()
        
            REG UNLOAD HKU\temp

        } else {
            Write-Warning "Unable to access registry at $Hive"
        }
    }

$installedApplications 

这很有效。我必须协调每个数组(注册表数组和Get Package数组)的不同头,但是我刚刚创建了一个新的PSObject,并且能够将它们合并到一个唯一的列表中。谢谢谢谢你的回答。虽然我没有选择它作为“答案”,但由于您提到的缓慢问题,它确实显示了其他软件包。
Get-CimInstance win32_product
非常缓慢,特别是如果您有许多大小与PhotoShop或MatLab相似的应用程序。