WMI:获取已安装软件的列表
Posted
技术标签:
【中文标题】WMI:获取已安装软件的列表【英文标题】:WMI: Get the list of Installed Softwares 【发布时间】:2020-11-14 02:39:21 【问题描述】:我需要使用wmi
调用来获取远程Windows 主机上已安装软件的列表。我尝试过使用Win32_Product
和Win32Reg_AddRemovePrograms
类。
使用Win32_Product
的好处是,它显示了机器上安装的所有软件,但它非常非常慢,并且在超过 90% 的主机上无法运行(出现错误,例如 -NTSTATUS: NT code 0xc002001b - NT code 0xc002001b
)。另一方面,Win32Reg_AddRemovePrograms
速度更快,并且在大多数主机上运行良好,但缺少很多软件。
还有其他 Win32 类可以有效地做到这一点吗?
【问题讨论】:
另外值得记住的是,使用 Win32_Product 可能会产生一些奇怪的副作用:support.microsoft.com/kb/974524。不过这篇文章可能有用:blogs.technet.com/b/heyscriptingguy/archive/2011/11/13/… 【参考方案1】:你可以使用 wmic。
例子:
wmic product get name,version /format:csv
wmic /node:localhost /output:d:\programlist.htm product
get name,version /format:htable.xsl
wmic product get name,version
wmic softwareelement get name,version
wmic softwarefeature get name,version
wmic wmic:root\cli>/output:c:\ProgramList.txt product get name,version
或者您可以像“添加/删除程序”一样读取所有卸载注册表项:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
在 64 位 Windows 上,请记住还要检查:
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\
返回计算机上安装的所有软件的列表,无论是否通过 Windows-Installer:
Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
strComputer = "."
strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
strEntry1a = "DisplayName"
strEntry1b = "QuietDisplayName"
strEntry2 = "InstallDate"
strEntry3 = "VersionMajor"
strEntry4 = "VersionMinor"
strEntry5 = "EstimatedSize"
Set objReg = GetObject("winmgmts://" & strComputer & _
"/root/default:StdRegProv")
objReg.EnumKey HKLM, strKey, arrSubkeys
WScript.Echo "Installed Applications" & VbCrLf
For Each strSubkey In arrSubkeys
intRet1 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
strEntry1a, strValue1)
If intRet1 <> 0 Then
objReg.GetStringValue HKLM, strKey & strSubkey, _
strEntry1b, strValue1
End If
If strValue1 <> "" Then
WScript.Echo VbCrLf & "Display Name: " & strValue1
End If
objReg.GetStringValue HKLM, strKey & strSubkey, _
strEntry2, strValue2
If strValue2 <> "" Then
WScript.Echo "Install Date: " & strValue2
End If
objReg.GetDWORDValue HKLM, strKey & strSubkey, _
strEntry3, intValue3
objReg.GetDWORDValue HKLM, strKey & strSubkey, _
strEntry4, intValue4
If intValue3 <> "" Then
WScript.Echo "Version: " & intValue3 & "." & intValue4
End If
objReg.GetDWORDValue HKLM, strKey & strSubkey, _
strEntry5, intValue5
If intValue5 <> "" Then
WScript.Echo "Estimated Size: " & Round(intValue5/1024, 3) & " megabytes"
End If
Next
【讨论】:
wmic product
只是Win32_Product
类的别名,不是吗?所有这些wmic
命令只是常规类的别名。 wmic product
实际上调用了wmic path Win32_Product get *
。 OP 正在寻求替代方案。
@Dawid Ferenczy Rogožan:是的,但是 WMIC(Windows 管理界面命令)是针对批处理脚本的 WMI 优化。它更快。【参考方案2】:
基于系统注册表窗口读数的 c# 编码版本。
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SoftwareInventory
class Program
static void Main(string[] args)
//!!!!! Must be launched with a domain administrator user!!!!!
Console.ForegroundColor = ConsoleColor.Green;
StringBuilder sbOutFile = new StringBuilder();
Console.WriteLine("DisplayName;IdentifyingNumber");
sbOutFile.AppendLine("Machine;DisplayName;Version");
//Retrieve machine name from the file :File_In/collectionMachines.txt
//string[] lines = new string[] "NameMachine" ;
string[] lines = File.ReadAllLines(@"File_In/collectionMachines.txt");
foreach (var machine in lines)
//Retrieve the list of installed programs for each extrapolated machine name
var registry_key = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, machine).OpenSubKey(registry_key))
foreach (string subkey_name in key.GetSubKeyNames())
using (RegistryKey subkey = key.OpenSubKey(subkey_name))
//Console.WriteLine(subkey.GetValue("DisplayName"));
//Console.WriteLine(subkey.GetValue("IdentifyingNumber"));
if (subkey.GetValue("DisplayName") != null)
Console.WriteLine(string.Format("0;1;2", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
sbOutFile.AppendLine(string.Format("0;1;2", machine, subkey.GetValue("DisplayName"), subkey.GetValue("Version")));
//CSV file creation
var fileOutName = string.Format(@"File_Out\0_1.csv", "Software_Inventory", DateTime.Now.ToString("yyyy_MM_dd_HH_mmssfff"));
using (var file = new System.IO.StreamWriter(fileOutName))
file.WriteLine(sbOutFile.ToString());
//Press enter to continue
Console.WriteLine("Press enter to continue !");
Console.ReadLine();
【讨论】:
以上是关于WMI:获取已安装软件的列表的主要内容,如果未能解决你的问题,请参考以下文章
电脑管家(像qq,360管家)是怎么获取到系统中安装的软件列表和补丁列表(漏洞,已安装,未安装)用C#如何实现
我在 C# 中使用 WMI 来获取所有已安装的软件,但它并没有显示所有软件,只显示 Microsoft 软件
powershell 使用PowerShell获取所有已安装软件的列表。见http://www.howtogeek.com/165293/how-to-get-a-list-of-software-i