0

我有一个要在安装期间执行的 .exe 文件。当 msi 文件由 bootstrapper(启动主 msi 文件的 .exe 文件)启动时执行良好,但由 msi 本身启动时无法正确执行。似乎这个问题与权限有关,因为我的引导程序在启动时获得了权限,如果我在具有权限的 cmd.exe 中执行 msi,它会很好地执行 .exe 文件。

当我从控制面板中的 ARP 菜单进入维护模式时,真正的问题来了。.exe 文件根据某些功能的动作状态执行。当我从引导程序启动的原始 msi 进入维护模式时它执行得很好(它有特权),但是当我从控制面板中的 ARP 菜单进入维护模式时执行得不好。

当我从控制面板中的 ARP 菜单进入维护模式时,我希望它能够同样好地执行。

以下是我的代码的一部分。

<CustomAction Id="CA1" BinaryKey="file.exe" ExeCommand="" Execute="deferred" Return="asyncNoWait" />
...
<Custom Action="CA1" Before="InstallFinalize"><![CDATA[&Feat1=3]]></Custom>

谢谢你。

4

2 回答 2

1

您的自定义操作已安排在 InstallInitialize 和 InstallFinalize 之间的延迟中。缺少的是需要设置为“否”的模拟属性。这将导致它在系统上下文中运行提升。目前它正在模拟开始安装的用户,如果该过程未提升,您的 EXE 将不会提升。

同样对于调用 EXE,我会查看WiX Quiet Execute Custom Action。最后,请务必阅读并理解Windows Installer 中自定义操作的安装阶段和脚本内执行选项

于 2013-09-04T14:59:57.600 回答
0

我就是这样做的,我知道这不是正确的方法,但目前这是我能够实现所需的唯一方法。

我提取二进制数据的自定义操作,写入临时文件夹中的新文件并执行该文件。

