簡體   English   中英

如何找到已安裝 MSI 文件的升級代碼?

[英]How can I find the Upgrade Code for an installed MSI file?

在某些情況下,可能需要檢索已部署包的 MSI 升級代碼

常見場景:

  • 我接手了別人的 MSI 項目,我需要確定哪些升級代碼用於已經存在的先前版本。 這是處理升級方案所必需的。 我在任何地方都沒有發布檔案
  • 我在開發過程中不小心更改了我的 WiX 包的升級代碼幾次,我需要在“野外”找到所有升級代碼版本。 我不知道升級代碼應該在版本之間保持穩定

這是一個Q/A 風格的問題

這個問題以前在各種化身中出現過,但這不是重復的 我正在發布一種使用主 MSI 自動化界面(或嚴格來說是 WMI)的方法。 應該比以前答案中基於注冊表的方法更可靠 這個答案還試圖總結其他檢索方法。

MSI 升級代碼檢索(通過 PowerShell / WMI)

卸載? : Via Upgrade Code, Via Product Code, Via Product Name, etc...

下面的PowerShell 腳本應檢索您機器上安裝的所有相關產品代碼升級代碼產品名稱(表輸出)。

輸出截圖(完整腳本如下):

外殼輸出

這些是直接來自相關機器上的Windows Installer 數據庫真實實時值 不需要任何轉換或解釋。 我們正在通過適當的 API。

技術說明! :請注意,直接在原始 MSI 文件(屬性表)或 WiX 源文件中檢查屬性可能與實際安裝的值不匹配,因為可以在安裝時通過轉換(更多信息如下)或命令中指定的屬性值覆蓋屬性線。 這個故事的寓意是:盡可能直接從系統中檢索屬性值。

快速免責聲明:在極少數情況下,運行腳本會觸發 Windows Installer 自我修復。 在下面的“免責聲明部分”中閱讀更多內容。 只是一個潛在的麻煩,但請閱讀免責聲明。

作為題外話,還有一個單行 PowerShell 命令,它將僅檢索產品代碼和升級代碼 - 不包括包名稱。 對於某些用戶來說,這實際上可能就足夠了(不過,我會推薦下面的完整腳本)。 在下面的部分中有此單行輸出的屏幕截圖。 注意:此命令比較大的腳本出現得快得多(“值”字段是升級代碼)。 另請注意:據我所知,沒有相關升級代碼的產品代碼不會顯示 - 它們將在較大的腳本中顯示:

gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value

要運行下面的完整 PowerShell 腳本:

  1. 啟動 PowerShell按住 Windows 鍵,點擊 R,松開 Windows 鍵,輸入“powershell”並按 OK 或按 Enter 鍵)。
  2. 完整復制下面的腳本,然后在 PowerShell 窗口中右鍵單擊
  3. 這應該會啟動腳本,並且需要很長時間才能運行
  4. 請報告任何問題。 我不是 PowerShell 專家 - 我是一名部署專家而不是編碼員,但腳本應該可以完成這項工作。
  5. 性能說明:我只是得到了整個Win32_Product WMI 對象
    • 櫻桃采摘特性似乎實際上使它稍微變慢了(VBScript 測試)。
    • 我想無論如何我們都需要獲取所有行,而櫻桃采摘列只是額外的提升?
    • 對於Win32_Property,我們過濾行和列(升級代碼只是許多行類型之一)。 為緩慢的操作做好准備,WMI 非常慢。
$wmipackages = Get-WmiObject -Class win32_product
$wmiproperties = gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"
$packageinfo = New-Object System.Data.Datatable
[void]$packageinfo.Columns.Add("Name")
[void]$packageinfo.Columns.Add("ProductCode")
[void]$packageinfo.Columns.Add("UpgradeCode")

foreach ($package in $wmipackages) 
{
    $foundupgradecode = $false # Assume no upgrade code is found

    foreach ($property in $wmiproperties) {

        if ($package.IdentifyingNumber -eq $property.ProductCode) {
           [void]$packageinfo.Rows.Add($package.Name,$package.IdentifyingNumber, $property.Value)
           $foundupgradecode = $true
           break
        }
    }
    
    if(-Not ($foundupgradecode)) { 
         # No upgrade code found, add product code to list
         [void]$packageinfo.Rows.Add($package.Name,$package.IdentifyingNumber, "") 
    }
}

$packageinfo | Sort-Object -Property Name | Format-table ProductCode, UpgradeCode, Name

