我有一个在安装过程中执行的.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>
谢谢。
答案 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;
}