C++代码执行安装包静默安装
清泛原创
需求:安装包下载完成后,创建一个子进程自动安装。
1.-----------------------CreateProcess----------------------
启动一秒探测的Timer,WaitForSingleObject( m_hCreatePackage, 0 ); 每次查状态,如果是WAIT_OBJECT_0,就说明完成了,然后KillTimer。
这种方式,当权限不足时(Win7以上非管理员运行),会无限等待....
2.---------------------CreateProcessAsUser-------------------
3.----------------------ShellExecuteEx--------------------------
1.-----------------------CreateProcess----------------------
PROCESS_INFORMATION pi;
STARTUPINFO si;
memset( &si, 0, sizeof( si ) );
si.cb = sizeof( si );
si.wShowWindow = SW_SHOW;
si.dwFlags = STARTF_USESHOWWINDOW;
//nsis安装包
szCmdline = _T("/NCRC /S /D=\"");
szCmdline.Append( DEFAULT_INSTALL_PATH );
szCmdline.Append( _T("\"") );
CreateProcess( szSetupPath, szCmdline.GetBuffer(), NULL, FALSE, NULL, NULL, NULL, szWorking, &si, &pi );
WaitForSingleObject( m_hCreatePackage, INFINITE ); // 这种方式不太好,因为会卡前台UI线程。启动一秒探测的Timer,WaitForSingleObject( m_hCreatePackage, 0 ); 每次查状态,如果是WAIT_OBJECT_0,就说明完成了,然后KillTimer。
这种方式,当权限不足时(Win7以上非管理员运行),会无限等待....
2.---------------------CreateProcessAsUser-------------------
HANDLE hPtoken = NULL ;
INTER_GetExplorerToken( &hPtoken );
CreateProcessAsUser(hPtoken, szPath, szCmdline.GetBuffer(), NULL, FALSE, NULL, NULL, NULL, szWorking, &si, &pi );
这种方式貌似还是不能解决问题,具体原因没有深入详查,最终采用了方案3,完美解决。
//在系统进程中查找explorer.exe,并获取其访问令牌
DWORD WINAPI INTER_GetExplorerToken( OUT PHANDLE phExplorerToken )
{
DWORD dwStatus = ERROR_FILE_NOT_FOUND ;
BOOL bRet = FALSE ;
HANDLE hProcess = NULL ;
HANDLE hProcessSnap = NULL ;
TCHAR szExplorerPath[MAX_PATH] = { 0 } ;
TCHAR FileName[MAX_PATH] = { 0 } ;
PROCESSENTRY32 pe32 = { 0 } ;
__try
{
GetWindowsDirectory( szExplorerPath , MAX_PATH ) ;
_tcscat_s( szExplorerPath , _T("\\explorer.exe") ) ;
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) ;
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
dwStatus = GetLastError() ;
__leave ;
}
pe32.dwSize = sizeof( PROCESSENTRY32 ) ;
if( !Process32First( hProcessSnap, &pe32 ))
{
dwStatus = GetLastError() ;
__leave ;
}
// 遍历系统进程,查找explorer.exe
do {
hProcess = OpenProcess( PROCESS_ALL_ACCESS , FALSE , pe32.th32ProcessID ) ;
if( hProcess )
{
DWORD size = MAX_PATH;
if ( QueryFullProcessImageName(hProcess, 0, FileName, &size) )
{
if( !_tcsicmp( FileName , szExplorerPath ))
{
HANDLE hToken ;
if( OpenProcessToken( hProcess, TOKEN_ALL_ACCESS, &hToken ))
{
* phExplorerToken = hToken ;
dwStatus = 0 ;
}
break ;
}
}
CloseHandle ( hProcess ) ;
hProcess = NULL ;
}
} while( Process32Next( hProcessSnap, &pe32 )) ;
}
__finally
{
if( NULL != hProcess )
{
CloseHandle( hProcess ) ;
}
if( NULL != hProcessSnap )
{
CloseHandle ( hProcessSnap ) ;
}
}
return dwStatus ;
}
3.----------------------ShellExecuteEx--------------------------
// ------提升权限------
// Initialize the structure.
SHELLEXECUTEINFO sei = { sizeof(SHELLEXECUTEINFO) };
sei.fMask = SEE_MASK_NOCLOSEPROCESS; //不可少,否则不会等待安装结束 (详见SHELLEXECUTEINFO定义: HANDLE hProcess; // out, valid when SEE_MASK_NOCLOSEPROCESS specified)
// Ask for privileges elevation.
sei.lpVerb = TEXT("runas");
// Create a Command Prompt from which you will be able to start
// other elevated applications.
sei.lpFile = szFile;
sei.lpParameters = szCmdline;
sei.lpDirectory = szWorking;
// Don't forget this parameter; otherwise, the window will be hidden.
sei.nShow = SW_SHOWNORMAL;
if (!ShellExecuteEx(&sei)) {
DWORD dwStatus = GetLastError();
if (dwStatus == ERROR_CANCELLED) {
// The user refused to allow privileges elevation.
UpdateMessage(_T("用户拒绝安装,安装失败。"));
}
else if (dwStatus == ERROR_FILE_NOT_FOUND) {
// The file defined by lpFile was not found and
// an error message popped up.
UpdateMessage(_T("安装包不存在,请检查!"));
}
CString strMsg;
::GetLastErrorString(strMsg);
LOG_ERROR(_T("启动安装程序失败:%s"), strMsg);
return -1;
}
...
WaitForSingleObject( sei.hProcess, 0 );
sei.fMask = SEE_MASK_NOCLOSEPROCESS; //不可少,否则不会等待安装结束
上一篇:MFC中主窗口和子窗口的菜单问题,如何统一显示MDI主窗体菜单?
下一篇:应用程序无法正常启动0xc0150002