# Enable the following line to export to CSV (good for annotation). Set full path in quotes
# $packageinfo | Export-Csv "[YourFullWriteablePath]\MsiInfo.csv"

# copy this line as well

在遠程機器上運行

  • 擴展上面的腳本以在遠程機器上運行應該相對容易,但我目前還沒有准備好正確測試它。
  • 下面的信息有點亂,如果不明白或不清楚,請告訴我。
  • 真正的 Windows 域中,它應該(理論上)只是將遠程機器添加到 WMI 調用本身(並遍歷機器列表 - 請參見下面的模型)。 至關重要的是:您應該使用真實的域管理員帳戶來運行查詢 有可能我在下面列出的使 WMI 在工作組環境中工作的更改也可能需要某些域,我不知道(防火牆規則和 UAC 注冊表調整)。 我猜想一個真正的域管理員帳戶應該具有所需的權限和訪問權限。
  • WMI 中的遠程連接受(至少) Windows 防火牆DCOM 設置CIMOM 設置用戶帳戶控制 (UAC) (以及任何其他非 Microsoft 因素的影響 - 例如真實防火牆、第三方軟件防火牆、各種安全軟件)種類等...)。 以下是一些細節:
  • 非域網絡(小型辦公室、家庭等)中,您可能必須將用戶憑據直接添加到 WMI 調用中才能使其工作。 並且您可能必須在相關機器上擁有“真正的管理員權限”才能使查詢在家庭網絡(工作組)中遠程運行。 我聽說內置的管理員帳戶沒有任何 UAC 問題,但我從未嘗試過。 在我看來:不要使用這個帳戶。
    • 在我的測試中,我必須 ( 1 ) 更新 Windows 防火牆規則和 ( 2 ) 禁用遠程 UAC 訪問令牌過濾並在遠程系統上使用真實的本地管理員帳戶。 請注意,我不推薦這些更改中的任何一個,只是報告對我有用的內容。
    • 更改 1 :Windows 防火牆,運行命令(cmd.exe,以管理員身份運行): netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes- 請參閱此命令行鏈接以禁用此新如果您只是在測試,請再次使用規則。基本上只需設置 enable=no)。 請參閱鏈接的來源,了解可能也適用的更具限制性的規則。
    • 更改 2 :禁用遠程 UAC 訪問令牌過濾:您需要設置以下注冊表值: HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\ LocalAccountTokenFilterPolicy = 1來源- 中頁,后半部分)。 我設置了一個 32 位的 DWORD。

在遠程系統上進行這些更改后,我還通過提示用戶$Cred = Get-Credential向每個調用添加了用戶憑據。 還有更多用於定義用戶憑據的高級選項,如此處所述: Pass password into -credential (和此處)。 為了測試運行,這里有一個小測試腳本。 復制下面的所有行,修改遠程機器名稱並通過右鍵單擊粘貼到 PowerShell(系統將提示您輸入憑據):

$Cred = Get-Credential
gwmi -ComputerName RemoteMachineName -credential $Cred -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value
# copy this line too

對於上面的大型 PowerShell 腳本,在Windows 域中的多台機器上遠程運行的基本添加可能是這樣的(我不會更新上面的腳本,因為我無法真正正確地測試它)。 請記住更新腳本頂部的遠程計算機名稱列表並使用域管理員帳戶運行:

# DOMAIN NETWORK: mock-up / pseudo snippet ONLY - lacks testing, provided "as is"
$ArrComputers = "Computer1", "Computer2", "Computer3"
foreach ($Computer in $ArrComputers) 
{
    # here we modify the WMI calls to add machine name
    $wmipackages = Get-WmiObject -Class win32_product -ComputerName $Computer
    $wmiproperties = gwmi  -ComputerName $Computer -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"

    # the rest of the above, large script here (minus the first 2 WMI lines)
}

為非域網絡調整相同的機器循環,您可以向 WMI 調用添加憑據。 類似這樣的事情(系統會提示您輸入每台機器的憑據 - 這可能會令人困惑)。 請記住更新腳本頂部的遠程計算機名稱列表,並在目標框上使用具有本地管理員權限的帳戶:

# WORKGROUP NETWORK: mock-up / pseudo snippet ONLY - lacks testing, provided "as is"
$ArrComputers = "Computer1", "Computer2", "Computer3"
foreach ($Computer in $ArrComputers) 
{
     $Cred = Get-Credential

     # here we modify the WMI calls to add machine name AND credentials
     $wmipackages = Get-WmiObject -Class win32_product -ComputerName $Computer -credential $cred
     $wmiproperties = gwmi  -ComputerName $Computer -credential $cred -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'"

     # the rest of the above, large script here (minus the first 2 WMI lines) 
}

