通过registry检测安装的程序

我需要开发一个进程来检测用户计算机是否安装了某些程序,如果是,是什么版本。 我相信我需要一个包含registry位置和密钥的列表来查找并将其提供给程序,这不是问题。 有没有更好的方法来完成这个?

我的第一个想法是检查registry中的卸载条目,但似乎我想检测的应用程序之一没有一个。 什么是使用应用程序进入的所有registry的标准位置?

用户特定的设置应写入HKCU \ Software,机器特定的设置为HKLM \ Software。 在这些密钥下,结构[software vendor name]\[application name] (例如HKLM\Software\Microsoft\Internet Explorer )可能是最常见的,但这只是一个惯例,而不是一个自然规律。

许多(大多数?)应用程序还将其卸载项添加到HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\[app name] ,但是,并非所有应用程序都这样做。

这些是最重要的关键; 然而,registry的内容不必完全代表已安装的软件 – 也许应用程序已经安装了一次,但后来被手动删除,或者卸载程序没有删除它的所有痕迹。 如果您想确定,请检查文件系统以查看应用程序是否仍然存在registry项所在的位置。

编辑:

如果您是组pipe理员的成员,则可以检查HKEY_USERSconfiguration单元 – 每个用户的HKCU实际驻留在那里(您需要知道用户的SID,或通过所有用户)。

注意:正如@Brian Ensink所说,“安装”是一个模糊的概念 – 我们是否试图find用户可以运行? 某些软件甚至不会写入registry:search“便携式应用程序”,查看已经过特别修改的应用程序,直接从媒体(CD / USB)运行, 而不在计算机上留下任何痕迹。 我们可能还需要扫描磁盘,networking磁盘和用户下载的任何东西,以及互联网上世界上可以访问的Windows共享(是的,这样的东西存在合法的 – \\live.sysinternals.com\tools想法)。 在这个方向上,除非系统策略阻止,否则用户可以运行的内容不受限制。

在64位系统上,x64密钥是:

 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 

大多数的程序都列在那里。 看看按键: DisplayName DisplayVersion

请注意,最后并不总是设置!

在64位系统上,x86密钥(通常包含更多条目)是:

 HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall 

您可以使用MSI API枚举Windows安装程序安装的所有内容,但不会列出机器上可用的所有软件。 不知道更多你需要什么,我认为“安装”的概念有点模糊。 有很多方法可以将软件部署到从大型复杂安装程序到ZIP文件以及其间的所有系统。

应用程序不需要有任何registry项。 实际上,许多应用程序根本不需要安装。 U3 USB记忆棒就是一个很好的例子。 他们的程序只是从文件系统运行。

如上所述,尽pipe可以通过卸载registry键find大多数好的应用程序。 这实际上是一对钥匙,每个用户和每台机器(HKCU / HKLM – Piskvor只提到HKLM的一个)。 但它并不(总是)给你安装目录。

如果它在HKCU,那么你必须认识到HKEY_CURRENT_USER确实意味着“当前用户”。 其他用户有自己的HKCU条目和他们自己安装的软件。 你找不到。 阅读每个 HKEY_USERSconfiguration单元对于漫游configuration文件的企业networking来说都是一场灾难。 您真的不想从您的远程[美国|中国|欧洲]办事处获取1000个帐户。

即使安装了应用程序,并且您知道在哪里,也可能没有相同的“版本”概念。 最好的来源是可执行文件中的“版本”资源。 这确实是一个复数,所以你必须find所有这些,从所有提取版本资源,并在一个合理的情况下决定冲突的情况下。

所以 – 祝你好运。 有失败的方式打瞌睡。

除了上面提到的所有registry项之外,您还可能需要查看为当前用户安装的程序的HKEY_CURRENT_USER \ Software \ Microsoft \ Installer \ Products。

您可以使用PowerShell脚本来查看寄存器并获取已安装的程序详细信息。 下面的脚本将生成一个包含已安装程序完整列表的文件。 用“.ps”扩展名保存,然后双击该文件。

 # # Generates a full list of installed programs. # # Temporary auxiliar file. $tmpFile = "tmp.txt" # File that will hold the programs list. $fileName = "programas-instalados.txt" # Columns separator. $separator = "," # Delete previous files. Remove-Item $tmpFile Remove-Item $fileName # Creates the temporary file. Create-Item $tmpFile # Searchs register for programs - part 1 $loc = Get-ChildItem HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall $names = $loc |foreach-object {Get-ItemProperty $_.PsPath} foreach ($name in $names) { IF(-Not [string]::IsNullOrEmpty($name.DisplayName)) { $line = $name.DisplayName+$separator+$name.DisplayVersion+$separator+$name.InstallDate Write-Host $line Add-Content $tmpFile "$line`n" } } # Searchs register for programs - part 2 $loc = Get-ChildItem HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall $names = $loc |foreach-object {Get-ItemProperty $_.PsPath} foreach ($name in $names) { IF(-Not [string]::IsNullOrEmpty($name.DisplayName)) { $line = $name.DisplayName+$separator+$name.DisplayVersion+$separator+$name.InstallDate Write-Host $line Add-Content $tmpFile "$line`n" } } # Sorts the result, removes duplicate lines and # generates the final file. gc $tmpFile | sort | get-unique > $filename 

似乎寻找特定的安装程序的东西会更好,但HKCU \软件和HKLM \软件是要看的地方。

Win32_Product永远不会显示所有内容,只有通过MSI安装程序安装的软件(据我所知)。

有很多软件包通过其他安装程序没有出现在那里安装。 另一种方式是必要的。