extern "C" UINT __stdcall InstallDrivers(MSIHANDLE hInstall)
{
//AssertSz(FALSE, "debug here");
//DebugBreak();

HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
HANDLE hFile = INVALID_HANDLE_VALUE;
BYTE* pbData = NULL;
DWORD cbData = 0, hProcess = 0;
char pwzFilename[MAX_PATH], szDriverType[MAX_PATH], pwzSentinelFilename[MAX_PATH], szIsInstalled[MAX_PATH];
LPWSTR szValueBuf = NULL, szIsHaspInstalled = NULL, szIsSentinelInstalled = NULL;
SHELLEXECUTEINFO ShExecInfo;
WINDOWPROCESSINFO info;

ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = _T("open");
ShExecInfo.lpParameters = NULL;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_SHOWNORMAL;
ShExecInfo.hInstApp = NULL;
ShExecInfo.hProcess = NULL;
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC | SEE_MASK_WAITFORINPUTIDLE;

hr = WcaInitialize(hInstall, "InstallDrivers");
ExitOnFailure(hr, "Failed to initialize");

WcaLog(LOGMSG_STANDARD, "Initialized.");
CreateDirectory("C:\\Temp", NULL);

strcpy_s(pwzFilename, "C:\\Temp\\HASPUserSetup.exe");

hr = ExtractBinary(L"Hasp", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 

DWORD cbWritten = 0;
if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

strcpy_s(pwzSentinelFilename, "C:\\Temp\\sentinel_setup.exe");
hr = ExtractBinary(L"Sentinel", &pbData, &cbData);
ExitOnFailure(hr, "failed to extract binary data");

if ((hFile = CreateFile(pwzSentinelFilename, GENERIC_WRITE,FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) 
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not create new temporary file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;  
} 

if ( !WriteFile(hFile, pbData, cbData, &cbWritten, NULL) )
{
    PMSIHANDLE hRecord = MsiCreateRecord(0);
    MsiRecordSetString(hRecord, 0, TEXT("Could not write to file"));
    MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_ERROR + MB_OK), hRecord);
    return ERROR_INSTALL_USEREXIT;
}

CloseHandle(hFile);

hr = WcaGetProperty(L"DRIVER", &szValueBuf);
ExitOnFailure(hr, "failed to get driver info");

wcstombs(szDriverType, szValueBuf, 260);
if (strcmp(szDriverType, "Hasp") == 0)
{   

    hr = WcaGetProperty(L"SENTINELINSTALLED", &szIsSentinelInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szValueBuf, 260);
    if (strcmp(szIsInstalled, "Sentinel Protection Installer 7.6.5") == 0)
    {
        ShExecInfo.lpFile = pwzSentinelFilename;
        ShellExecuteEx(&ShExecInfo);
        info.pid = GetProcessId(ShExecInfo.hProcess);
        info.hwnd = 0;
        AllowSetForegroundWindow(info.pid);
        EnumWindows(OnGetWindowByProcess, (LPARAM)&info);   
        SetWindowPos( info.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        if (info.hwnd != 0)
        {
            SetForegroundWindow(info.hwnd);
            SetActiveWindow(info.hwnd);
        }
        WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
        CloseHandle(ShExecInfo.hProcess);

    }
        ShExecInfo.lpFile = pwzFilename;
        ShellExecuteEx(&ShExecInfo);    
        info.pid = GetProcessId(ShExecInfo.hProcess);
        info.hwnd = 0;
        AllowSetForegroundWindow(info.pid);
        EnumWindows(OnGetWindowByProcess, (LPARAM)&info);
        SetWindowPos( info.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        if (info.hwnd != 0)
        {
            SetForegroundWindow(info.hwnd);
            SetActiveWindow(info.hwnd);
        }
        WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
        CloseHandle(ShExecInfo.hProcess);



}else
{
    hr = WcaGetProperty(L"HASPINSTALLED", &szIsHaspInstalled);
    ExitOnFailure(hr, "failed to get driver info");
    wcstombs(szIsInstalled, szIsHaspInstalled, 260);

    if (strcmp(szIsInstalled, "Sentinel Runtime") == 0)
    {
        ShExecInfo.lpFile = pwzFilename;
        ShellExecuteEx(&ShExecInfo);
        info.pid = GetProcessId(ShExecInfo.hProcess);
        info.hwnd = 0;
        AllowSetForegroundWindow(info.pid);
        EnumWindows(OnGetWindowByProcess, (LPARAM)&info);
        SetWindowPos( info.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        if (info.hwnd != 0)
        {
            SetForegroundWindow(info.hwnd);
            SetActiveWindow(info.hwnd);
        }
        WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
        CloseHandle(ShExecInfo.hProcess);


    }
        ShExecInfo.lpFile = pwzSentinelFilename;
        ShellExecuteEx(&ShExecInfo);
        info.pid = GetProcessId(ShExecInfo.hProcess);
        info.hwnd = 0;
        AllowSetForegroundWindow(info.pid);
        EnumWindows(OnGetWindowByProcess, (LPARAM)&info);   
        SetWindowPos( info.hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
        if (info.hwnd != 0)
        {
            SetForegroundWindow(info.hwnd);
            SetActiveWindow(info.hwnd);
        }
        WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
        CloseHandle(ShExecInfo.hProcess);       
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}

并提取二进制代码:

/********************************************************************
ExtractBinary - helper function 

********************************************************************/
HRESULT ExtractBinary(
__in LPCWSTR wzBinaryId,
__out BYTE** pbData,
__out DWORD* pcbData
)
{
HRESULT hr = S_OK;
LPWSTR pwzSql = NULL;
PMSIHANDLE hView;
PMSIHANDLE hRec;

// make sure we're not horked from the get-go
hr = WcaTableExists(L"Binary");
if (S_OK != hr)
{
    if (SUCCEEDED(hr))
    {
        hr = E_UNEXPECTED;
    }
    ExitOnFailure(hr, "There is no Binary table.");
}

ExitOnNull(wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be null");
ExitOnNull(*wzBinaryId, hr, E_INVALIDARG, "Binary ID cannot be empty string");

hr = StrAllocFormatted(&pwzSql, L"SELECT `Data` FROM `Binary` WHERE `Name`=\'%s\'", wzBinaryId);
ExitOnFailure(hr, "Failed to allocate Binary table query.");

hr = WcaOpenExecuteView(pwzSql, &hView);
ExitOnFailure(hr, "Failed to open view on Binary table");

hr = WcaFetchSingleRecord(hView, &hRec);
ExitOnFailure(hr, "Failed to retrieve request from Binary table");

hr = WcaGetRecordStream(hRec, 1, pbData, pcbData);
ExitOnFailure(hr, "Failed to read Binary.Data.");

LExit:
ReleaseStr(pwzSql);

return hr;
}
于 2013-09-04T11:53:39.277 回答