真正的答案到此結束 我相信上面較新的腳本應該涵蓋大多數用例,但我也會保留下面的內容,因為它並沒有過時,只是效率可能不如上面的腳本。 閱讀它可能會重復。

如果您想在運行時從您自己的應用程序中檢索單個升級代碼,下面用於檢索單個升級代碼而不是整個列表的腳本可能會很有趣。 我會留下那些較舊的內容。

免責聲明:上述腳本使用 WMI,當您訪問類Win32_Product 時,它會觸發對已安裝包完整性檢查 這很慢,並且在非常特殊的情況下會觸發 MSI 自我修復。 如果您要參加重要會議,這可不好:-)。 幸運的是,您應該能夠取消任何觸發的自我修復(但在您完成修復之前,您的查詢可能不會完成)。 快速上下文鏈接(用於保管)。

恕我直言:不要讓這阻止您使用 WMI - 這只是一個煩惱。 注意:下面描述的 PowerShell 和 VBScript 方法都使用 WMI,也可能觸發此問題。


檢索未安裝的 MSI 文件的升級代碼

如果您需要未安裝在您的機器上的 MSI 軟件包的升級代碼,請閱讀底部的“手動檢索升級代碼”部分以獲取多個選項(主要查看 MSI 文件本身,或其源文件用於編譯它)。

從原始 MSI 安裝文件本身或從用於編譯 MSI 的 (WiX) 源獲取已安裝軟件包的升級代碼是不安全的,因為可以在安裝時使用轉換覆蓋升級代碼(詳細信息在下面的文本中 - 轉換是在安裝時應用的小數據庫片段,有關詳細信息,請參閱 Symantec 鏈接)。

升級代碼的編程檢索依賴於WMI ,您可以使用PowerShellVBScript來調用WMI 下面介紹這兩種方法。 本質上,運行以下WMI 查詢以檢索指定產品代碼的升級代碼:

SELECT * FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='{YourProdGuid}'

它與用於 VBScript 和 PowerShell 的查詢相同。 您還可以使用諸如WMIExplorer.exe類的工具將其作為直接 WMI 查詢運行。 一個非常有用的工具 - 強烈推薦。 我相信這是他們的網站: https : //github.com/vinaypamnani/wmie2/releases


通過 PowerShell / WMI 檢索單個升級代碼

您可以檢索指定產品代碼的單個升級代碼,而不是輸出包含所有產品代碼和升級代碼的整個表。 如果您嘗試從自己的應用程序代碼內部進行檢索,這很好(那么它只是一個標准的 WMI 查詢,與 PowerShell 無關)。

下面是通過 PowerShell 完成的單個升級代碼檢索(啟動 PowerShell:按住 Windows 鍵,點擊 R,松開 Windows 鍵,輸入“powershell”並按 OK 或按 Enter 鍵):

gwmi -Query "SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='{YourGuid}'" | Format-Table Value

輸出應該是這樣的(可能有點難以閱讀,我應該使用更大的字體):

使用 PowerShell 檢索升級代碼 - 帶注釋

上述查詢中指定的產品代碼用於“ Windows SDK Intellidocs ”。 您顯然必須將其替換為您自己的產品代碼 guid。 要查找您需要傳入的產品代碼,您還可以使用 PowerShell 查詢,如下所述: 如何找到已安裝的 MSI 設置的產品 G​​UID?

返回的升級代碼直接來自真實的 Windows Installer 注冊表數據庫。 它不需要進一步的處理或解釋或手動轉換步驟 即使在安裝 MSI 時轉換更改了原始升級代碼,它也是正確的(有關轉換問題的詳細信息如下)。

更新,特別注意:在沒有不必要地復雜化的情況下,我相信我在 WMI 中發現了一個非常具體的錯誤。 當原始 MSI 沒有升級代碼集,而您通過轉換添加一個時,WMI 似乎根本不報告升級代碼。 但是:如果原始 MSI 具有升級代碼,並且您在轉換中覆蓋它,WMI 將報告轉換的升級代碼(這是預期的)。 我確實看到了這一點,但需要再用一個測試包進行驗證才能確定。 故事寓意:始終在您的 MSI 中設置升級代碼! 然后你永久地避免了整個問題。 並且不要自動生成它 - 對其進行硬編碼(閱讀下面的“升級代碼的手動檢索”以獲得解釋)。


