2010-06-23 35 views
2

鑑於MSI產品代碼,我想從已安裝的產品中獲取升級代碼(以及其他屬性)。我試圖通過調用MsiOpenProduct方法,然後MsiGetProductProperty()。安(略)的例子看起來是這樣的:MsiOpenProduct是從已安裝產品中讀取屬性的正確方法嗎?

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

這讓我的期望值,並從MSDN文檔來看,這似乎是做到這一點的一種有效方式:

的MsiOpenProduct功能打開 產品用於訪問產品數據庫的功能 。當處理不再需要 時,必須使用句柄將 MsiCloseHandle函數調用爲 。

但是,調用MsiOpenProduct()會彈出「Windows安裝程序準備安裝...」對話框。對MsiCloseHandle()的調用使它再次消失。

這讓我疑惑:

  • 什麼調用MsiOpenProduct()引擎蓋下呢?我不想觸發任何操作,我只想讀取屬性。
  • 我不介意彈出對話框,因爲這只是單元測試代碼,只要這沒有副作用。由於有許多單元測試可以做到這一點,所以它在連續快速打開和關閉手柄時仍然可以正常工作。
  • 儘管我偶然發現了MsiGetProductInfo方法,但似乎無法獲取升級代碼。我對嗎?
  • MsiOpenProduct是否正確讀取升級代碼等屬性?
+0

我得出了同樣的結論 - 我使用VBScript中的OpenProduct來獲取UpgradeCode(COM調用,與C++調用不同)。我通過設置頂級安裝程序對象的UILevel屬性來抑制您所說的GUI。我發現獲得升級代碼的唯一方式是通過WMI:'從Win32_Property選擇*屬性='UpgradeCode'。對於特定的產品代碼: 'SELECT * FROM Win32_Property WHERE Property ='UpgradeCode'AND ProductCode ='{B862B671-59FD-7457-AFA0-C738FB7ABD60}''。也許我應該在下面添加一個答案,儘管它是VBScript。 – 2018-02-05 02:18:27

回答

3

MsiOpenProduct應該沒問題只要你不運行任何序列或動作,它不會執行任何操作。如果你想沉默對話框,你可以小心使用MsiSetInternalUI()或MsiSetExternalUI()。

你可以拿,只要ProductCodeUpgradeCode是安全的靜態(即只要他們不被變換改變)的另一種方法,是找到使用MsiGetProductInfo(數據庫)和調用MsiOpenDatabase() 。不同的是,MsiOpenProduct()(或類似的MsiOpenPackage)應用安裝時使用的轉換並準備會話,而MsiOpenDatabase()不會。

+0

那麼這對我來說是完美的。 MsiGetProductInfo正是我所需要的。 – 2012-02-09 17:10:24

1

對於您想要的信息,聽起來像您可以調用:: MsiGetProductInfo()。 :: MsiOpenDatabase()是一個非常慢而:: MsiGetProductInfo()是(IIRC)更符合註冊表查找。

+0

這可能是真的,但正如我上面寫的,我發現沒有辦法通過MsiGetProductInfo獲取升級代碼。看來你只能查詢一組有限的屬性。有關屬性列表,請參閱http://msdn.microsoft.com/zh-cn/library/aa370130%28VS.85%29.aspx。 – Hatch 2010-07-12 11:17:53

+0

哦,你說得對。我錯誤地記住了列表中的UpgradeCode。 – 2010-07-16 16:14:00

+0

當我在尋找關於此問題的信息時,從未看到過這個問題。我使用WMI來檢索升級代碼,但是再次嘗試使用MSI API並且它可以工作(在我作爲單獨的答案在此添加的VBScript中顯示)。 MSI API的工作速度似乎比WMI快2-3倍,但速度仍然很慢。不是很好,至少可以說,但它確實報告我需要的東西。 **任何關於旋轉這麼多Session對象的想法?** JavaScript在這裏完全失敗,同時公開會話(可能是我可憐的JavaScript技能)的絆腳石。我從VBScript中看不到所有會話對象的副作用。 – 2018-02-05 02:56:33

0

有關於如何獲得使用PowerShell的的VBScriptWMI這裏的UpgradeCode信息的全面的答案:How can I find the Upgrade Code for an installed MSI file?

下面是使用VBScript/COM自動化快速,簡單的例子(MSI API,而不是WMI)以及OP討論的方法(使用OpenProduct方法 - 與Win32安裝程序功能相當的COM)。


正如我在上面的評論中所討論的,我只是添加這個小小的VBScript來做與OP在C++中一樣的功能。請注意,可以通過WMI(Win32_Product對象),COM automationWin32 C++ installer functions訪問Windows Installer

由於某種原因,包的UpgradeCode似乎無法直接從COM API或Win32 API獲得。很奇怪的,特別是因爲它是一個輸入參數的功能,如Installer.RelatedProducts - 它不是實際的通話應該是RelatedProducts(UpgradeCode)的文件中明確,但看在msi.IDL看到:StringList* RelatedProducts([in] BSTR UpgradeCode);

的WMI選項工作,但所以這個OpenProduct調用如下所示(這是顯着更快,看起來很安全 - 據我所知,WMI是完全只讀的 - 但天知道他們在做什麼「引擎蓋下」。他們是否在旋轉會話對象?或者他們是從WMI數據庫中讀取的?WMI確實「感覺」更安全)。

以下方法的優點在於,它將應用安裝時應用於有問題產品的所有變換。如果您想寫入磁盤而不是顯示消息框,並且不能查找文檔,那麼這裏有一個類似的VBScript,它可以將包信息寫入桌面文本文件:How can I find the product GUID of an installed MSI setup? - 在頁面上稍微向下,只需複製一個幾行和你是消息框免費)。

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" 

我曾嘗試在C++的Win32安裝程序的功能,以尋找任何其他方式獲取的UpgradeCode,但我看不到任何明顯。會話方法也應該用C++來工作,但是我對於句柄和資源的釋放有點擔心。我沒有用C++進行適當的便利訓練,但知道綽綽有餘是危險的。 火中的洞。等...

我想知道OP是否檢索到盒子上的所有包裝,或者只是一個包裝。我想知道Javascript中看到的時間問題和併發會話對象問題是否也會在C++中出現?我會放棄它,我想 - 總有一天。

相關問題