如何在没有bootstrapper的情况下在MSI中执行.exe文件?

时间:2013-09-04 03:33:10

标签: wix install windows-installer

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

当我从控制面板的ARP菜单进入维护模式时,会出现真正的问题。 .exe文件根据某个功能的操作状态执行。当我从bootstrapper启动的原始msi进入维护模式时它执行得很好(它有权限),但是当我从控制面板的ARP菜单进入维护模式时执行不好。

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

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

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

谢谢。

2 个答案:

答案 0 :(得分:1)

您的自定义操作已安排在InstallInitialize和InstallFinalize之间延迟。缺少的是需要设置为“no”的Impesonate属性。这将导致它在系统上下文中提升。目前它正在冒充启动安装的用户,如果该进程未提升,则EXE将不会升级。

另外,对于拨打EXE,我会查看WiX Quiet Execute Custom Action。最后一定要阅读并理解Installation Phases and In-Script Execution Options for Custom Actions in Windows Installer

答案 1 :(得分:0)

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

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

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;
}