使用 VBScript/WMI 檢索單個升級代碼(傳統方法)

下面的 VBScript 解決方案沒有任何問題——它甚至比 PowerShell 有一些優勢——盡管 VBScript 現在是一種傳統技術。 好處是它應該適用於所有機器,即使 .NET 框架丟失(或鎖定),以及 PowerShell 丟失(或鎖定)的機器。 這是一個過時但可行的解決方案,非常靈活(除非 VBScript 也被鎖定,但所有現代操作系統版本都完全支持 VBScript)。

為了盡可能簡單地檢索升級代碼,我創建了一個“准系統 VBScript ”,它應該可以解決問題。 它尚未針對遠程計算機進行測試,即使 WMI 設計上應該能夠這樣做。 該腳本旨在在安裝了未知升級代碼的神秘 MSI 的系統上運行。

此 VBScript 需要輸入產品代碼(運行腳本時顯示的輸入對話框),然后它將繼續查找相應的升級代碼(如果有)。 如上所述,要查找 MSI 的產品代碼,您可以使用以下方法: 如何找到已安裝 MSI 設置的產品 G​​UID? . 獲得產品代碼 (guid) 后,您可以在目標計算機上運行此 VBScript,幾秒鍾后您應該會收到升級代碼。 WMI 檢索可能非常緩慢。

'
' Purpose: Barebone / minimal VBScript implementation to allow retrieval of MSI UpgradeCodes via WMI.
'
' Version: 0.2, September.2017 - Stein Åsmul.
'
' Notes:
'
'  - As it stands, this script is intended to be run interactively (WScript).
'  - Conversion to run via CScript should be trivial (nothing ever is...)
'  - The script will ask the user to provide a valid product GUID for an installed MSI.
'  - To find a valid product GUID for your system, perhaps see this SO answer: https://stackoverflow.com/a/29937569/129130
'  - The script does not RegEx anything to check for valid GUID format (this is barebone - as terse as possible,
'    with as little as possible included that can break).
'
' UPDATE: for information on remote running, check "Running on remote machines" section here:
' https://stackoverflow.com/a/46637095/129130 (firewall and registry change seems to be needed).

strComputer = "."
' Remote connections was NOT tested for this script. In principle you should just add the machine name to "strComputer" above.
' AFAIK you must have "real" admin rights on the box you try to connect to. Many users report intermittent problems running remote WMI.
' Remote connections in WMI are affected by the Windows Firewall, DCOM settings, and User Account Control (UAC).
'    - Setting up a Remote WMI Connection: https://msdn.microsoft.com/en-us/library/aa822854(v=vs.85).aspx
'    - Connecting to WMI on a Remote Computer: https://msdn.microsoft.com/en-us/library/aa389290(v=vs.85).aspx
'    - Perhaps useful: https://social.technet.microsoft.com/Forums/lync/en-US/05205b52-0e43-4ce3-a8b8-58ec4c2edea5/wmi-generic-failure-when-accessing-win32product-remotely?forum=winserverManagement
'    - Maybe it is also worth noting that I think WMI queries can be slow enough to trigger timeouts,
'      and then you have the old favorite: intermittent bugs.

Set owmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

' User interaction
productcode = InputBox("Please paste or type in the product code for the product whose upgrade code you want " + _
                       "to retrieve (not case sensitive, a blank product code will abort the script)." + vbNewLine + vbNewLine + _
                       "Please note that the script can take up to a minute to run due to WMI's slowness.", "UpgradeCode retrieval:")
If productcode = vbCancel Or Trim(productcode) = "" Then
   WScript.Quit(0)
End If

' Run WMI call and verify that it completes successfully.
On Error Resume Next
Set upgradecode = owmi.ExecQuery("SELECT Value FROM Win32_Property WHERE Property='UpgradeCode' AND ProductCode='" & productcode & "'")
If (Err.number <> 0) Then
   MsgBox "The WMI query failed, this is a critical error - aborting.", vbCritical, "Fatal error."
   WScript.Quit(2) ' Following exit code "standard" from MSI SDK automation samples
End If
On Error GoTo 0

