通过注册表检测已安装的程序

Posted

技术标签:

【中文标题】通过注册表检测已安装的程序【英文标题】:Detecting installed programs via registry 【发布时间】:2010-09-30 14:14:32 【问题描述】:

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

我的第一个想法是检查卸载条目中的注册表,但似乎我希望检测的应用程序之一没有。所有使用应用程序登录的注册表的标准位置是什么?

【问题讨论】:

【参考方案1】:

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

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall

那里列出了大多数程序。看钥匙: DisplayName DisplayVersion

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

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

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

【讨论】:

对于x86系统,在x64中是同一个key吗? @MohammadrezaPanahi 是的,相同的密钥(第一个:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall)。【参考方案2】:

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

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

这些是最重要的键;但是,注册表的内容不必完全代表已安装的软件 - 可能该应用程序已安装一次,但随后被手动删除,或者卸载程序没有删除它的所有痕迹。如果您想确定,请检查文件系统以查看应用程序是否仍然存在于其注册表项所说的位置。

编辑:

如果您是管理员组的成员,您可以检查 HKEY_USERS 配置单元 - 每个用户的 HKCU 实际上都驻留在那里(您需要知道用户 SID,或者查看所有这些)。

注意:正如@Brian Ensink 所说,“已安装”是一个有点模糊的概念——我们是否试图找到用户可以运行的内容?有些软件甚至根本不写入注册表:搜索“便携式应用程序”以查看经过专门修改以直接从媒体 (CD/USB) 运行的应用程序,留下任何痕迹在电脑上面。我们可能还需要扫描磁盘、网络磁盘以及用户下载的任何内容,以及 Internet 上全球可访问的 Windows 共享(是的,这些东西是合法存在的 - 我想到了 \\live.sysinternals.com\tools)。在这个方向上,用户可以运行的内容没有真正的限制,除非系统策略阻止。

【讨论】:

添加/删除程序列表如何填充?我列出的应用程序中有一半以上在上述位置没有注册表项(Microsoft 应用程序除外)。 此外,非管理员用户可以安装愿意远离 HKLM 的软件。这很常见,它允许按用户安装。 某些用户安装的应用程序,如 Chrome、GoToMeeting、Pixie、WinDirStat 和 WebEx 不会写入 HKLM\...\Uninstall。 HKCU 仅适用于当前用户,因此除非用户是您,否则这些将不包含用户(非管理员)安装的软件的条目。 @Bratch:是的,你是对的。新增 HKEY_USERS - 管理员可以通过这种方式访问​​其他用户的 HKCU;还有一段关于免安装应用的文章。 不知道 \\live.sysinternals.com\tools。很棒的提示!谢谢。【参考方案3】:

您可以使用 MSI API 枚举由 Windows Installer 安装的所有内容,但不会列出计算机上所有可用的软件。在不了解您需要什么的情况下,我认为“已安装”的概念有点模糊。将软件部署到系统的方法有很多种,从大型复杂的安装程序到 ZIP 文件以及介于两者之间的所有内容。

【讨论】:

+1;从长远来看,使用 MSI API 而不是手动修改注册表会更可靠,对您来说痛苦更少...... 这是一个很好的答案(至少对我而言),但如果您包含一个链接会更好。 我同意 RenniePet 的观点;一个例子或至少一个链接到附近的地方会很好。【参考方案4】:

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

如前所述,大多数优秀的应用程序都可以通过它们的卸载注册表项找到。这实际上是一对密钥,每个用户和每个机器(HKCU/HKLM - Piskvor 只提到了 HKLM 一个)。但是,它并不(总是)给你安装目录。

如果是在 HKCU 中,那么您必须意识到 HKEY_CURRENT_USER 的真正含义是“当前用户”。其他用户有自己的 HKCU 条目,以及自己安装的软件。你找不到那个。阅读每一个 HKEY_USERS hive 对具有漫游配置文件的公司网络来说是一场灾难。您真的不想从远程 [US|China|Europe] 办公室获取 1000 个帐户。

即使安装了应用程序,并且您知道在哪里,它也可能与您的“版本”概念不同。最好的来源是可执行文件中的“版本”资源。那确实是复数,所以你必须找到所有的,从所有中提取版本资源,并在发生冲突的情况下做出合理的决定。

所以 - 祝你好运。失败的方式有很多种。

【讨论】:

【参考方案5】:

您可以使用 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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

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

【讨论】:

我在这个地址找不到任何东西。 这只是可能安装某些产品的另一个位置(至少在 Windows 7 上) - 我有一个应用程序在那里留下了一个条目。【参考方案8】:

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

有很多软件包是通过其他安装程序安装的,而这些安装程序并没有在其中显示。需要另一种方式。

【讨论】:

【参考方案9】:

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted

【讨论】:

以上是关于通过注册表检测已安装的程序的主要内容,如果未能解决你的问题,请参考以下文章

无法通过 TestFlight 安装应用程序:已注册的最大设备数

有没有办法在没有卸载注册表或 C:\Windows\Installer 的情况下检测安装位置?

如何检测 VC++ 2008 可再发行组件?

创建EXCEL对象失败,请确认已正确安装Excel程序?

Navisworks2017卸载或安装不上怎么办

finalshell安装mysql依赖检测失败