给定一个MSI产品代码,我想从已经安装的产品中获取升级代码(以及其他属性)。我通过调用MsiOpenProduct方法和MsiGetProductProperty()进行了尝试。一个(简化的)示例如下所示:

MSIHANDLE handle = NULL;
MsiOpenProduct(strProductCode,&handle);
CString strUpgradeCode;
MsiGetProductProperty(handle,_T("UpgradeCode"), strUpgradeCode.GetBuffer(GUID_LENGTH), &dwSize);
strUpgradeCode.ReleaseBuffer();
MsiCloseHandle(handle);

这为我提供了所需的值,并且从MSDN文档中判断,这似乎是执行此操作的有效方法:



但是,对MsiOpenProduct()的调用会弹出“Windows安装程序正在准备安装...”对话框。调用MsiCloseHandle()使它再次消失。

这让我想知道:
  • 在后台调用MsiOpenProduct()有什么作用?我不想触发任何 Action ,我只想读取属性。
  • 我不介意弹出对话框,因为这仅适用于单元测试代码,只要它没有副作用即可。并且由于有许多单元测试可以执行此操作,因此在快速连续打开和关闭手柄时,它仍然必须能够正常工作。
  • 尽管我偶然发现了MsiGetProductInfo方法,但似乎没有办法获取升级代码。我对吗?
  • MsiOpenProduct是读取属性(如升级代码)的正确方法吗?
  • 最佳答案

    MsiOpenProduct应该很好,只要您不运行任何序列或 Action ,它就不会做任何事情。如果要使对话框静音,则可以谨慎使用MsiSetInternalUI()或MsiSetExternalUI()。

    只要ProductCodeUpgradeCode安全地是静态的(即,只要它们不被转换更改),您可以采用的另一种方法是使用MsiGetProductInfo()定位数据库并在其上调用MsiOpenDatabase()。区别在于MsiOpenProduct()(或类似的MsiOpenPackage)应用在安装时使用的转换并准备 session ,而MsiOpenDatabase()则不这样做。

    09-04 08:38