' Report results.
Select Case upgradecode.count

   Case 0
       ' We have to provide a separate message for this state, since some packages may not have an UpgradeCode.
       ' However, the product GUID could also have been misspelled.
       MsgBox "No UpgradeCode was found, are you sure you entered the correct product GUID?" & vbNewLine & vbNewLine & _
              "Note: It is possible for a product to NOT have an UpgradeCode.", vbInformation, "No UpgradeCode found."

   Case 1
      ' The "default state" - should cover almost all normal packages.

      ' Only one upgrade code should have been retrieved, and it can be referenced by upgradecode.ItemIndex(0).Value on newer systems 
      ' (Vista and later), but on XP this apparently does not work (never tested by me), for compatibility we use a standard For Each 
      ' enumeration instead. Source: https://stackoverflow.com/questions/2378723/get-first-record-from-wmi-execquery

      For Each u in upgradecode
        Msgbox "The Upgrade Code is: " & u.Value & vbNewLine & vbNewLine & _
              "Just press CTRL + C to copy all text in this dialog (then paste to notepad or similar to extract the GUID).", _
              vbInformation, "UpgradeCode found."
          ' Exit For
      Next

   Case Else
       ' Should never get here - let us know if you do get this message.
       MsgBox "An error occurred, the query returned more than one result. There can only be one UpgradeCode. " & _ 
              "Please report this error on StackOverflow", vbInformation, "Error while retrieving UpgradeCode."
End Select

檢索機器上的所有升級代碼和產品代碼

我應該提到,我有一個大型 VBScript,它將為它運行的機器上所有已安裝的 MSI 包生成一個綜合的 HTML 報告 這包括所有升級代碼和相關產品代碼列表(共享相同升級代碼的產品代碼)。 但是,我對代碼不太滿意(我是部署專家,而不是編碼員)。 該腳本太大、太慢且未經測試無法使用,因此我創建了上面找到的基本 VBScript 來僅對單個包進行檢索。 此腳本更易於測試和修改以供您自己使用。 如果有興趣,我可以提供這個大型 VBScript 進行測試。 除了單個 HTML 文件輸出到“我的文檔”之外,它是只讀的。 也應該可以修改此腳本以在遠程計算機上使用。

一行 PowerShell 命令可用於檢索所有產品代碼和相關升級代碼,但此輸出填充缺少產品名稱。 為了完整起見,我將其包含在此處:

gwmi -Query "SELECT ProductCode,Value FROM Win32_Property WHERE Property='UpgradeCode'" | Format-Table ProductCode,Value

輸出將與此類似(“值”字段是升級代碼 - 據我所知,不會顯示沒有關聯升級代碼的產品代碼):

輸出所有升級代碼和產品代碼


手動檢索升級代碼

本節列出了一些“手動方式”來檢索不需要任何編碼或命令行的升級代碼。 這些手動方法不是推薦的方法。 我包括它們只是因為這試圖成為“參考答案”。 應該提供幾個不同的選項。 我的建議是使用上面提供的 PowerShell 或 VBScript。

話雖如此,升級代碼通常不應跨產品版本更改,因此您可以嘗試在 MSI 文件本身或用於編譯它的源代碼中找到的代碼,如下所述。 已經多次提到的問題是轉換可以在安裝時更改升級代碼,因此如果您想確保找到正確的升級代碼,則需要以編程方式檢索升級代碼。 除非您嘗試從系統上未安裝的 MSI 獲取升級代碼。 然后您只需要一個 MSI 文件查看器,如下面的要點 1 中所述。

轉換只是一個數據庫片段,其中包含在安裝時應用於原始 MSI 的更改 它是一種主要用於企業應用程序打包的工具,用於修改安裝程序,而無需直接修改 MSI 文件。 轉換的擴展名為.mst 通過轉換更改升級代碼是不尋常的,但並非聞所未聞 - 特別是對於企業重新打包。 極少數情況下,應用程序打包者可能會有意更改升級 guid,以使他們能夠為已安裝的軟件包提供自己的升級(而不是直接依賴供應商更新)。 很少見,但我已經看到它完成了。 這是否是一件好事,值得商榷。

