在 C# 中访问 WindowsInstaller.Installer COM 对象
Accessing the WindowsInstaller.Installer COM Object in C#
我在 GitHub 上找到了一个 nice Powershell function,它使用 WindowsInstaller.Installer COM 对象来查询已安装的应用程序,并非常漂亮地列出了所有详细信息和属性。但是,我不想使用 Powershell 我想创建一个 exe。
我不想搜索注册表,也不想使用 WMI。我想使用与 powershell 脚本和我发现的另一个 vbscript 中使用的完全相同的方法。确实存在一个名为 WindowsInstaller.Installer 的 COM 对象。它确实存在,但出于某种原因,我找不到一个示例来说明在使用 C# 将 msi.dll 导入 Visual Studio 后如何访问它。
有人知道这个问题的答案吗?
在Visual Studio中,为WindowsInstaller 添加COM 引用的WindowsInstaller.Installer 引用只是一种类型,仅此而已。它不包含名为 "GetType" 的方法,并且尝试将此 PowerShell 转换为 C# 无法正常工作。
我也不知道 @{}
是什么意思,但我猜它是 Hashtable 的意思。
我试图强制出现以下情况的不幸尝试:
private void Form1_Load(object sender, EventArgs e)
{
Type installerType = Type.GetType("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var type = installer.GetType();
var Products = type.InvokeMember("Products", System.Reflection.BindingFlags.GetProperty, null, installer, null) as IEnumerable<object>;
foreach (var product in Products)
{
Hashtable hash = new Hashtable();
hash.Add("ProductCode", product);
string[] Attributes = { "Language", "ProductName", "PackageCode", "Transforms", "AssignmentType", "PackageName", "InstalledProductName", "VersionString", "RegCompany", "RegOwner", "ProductID", "ProductIcon", "InstallLocation", "InstallSource", "InstallDate", "Publisher", "LocalPackage", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo" };
foreach (var attribute in Attributes)
{
object[] thing = { product, attribute };
var details = type.InvokeMember("ProductInfo", System.Reflection.BindingFlags.GetProperty, null, installer, thing);
hash.Add(attribute, details);
}
new ??????????
}
}
你说得对 @{}
,这是一个新的哈希表。我认为对于您想要的,您可以创建一个列表,然后迭代以收集属性的每个产品都可以将其添加到该列表中
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<Hashtable> ProductCollection = new List<Hashtable>();
foreach (var product in Products)
{
Hashtable hash = new Hashtable();
hash.Add("ProductCode", product);
string[] Attributes = { "Language", "ProductName", "PackageCode", "Transforms", "AssignmentType", "PackageName", "InstalledProductName", "VersionString", "RegCompany", "RegOwner", "ProductID", "ProductIcon", "InstallLocation", "InstallSource", "InstallDate", "Publisher", "LocalPackage", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo" };
foreach (var attribute in Attributes)
{
try
{
var details = installer.ProductInfo[product.ToString(), attribute.ToString()];
hash.Add(attribute, details);
}
catch
{
}
}
ProductCollection.Add(hash);
}
现在只需参考 ProductCollection 即可获取您的产品详细信息。如果您想更进一步,您可以为每个 MSI 创建一个 class,并让您的流程为每个产品创建一个对象。
public class MSIInfo
{
public string ProductCode { get; set; }
public string Language { get; set; }
public string ProductName { get; set; }
public string PackageCode { get; set; }
public string Transforms { get; set; }
public string AssignmentType { get; set; }
public string PackageName { get; set; }
public string InstalledProductName { get; set; }
public string VersionString { get; set; }
public string RegCompany { get; set; }
public string RegOwner { get; set; }
public string ProductID { get; set; }
public string ProductIcon { get; set; }
public string InstallLocation { get; set; }
public string InstallSource { get; set; }
public string InstallDate { get; set; }
public string Publisher { get; set; }
public string LocalPackage { get; set; }
public string HelpLink { get; set; }
public string HelpTelephone { get; set; }
public string URLInfoAbout { get; set; }
public string URLUpdateInfo { get; set; }
public override string ToString()
{
return $"{ProductName} - {ProductCode}";
}
public static IEnumerable<MSIInfo> GetProducts()
{
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<MSIInfo> ProductCollection = new List<MSIInfo>();
foreach (var product in Products)
{
MSIInfo msi = new MSIInfo();
msi.ProductCode = product.ToString();
foreach (var property in msi.GetType()?.GetProperties())
{
try
{
if (property.Name != "ProductCode")
{
string val = installer.ProductInfo[product.ToString(), property.Name];
property.SetValue(msi, val);
}
}
catch (System.Runtime.InteropServices.COMException)
{
}
}
ProductCollection.Add(msi);
}
return ProductCollection;
}
}
一旦你有了那个class你就可以像这样从你的代码中获取集合
var Products = MSIInfo.GetProducts();
我在 GitHub 上找到了一个 nice Powershell function,它使用 WindowsInstaller.Installer COM 对象来查询已安装的应用程序,并非常漂亮地列出了所有详细信息和属性。但是,我不想使用 Powershell 我想创建一个 exe。
我不想搜索注册表,也不想使用 WMI。我想使用与 powershell 脚本和我发现的另一个 vbscript 中使用的完全相同的方法。确实存在一个名为 WindowsInstaller.Installer 的 COM 对象。它确实存在,但出于某种原因,我找不到一个示例来说明在使用 C# 将 msi.dll 导入 Visual Studio 后如何访问它。
有人知道这个问题的答案吗?
在Visual Studio中,为WindowsInstaller 添加COM 引用的WindowsInstaller.Installer 引用只是一种类型,仅此而已。它不包含名为 "GetType" 的方法,并且尝试将此 PowerShell 转换为 C# 无法正常工作。
我也不知道 @{}
是什么意思,但我猜它是 Hashtable 的意思。
我试图强制出现以下情况的不幸尝试:
private void Form1_Load(object sender, EventArgs e)
{
Type installerType = Type.GetType("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var type = installer.GetType();
var Products = type.InvokeMember("Products", System.Reflection.BindingFlags.GetProperty, null, installer, null) as IEnumerable<object>;
foreach (var product in Products)
{
Hashtable hash = new Hashtable();
hash.Add("ProductCode", product);
string[] Attributes = { "Language", "ProductName", "PackageCode", "Transforms", "AssignmentType", "PackageName", "InstalledProductName", "VersionString", "RegCompany", "RegOwner", "ProductID", "ProductIcon", "InstallLocation", "InstallSource", "InstallDate", "Publisher", "LocalPackage", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo" };
foreach (var attribute in Attributes)
{
object[] thing = { product, attribute };
var details = type.InvokeMember("ProductInfo", System.Reflection.BindingFlags.GetProperty, null, installer, thing);
hash.Add(attribute, details);
}
new ??????????
}
}
你说得对 @{}
,这是一个新的哈希表。我认为对于您想要的,您可以创建一个列表,然后迭代以收集属性的每个产品都可以将其添加到该列表中
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<Hashtable> ProductCollection = new List<Hashtable>();
foreach (var product in Products)
{
Hashtable hash = new Hashtable();
hash.Add("ProductCode", product);
string[] Attributes = { "Language", "ProductName", "PackageCode", "Transforms", "AssignmentType", "PackageName", "InstalledProductName", "VersionString", "RegCompany", "RegOwner", "ProductID", "ProductIcon", "InstallLocation", "InstallSource", "InstallDate", "Publisher", "LocalPackage", "HelpLink", "HelpTelephone", "URLInfoAbout", "URLUpdateInfo" };
foreach (var attribute in Attributes)
{
try
{
var details = installer.ProductInfo[product.ToString(), attribute.ToString()];
hash.Add(attribute, details);
}
catch
{
}
}
ProductCollection.Add(hash);
}
现在只需参考 ProductCollection 即可获取您的产品详细信息。如果您想更进一步,您可以为每个 MSI 创建一个 class,并让您的流程为每个产品创建一个对象。
public class MSIInfo
{
public string ProductCode { get; set; }
public string Language { get; set; }
public string ProductName { get; set; }
public string PackageCode { get; set; }
public string Transforms { get; set; }
public string AssignmentType { get; set; }
public string PackageName { get; set; }
public string InstalledProductName { get; set; }
public string VersionString { get; set; }
public string RegCompany { get; set; }
public string RegOwner { get; set; }
public string ProductID { get; set; }
public string ProductIcon { get; set; }
public string InstallLocation { get; set; }
public string InstallSource { get; set; }
public string InstallDate { get; set; }
public string Publisher { get; set; }
public string LocalPackage { get; set; }
public string HelpLink { get; set; }
public string HelpTelephone { get; set; }
public string URLInfoAbout { get; set; }
public string URLUpdateInfo { get; set; }
public override string ToString()
{
return $"{ProductName} - {ProductCode}";
}
public static IEnumerable<MSIInfo> GetProducts()
{
Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Installer installerObj = (Installer)Activator.CreateInstance(installerType);
WindowsInstaller.Installer installer = installerObj as WindowsInstaller.Installer;
var Products = installerObj.Products;
List<MSIInfo> ProductCollection = new List<MSIInfo>();
foreach (var product in Products)
{
MSIInfo msi = new MSIInfo();
msi.ProductCode = product.ToString();
foreach (var property in msi.GetType()?.GetProperties())
{
try
{
if (property.Name != "ProductCode")
{
string val = installer.ProductInfo[product.ToString(), property.Name];
property.SetValue(msi, val);
}
}
catch (System.Runtime.InteropServices.COMException)
{
}
}
ProductCollection.Add(msi);
}
return ProductCollection;
}
}
一旦你有了那个class你就可以像这样从你的代码中获取集合
var Products = MSIInfo.GetProducts();