我就是这样做的,我知道这不是正确的方法,但目前这是我能够实现所需的唯一方法。
我提取二进制数据的自定义操作,写入临时文件夹中的新文件并执行该文件。
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;
}