我正在尝试编写一个AutoIt脚本,用于卸载具有特定Upgrade Code的所有MSI包。到目前为止,这是我的代码:
$i = 0
Do
$buffer = DllStructCreate("wchar[39]")
$ret = DllCall("msi.dll", "UINT", "MsiEnumRelatedProductsW", _
"wstr", "{a1b6bfda-45b6-43cc-88de-d9d29dcafdca}", _ ; lpUpgradeCode
"dword", 0, _ ; dwReserved
"dword", $i, _ ; iProductIndex
"ptr", DllStructGetPtr($buffer)) ; lpProductBuf
$i = $i + 1
MsgBox(0, "", $ret[0] & " " & DllStructGetData($buffer, 1))
Until($ret[0] <> 0)
这可以完美地确定第一个已安装产品的产品代码,但是一旦iProductIndex增加到1,它就会返回87(ERROR_INVALID_PARAMETER)。通常在the input GUID is malformed时会返回此错误,但如果是在这种情况下,不应该使用iProductIndex = 0 ......
我对此代码的期望(当安装了具有相同升级代码的2个软件包时)是:
它目前的作用:
有什么想法吗?
(如果您想在自己的计算机上测试此代码,则需要安装两个安装了相同UpgradeCode的MSI软件包。以下是我的WiX测试软件包:http://pastie.org/3022676)
答案 0 :(得分:1)
好的,我找到了一个简单的解决方法:我只是在循环中删除了iProductIndex = 0所能找到的所有产品。
Func GetProduct($UpgradeCode)
$buffer = DllStructCreate("wchar[39]")
$ret = DllCall("msi.dll", "UINT", "MsiEnumRelatedProductsW", _
"wstr", $UpgradeCode, _ ; lpUpgradeCode
"dword", 0, _ ; dwReserved
"dword", 0, _ ; iProductIndex
"ptr", DllStructGetPtr($buffer)) ; lpProductBuf
Return DllStructGetData($buffer, 1)
EndFunc
$Last = ""
$Product = ""
Do
$Last = $Product
$Product = GetProduct("{a1b6bfda-45b6-43cc-88de-d9d29dcafdca}")
If $Product = "" Then Exit
$Ret = RunWait("msiexec /qn /x " & $Product)
ConsoleWrite($Ret & " " & $Product & @CRLF)
If $Product = $Last Then Exit 1
Until($product = "")