我需要开发一个流程,以便检测用户计算机上是否安装了某些程序,以及如果安装了,它们的版本是什么。我相信我需要一个包含注册表位置和密钥的列表,并将其提供给程序进行查找,这并不是一个问题。有更好的方法来完成这个任务吗?
我的第一个想法是在卸载项中检查注册表,但是似乎我想要检测的应用程序之一没有。所有使用注册表的应用程序的标准位置在哪里进行条目?
我需要开发一个流程,以便检测用户计算机上是否安装了某些程序,以及如果安装了,它们的版本是什么。我相信我需要一个包含注册表位置和密钥的列表,并将其提供给程序进行查找,这并不是一个问题。有更好的方法来完成这个任务吗?
我的第一个想法是在卸载项中检查注册表,但是似乎我想要检测的应用程序之一没有。所有使用注册表的应用程序的标准位置在哪里进行条目?
用户特定的设置应该被写入到HKCUSoftware,机器特定的设置应该被写入到HKLMSoftware。在这些键下,结构[软件提供商名称][应用程序名称]
(例如HKLMSoftwareMicrosoftInternet Explorer
)可能是最常见的,但这只是一个约定,并不是自然法则。
许多(大多数?)应用程序还会将其卸载条目添加到 HKLMSoftwareMicrosoftWindowsCurrentVersionUninstall [应用程序名称] code>中,但并非所有应用程序都会这样做。
这些是最重要的键;但是,注册表的内容不一定要完全代表已安装的软件 - 可能应用程序曾经被安装过,但后来被手动删除,或者卸载程序没有删除其所有痕迹。如果你想确定,可以检查文件系统,看看应用程序是否仍然存在于其注册表条目所说的位置。
编辑:
如果您是管理员组的成员,则可以检查 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中,那么你必须意识到
即使应用程序已经安装,并且您知道在哪里,它可能没有您拥有的相同“版本”概念。最好的来源是可执行文件中的“版本”资源。这确实是复数形式,因此您必须找到所有这些,从所有这些中提取版本资源,并在发生冲突时决定一些合理的事情。
所以-祝你好运。有许多失败的方式。
您可以使用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