在C#中访问WindowsInstaller.Installer COM对象

4
我在GitHub上找到一个很好的Powershell函数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 ??????????
        }

    }
1个回答

7

关于@{},你是正确的,它是一个新的哈希表。我认为,对于你想要的功能,你可以创建一个列表,并在遍历每个产品以收集属性时将其添加到该列表中。

   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创建一个类,并让您的进程为每个产品创建一个对象。
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;

        }
    }

一旦你有了那个类,就可以像这样从代码中获取集合:

var Products = MSIInfo.GetProducts();

1
非常有帮助,非常感谢!我已经接近成功了,但是你帮我完全解决了问题。 - Nathan McKaskle
1
你基本上已经完成了99%的工作...一开始我看着你的解决方案,无法弄清楚它为什么不起作用。这是一个有趣的难题,很高兴解决了 :) - Paul G
1
Visual Studio无法识别“WindowsInstaller.Installer”,我缺少哪个引用? - Alonzzo2
2
添加对'C:\Windows\System32\msi.dll'的引用,以及 'using WindowsInstaller;' - Paul G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接