【问题标题】:Accessing the WindowsInstaller.Installer COM Object in C#在 C# 中访问 WindowsInstaller.Installer COM 对象
【发布时间】:2019-01-17 12:15:49
【问题描述】:

我在 GitHub 上找到了一个nice Powershell function,它使用 WindowsInstaller.Installer COM 对象来查询已安装的应用程序,并非常漂亮地列出了所有详细信息和属性。但是,我不想使用Powershell 我想创建一个exe。

我不想搜索注册表,也不想使用 WMI。我想使用与 powershell 脚本和我找到的另一个 vbscript 中使用的完全相同的方法。确实存在一个名为 WindowsInstaller.Installer 的 COM 对象。它确实存在,但由于某种原因,我找不到一个示例,说明在使用 C# 在 Visual Studio 中导入 msi.dll 后如何访问它。

有人知道这个问题的答案吗?

在 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 ??????????
        }

    }

【问题讨论】:

    标签: c# com windows-installer


    【解决方案1】:

    @{} 是对的,它是一个新的哈希表。我认为对于您想要的内容,您可以创建一个列表,每个产品都可以通过迭代来收集属性,您可以将其添加到该列表中

       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();
    

    【讨论】:

    • 非常有帮助,非常感谢!我很接近,但你让我一直到那里,然后是一些。
    • 你几乎 99% 都在那里......我一开始盯着你的解决方案,无法弄清楚它是如何不起作用的。解决人类的难题很有趣:)
    • VS 无法识别“WindowsInstaller.Installer”,我缺少什么参考?
    • 添加对“C:\Windows\System32\msi.dll”的引用以及“使用 WindowsInstaller;”
    猜你喜欢
    • 2013-01-14
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 2014-06-25
    相关资源
    最近更新 更多