用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)来说很重要,如果不设置该参数那么所读取的配置的路径将会和你服务路径一样