查找 MSI 升級代碼的簡單手動方法

  1. 雖然很明顯,但找到升級代碼的最簡單方法是打開用於安裝產品的原始 MSI ,然后在屬性表中找到升級代碼 您所需要的只是一個能夠打開 MSI 文件的工具。 這里有一些工具: 要使用什么安裝產品? InstallShield、WiX、Wise、Advanced Installer 等 如果您安裝了 Visual Studio,您最快的選擇可能是 Orca(搜索Orca-x86_en-us.msi並安裝它 - 這是 Microsoft 自己的官方 MSI 查看器和編輯器),或者如果您沒有安裝 Visual Studio,則可能是 Super Orca (按照上面的鏈接找到它)。

  2. 如果您是使用 WiX(或任何其他部署工具)的開發人員,您顯然可以在用於編譯 MSI 的WiX 源文件(或 Installshield 源、Advanced Installer 源或您使用的任何部署工具)中輕松找到升級代碼使用)。

    • 讓我們不要在這里用太多善意的建議來混淆主要問題,但是您顯然應該在源代碼硬編碼升級代碼,並且永遠不要自動生成它
    • 升級代碼定義了“相關產品系列”,並且應該在不同版本(版本)之間保持穩定。 在大多數情況下,它也應該跨語言版本保持穩定。 確切的設置取決於部署要求。
    • 如果產品應該能夠並排存在,您通常對需要共存的產品有不同的升級代碼。
    • 經驗法則:盡可能長時間保持升級代碼穩定。 當需求絕對需要時更改它們。
    • 總結一下:永遠不要對具有自己“生命周期”且彼此沒有實際關系的不同產品使用相同的升級代碼。 他們沒有關系。 這與保持相關產品的升級代碼穩定一樣重要。 思考“生命周期”與“家庭關系”與“共存”的要求。
    • 這是一個很大的題外話,回到手頭的問題:查找升級代碼。
  3. 即使您沒有原始 MSI,甚至可以在%SystemRoot%\\Installer文件夾中從原始安裝中找到緩存的 MSI 這里的 MSI 文件有一個神秘的十六進制名稱,但它們只是用於安裝不同產品的原始 MSI 文件的副本 - 緩存在安全的地方,可用於修改、修復和卸載操作。 不管你做什么,都不要在這個文件夾里亂搞。 永遠,永遠不要刪除任何東西 您可以通過選擇第一個 MSI 文件並檢查 Windows 資源管理器狀態欄來找到安裝產品的 MSI,舊 Windows 版本的產品名稱是什么。 在 Windows 10 中,您似乎可以使用指針將鼠標懸停在 MSI 上,然后您會看到一個包含一些 MSI 詳細信息的彈出窗口。 然后您只需單擊列表,直到找到正確的產品並打開 MSI 並在屬性表中找到升級代碼。

  4. 有些人使用注冊表來讀取升級代碼: 如何在 C# 中找到已安裝應用程序的升級代碼? . 在我看來,這不是一個好方法,有更好的方法 - 例如如上所述僅使用 PowerShell。 不需要對打包的 GUID (這是 Windows Installer 注冊表數據庫中使用的 GUID 格式)進行所有這些轉換和解釋。

這應該完成主要的“手動方法”以快速檢索升級代碼。 只是一些有時足夠好的武器庫方法。 可能還有幾種方法我已經忘記了。

確實更喜歡程序化方法,但是如果您匆忙工作並且沒有可用的所有工具,那么一些手動選項是不錯的選擇。 然而,其中一些手動方法需要比 PowerShell 命令行更多的工具(如果您對某人的機器執行“支持任務”,則需要一個 MSI 文件查看器,該查看器並不總是在盒子上可用)。 是時候使用 PowerShell 了(是的,我也覺得過時了)。

順便說一下,MSI 文件本質上是精簡的 SQL Server 數據庫,存儲為 COM 結構的存儲文件(MS Office 文件格式)。 本質上是文件中的文件系統,具有各種類型的存儲流。

如果您被困在沒有 MSI 查看器的機器上,您可以直接從 PowerShell 查詢緩存的 MSI 數據庫:

為了滿足您直接使用 WMI 的要求,或者在那些時候您只需要一次性使用 Powershell(或需要使用 .bat 或其他文件),請使用 wmic:

    C:\>wmic product list brief
    Caption                                                                                              IdentifyingNumber                       Name                                                                                                 Vendor                          Version
        Sourcetree                                                                                           {1B05DFFD-1DB9-48CD-9265-F3976512A579}  Sourcetree                                                                                           Atlassian                       2.6.10.0
        Microsoft Office Access database engine 2007 (English)                                               {90120000-00D1-0409-0000-0000000FF1CE}  Microsoft Office Access database engine 2007 (English)                                               Microsoft Corporation           12.0.4518.1031
        Office 16 Click-to-Run Extensibility Component                                                       {90160000-008C-0000-0000-0000000FF1CE}  Office 16 Click-to-Run Extensibility Component    

有多種格式和輸出選項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM