清泛IT社区

标题: C++代码执行安装包静默安装 [打印本页]

作者: zqp2013    时间: 2015-01-07 15:22
标题: C++代码执行安装包静默安装
本帖最后由 zqp2013 于 2015-1-8 10:19 编辑

需求:安装包下载完成后,创建一个子进程自动安装。

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安装包(http://bbs.tsingfun.com/forum-55-1.html)
        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 );










欢迎光临 清泛IT社区 (https://bbs.tsingfun.com/) Powered by Discuz! X3.3