用Windows服务来启动带UI界面的程序 很多同学使用服务来单纯的启动另一个程序(WinExe,ShellExe,CreateProcess)结果发现我们的程序没界面但有进程,那是为什么呢?服务启动UI程序不能直接CreateProcess(),否则因为service session,程序UI不能看见,所以 我们需要拿到当前explorer.exe的token,然后CreateProcessAsUser模拟当前用户启动进程这样就可以显示界面了
第一步,得到explorer.exe环境的token DWORD INTER_GetExplorerToken( PHANDLE phExplorerToken ) { DWORD dwStatus = ERROR_FILE_NOT_FOUND; BOOL bRet = FALSE; HANDLE hProcess = NULL; HANDLE hProcessSnap = NULL ; char szExplorerPath[MAX_PATH] = { 0 }; char FileName[MAX_PATH] = { 0 }; PROCESSENTRY32 pe32 = { 0 }; try { hProcessSnap = ::CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ); if( hProcessSnap == INVALID_HANDLE_VALUE ) { dwStatus = GetLastError(); } else { pe32.dwSize = sizeof( PROCESSENTRY32 ); int bMore = ::Process32First(hProcessSnap, &pe32); while( bMore ) { if ( ::wcscmp(pe32.szExeFile, _T("explorer.exe")) == 0 ) { hProcess = ::OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID ); if( OpenProcessToken(hProcess , TOKEN_ALL_ACCESS , phExplorerToken) ) { dwStatus = 0; } else { dwStatus = GetLastError(); } break; } bMore = ::Process32Next( hProcessSnap, &pe32 ); } } } catch(...) { } if( hProcess ) { CloseHandle( hProcess ); } if( hProcessSnap ) { CloseHandle ( hProcessSnap ); } return dwStatus; } 第二步,启动程序 void RunProcess(CString szExeFile, CString szDirectory) { HANDLE hToken = NULL; if( INTER_GetExplorerToken( &hToken ) == 0 ) { PROCESS_INFORMATION pi = { 0 }; SECURITY_ATTRIBUTES sa = { 0 }; sa.nLength = sizeof( SECURITY_ATTRIBUTES ); STARTUPINFO si = { 0 }; si.dwFlags = STARTF_USESHOWWINDOW; si.cb = sizeof( STARTUPINFO ); si.wShowWindow = SW_SHOW; CreateProcessAsUser( hToken, szExeFile, NULL, &sa, &sa, FALSE, NORMAL_PRIORITY_CLASS| CREATE_NEW_CONSOLE, NULL, szDirectory, &si, &pi ); } } 最后,大家注意了我使用了CreateProcessAsUser 的 lpCurrentDirectory 参数,这个对希望使用配置文件(ini)来说很重要,如果不设置该参数那么所读取的配置的路径将会和你服务路径一样