English 中文(简体)
通过注册表检测已安装的程序
原标题:
  • 时间:2009-01-09 21:06:13
  •  标签:

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

我的第一个想法是在卸载项中检查注册表,但是似乎我想要检测的应用程序之一没有。所有使用注册表的应用程序的标准位置在哪里进行条目?

最佳回答

用户特定的设置应该被写入到HKCUSoftware,机器特定的设置应该被写入到HKLMSoftware。在这些键下,结构[软件提供商名称][应用程序名称](例如HKLMSoftwareMicrosoftInternet Explorer)可能是最常见的,但这只是一个约定,并不是自然法则。

许多(大多数?)应用程序还会将其卸载条目添加到 HKLMSoftwareMicrosoftWindowsCurrentVersionUninstall [应用程序名称] 中,但并非所有应用程序都会这样做。

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

编辑:

如果您是管理员组的成员,则可以检查 HKEY_USERS hive - 每个用户的 HKCU 实际上驻留在那里(您需要知道用户的 SID,或浏览所有这些用户)。

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

问题回答

在64位系统中,x64键是:

HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall

Most programs are listed there. Look at the keys: DisplayName DisplayVersion

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

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

HKEY_LOCAL_MACHINESOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionUninstall

您可以使用 MSI API 枚举 Windows Installer 安装的所有内容,但无法列出计算机上可用的所有软件。如果不了解您需要什么,我认为“已安装”这个概念有些模糊。将软件部署到系统的方法有很多,包括大型复杂的安装程序、ZIP 文件和各种其他方法。

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

注意到,大多数优秀的应用程序可以通过其卸载注册表键找到。实际上,这是一对键,每个用户和每台机器一个(HKCU / HKLM-Piskvor仅提到了HKLM)。但它不会(总是)为您提供安装目录。

如果它在HKCU中,那么你必须意识到实际上意味着“当前用户”。其他用户有他们自己的HKCU条目和安装的软件。你找不到那个。在具有漫游配置文件的公司网络上阅读每个HKEY_USERS蜂窝是一场灾难。您真的不想从您的远程[美国|中国|欧洲]办公室获取1000个帐户。

即使应用程序已经安装,并且您知道在哪里,它可能没有您拥有的相同“版本”概念。最好的来源是可执行文件中的“版本”资源。这确实是复数形式,因此您必须找到所有这些,从所有这些中提取版本资源,并在发生冲突时决定一些合理的事情。

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

您可以使用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:SoftwareMicrosoftWindowsCurrentVersionUninstall
$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:SoftwareWow6432NodeMicrosoftWindowsCurrentVersionUninstall
$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

似乎寻找已安装程序的特定内容会更好,但HKCUSoftware和HKLMSoftware是需要关注的地方。

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

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

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

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





相关问题