我该如何获取系统上安装的软件产品列表。我的目标是遍历这些产品,并获取其中一些产品的安装路径。
伪代码(结合多种语言 :))
foreach InstalledSoftwareProduct
if InstalledSoftwareProduct.DisplayName LIKE *Visual Studio*
print InstalledSoftwareProduct.Path
我该如何获取系统上安装的软件产品列表。我的目标是遍历这些产品,并获取其中一些产品的安装路径。
伪代码(结合多种语言 :))
foreach InstalledSoftwareProduct
if InstalledSoftwareProduct.DisplayName LIKE *Visual Studio*
print InstalledSoftwareProduct.Path
您可以使用MSI API函数枚举所有已安装的产品。以下是一段示例代码。
在我的代码中,我首先枚举所有产品,获取产品名称,如果包含字符串“Visual Studio”,则检查InstallLocation
属性。然而,这个属性并不总是被设置。我不确定是否这不是需要检查的正确属性,或者是否有另一个总是包含目标目录的属性。也许InstallLocation
属性检索到的信息对您已经足够了呢?
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
class Program
{
[DllImport("msi.dll", CharSet = CharSet.Unicode)]
static extern Int32 MsiGetProductInfo(string product, string property,
[Out] StringBuilder valueBuf, ref Int32 len);
[DllImport("msi.dll", SetLastError = true)]
static extern int MsiEnumProducts(int iProductIndex,
StringBuilder lpProductBuf);
static void Main(string[] args)
{
StringBuilder sbProductCode = new StringBuilder(39);
int iIdx = 0;
while (
0 == MsiEnumProducts(iIdx++, sbProductCode))
{
Int32 productNameLen = 512;
StringBuilder sbProductName = new StringBuilder(productNameLen);
MsiGetProductInfo(sbProductCode.ToString(),
"ProductName", sbProductName, ref productNameLen);
if (sbProductName.ToString().Contains("Visual Studio"))
{
Int32 installDirLen = 1024;
StringBuilder sbInstallDir = new StringBuilder(installDirLen);
MsiGetProductInfo(sbProductCode.ToString(),
"InstallLocation", sbInstallDir, ref installDirLen);
Console.WriteLine("ProductName {0}: {1}",
sbProductName, sbInstallDir);
}
}
}
}
MsiEnumProducts
文档似乎没有提到这一点。所以我最终坚持使用注册表方式(迭代Microsoft\Windows\CurrentVersion\Uninstall
键)。https://stackoverflow.com/questions/20708136/unable-to-query-registry-for-installed-msi-files#comment102393783_20710736 - sjlewisWin32_Products
类表示由 Windows Installer 安装的所有产品。例如,以下 PowerShell 脚本将检索在本地计算机上由 Windows Installer 安装的所有产品:Get-WmiObject -Class Win32_Product -ComputerName .
请查看软件安装相关操作。将PS查询移植到等效的C# WMI API使用(也就是在.NET框架中使用WMI)留给读者作为练习。
如果你需要的所有程序都将它们的安装路径存储在注册表中,那么你可以使用类似于以下链接的东西: http://visualbasic.about.com/od/quicktips/qt/regprogpath.htm(我知道这是VB,但原理相同)。
我相信如果有些程序没有存储它们的安装路径(或者以难以理解的方式存储),可能会有一种通过.NET获取程序列表的方法,但我不知道。
通过注册表的最简单方法
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 && subkey.GetValue("DisplayName").ToString().Contains("Visual Studio"))
{
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();
}
}
}