Подробный ответ с информацией о том, как получить код UpgradeCode с использованием Powershell или VBScript и WMI здесь: Как найтиКод обновления для установленного файла MSI?
Ниже приведен краткий базовый пример с использованием автоматизации VBScript / COM ( MSI API , а не WMI) и подходом, обсужденным OP (с использованиемметод OpenProduct - COM, эквивалентный функции установщика Win32.
Как обсуждалось в моем комментарии выше, я просто добавлю этот небольшой VBScript, чтобы сделать то же самое, что делает OP в C ++.Обратите внимание, что Установщик Windows может быть доступен через WMI (объект Win32_Product), Автоматизация COM * и Функции установщика Win32 C ++ .
По какой-то причине UpgradeCode
для пакета, по-видимому, недоступен непосредственно из COM API или Win32 API.Очень странно, тем более, что это входной параметр для таких функций, как Installer.RelatedProducts - в документации не ясно, что фактический вызов должен быть RelatedProducts(UpgradeCode)
, но, глядя на msi.IDL
, вы видите: StringList* RelatedProducts([in] BSTR UpgradeCode);
Опция WMI работает, но также работает этот вызов OpenProduct
, показанный ниже (который значительно быстрее и выглядит безопасным - насколько я знаю, WMI полностью доступен только для чтения - но небеса знаютчто они делают «под капотом». Они раскручивают объект сеанса? Или они читают из базы данных WMI? WMI каким-то образом «чувствует себя безопаснее».
Прелесть метода, приведенного ниже, заключается в том, чтоон будет применять все преобразования, которые были применены к рассматриваемому продукту во время установки.Если вы хотите записать на диск вместо того, чтобы показывать окна сообщений и не можете потрудиться, просматривая документы, вот аналогичный VBScript, который записывает информацию о пакете в текстовый файл рабочего стола: Как мне найти GUID продукта дляустановка MSI? - совсем немного вниз по странице, просто скопируйте пару строк, и вы свободны от окна сообщения).
Примечание! Сценарий нижесоздайте один файл журнала для каждого открытого MSI, если в системе включено автоматическое ведение журнала .Пока он существует, скрипт откроет только один MSI, прежде чем он будет существовать (конструкция Exit For
).
On Error Resume Next ' This "tersified" script has no error handling
Const msiUILevelNone = 2
Set installer = CreateObject("WindowsInstaller.Installer")
Set products = installer.ProductsEx("", "", 7)
installer.UILevel = msiUILevelNone ' Suppress GUI (MSI progress dialog)
'Iterate over all MSI packages on the box
For Each product In products
' productcode = product.ProductCode
' name = product.InstallProperty("ProductName")
' version = product.InstallProperty("VersionString")
' pkgcode = product.InstallProperty("PackageCode")
Set session = installer.OpenProduct(product.ProductCode)
upgradecode = session.ProductProperty("UpgradeCode")
MsgBox upgradecode
Set session = Nothing ' Important, close the session (doesn't work in Javascript btw)
Exit For ' End after one iteration (so you don't get a million message boxes)
' Alternatively something like: If i > 4 Then Exit For
Next
Set installer = Nothing
MsgBox "Finished"
Я попытался найти в функциях установки C32 Win32 любой другой способполучить код UpgradeCode, но я не вижу ничего очевидного.Сеансовый подход должен работать и в C ++, но я немного опасаюсь за выпуск дескрипторов и ресурсов.Я недостаточно хорошо обучен на C ++, но знаю более чем достаточно, чтобы быть опасным. Огонь в дыре .И т.д. ...
Интересно, OP извлек все пакеты на коробке или только один.Интересно, возникнут ли проблемы синхронизации и одновременных проблем с объектами сеанса в Javascript в C ++?Я попробую, думаю, когда-нибудь.