MsiEnumRelatedProducts使用iProductIndex>返回ERROR_INVALID_PARAMETER。 0

时间:2011-12-15 20:09:20

标签: autoit

我正在尝试编写一个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个软件包时)是:

  1. 打印“0&lt;第一产品代码&gt;”
  2. 打印“0&lt;第二产品代码&gt;”
  3. 打印“259”(ERROR_NO_MORE_ITEMS)
  4. 它目前的作用:

    1. 打印“0&lt;第一产品代码&gt;”
    2. 打印“87”(ERROR_INVALID_PARAMETER)
    3. 有什么想法吗?

      (如果您想在自己的计算机上测试此代码,则需要安装两个安装了相同UpgradeCode的MSI软件包。以下是我的WiX测试软件包:http://pastie.org/3022676

1 个答案:

答案 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 = "")