枚举已安装产品的升级代码?

时间:2015-04-10 07:02:03

标签: c++ winapi windows-installer

我想获取Windows框中所有已安装产品的所有升级代码列表。问题是:是否有专门的MSI功能来解决这个问题?

MsiEnumProducts()枚举所有已安装的产品,MsiEnumRelatedProducts()枚举给定升级代码的所有产品。但我无法找到一个功能来获取系统中的所有升级代码。

我可以想象的解决方法是使用MsiEnumProducts()获取所有已安装产品的列表,使用MsiOpenProduct()函数打开每个产品并阅读" UpgradeCode"具有MsiGetProductProperty()的属性。但由于多次MsiOpenProduct()调用,这应该非常慢。

1 个答案:

答案 0 :(得分:2)

我相信MsiEnumProducts循环使用MsiOpenProduct,然后MsiGetProductProperty是正确的官方序列。如果您真的需要更快并且愿意绕过API,您可以直接在HKCR \ Installer \ UpgradeCodes上阅读注册表。你必须反转Darwin Descriptors。这在技术上是不受支持的,但实际上这些密钥已经存在了16年,MSFT已经在Windows Installer上进行了ZERO开发。好吧,也许他们更新了版本号并删除了Windows 10 LOL中的ARM支持。

FWIW,我喜欢使用C#而不是C ++,但概念是一样的。以下代码片段在我的开发人员计算机上运行约2秒钟。

using System;
using Microsoft.Deployment.WindowsInstaller;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var productInstallation in ProductInstallation.AllProducts)
            {
                using(var database = new Database(productInstallation.LocalPackage, DatabaseOpenMode.ReadOnly))
                {
                    Console.WriteLine(database.ExecutePropertyQuery("UpgradeCode"));
                }
            }
        }
    }
}

根据DTF文档,ProductInstallation.AllProducts使用MsiEnumProducts。 Database类构造函数使用MsiOpenDatabase,而ExecutePropertyQuery是一个更高级别的调用,基本上抽象从属性WHERE Property ='%s'执行SELECT值。因此,它将调用API来创建,执行和从视图中获取结果。所有这些类都实现了IDisposable来调用正确的API来释放资源。

呀...这就是我喜欢托管代码的原因。 :)