使用属性抑制重启失败的 MsiConfigureFeature

问题描述

我正在尝试卸载我的功能并希望禁止重新启动,但它因错误 1618 而失败

   MsiOpenProductA(productCode,&handle))

    MsiSetPropertyA(handle,"REBOOT","ReallySuppress");
    MsiSetInternalUI(INSTALLUILEVEL_NONE,NULL);

    Ret = MsiConfigureFeatureA(
                            productCode,feature,INSTALLSTATE_ABSENT);
    if (ERROR_SUCCESS == Ret) {
        std::cout << "myFeature is uninstalled\n";
    }
    else {
        std::cout << "myFeature is not uninstalled "<<Ret<<std::endl;
    }

它因错误 1618 而失败,即另一个安装已经在进行中。在继续此安装之前完成该安装 我怀疑这是因为我打开了句柄。

任何人来到这里都会有很大帮助

解决方法

有关导致您的 error 1618 的原因的技术细节,请参阅我的其他回答 - 在我们处理此问题时,请查看此站点以查找奇怪的错误代码:https://www.magnumdb.com/)。


新版本:这是代码的另一个版本。它使用带有命令行设置的 ConfigureProductEx 来删除该功能。可能有更好的方法。 请测试这不会删除过多的功能Please double check the documentation here(有限测试):

程序:在运行以下示例之前,请执行以下操作:

  1. 以管理员身份运行(以管理员身份启动 Visual Studio)。
  2. 将下面的产品代码更新为您自己的。 How to find your product code (vbscript)。
#define WIN32_LEAN_AND_MEAN // Minimize includes from Windows.h
#include <windows.h>
#include <msi.h> // Windows Installer
#include <tchar.h> 

#pragma comment(lib,"msi.lib") // To make code link

int main()
{
    // NB! RUN CODE WITH ADMIN RIGHTS

    MsiSetInternalUI(INSTALLUILEVEL_NONE,NULL);

    // The below command line suppresses reboot and removes the specified feature
    const TCHAR commandline[] = _T("REBOOT=ReallySuppress REMOVE=FeatureNameToRemove");
    const TCHAR prodcode[39] = _T("{00000000-0000-0000-0000-000000000000}");

    UINT res = MsiConfigureProductEx(prodcode,INSTALLLEVEL_DEFAULT,INSTALLSTATE_DEFAULT,commandline);

    return res; // Error Codes: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376931(v=vs.85).aspx
}

链接:

,

简短回答:您不需要先打开产品,它会启动两个锁而不是一个。以下是您可以用来测试的 Visual Studio 2019 示例。


程序:在运行以下示例之前,请执行以下操作:

  1. 以管理员身份运行(以管理员身份启动 Visual Studio)。
  2. 将下面的产品代码更新为您自己的。 How to find your product code (vbscript)。
#define WIN32_LEAN_AND_MEAN // Minimize includes from Windows.h
#include <iostream>
#include <windows.h>
#include <msi.h> // Windows Installer

#pragma comment(lib,"msi.lib") // To make code link

int main()
{
   // NB! RUN CODE WITH ADMIN RIGHTS

    MsiSetInternalUI(INSTALLUILEVEL_NONE,NULL);

    // Put your own MSI's product code as the first parameter below:
    int r = MsiConfigureFeature(TEXT("{00000000-0000-0000-0000-000000000000}"),TEXT("FeatureName"),INSTALLSTATE_ABSENT);

    if (ERROR_SUCCESS == r) {
        std::cout << "myFeature is uninstalled\n";
    }
    else {
        std::cout << "myFeature is not uninstalled " << r << std::endl;
    }
}

Mutex:一次只能运行一个 MSI InstallExecuteSequence。当这个序列开始时设置一个 Mutex,然后在第一个序列被释放之前不能启动其他类型的序列。换句话说,OpenProduct 和 MsiConfigureFeature 都将尝试设置互斥锁,但第二次尝试失败。