主要代码如下: DWORD FindSessionPid(LPSTR lpProcessName, DWORD dwSessionId) { DWORD res = 0; PROCESSENTRY32 procEntry; HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnap == INVALID_HANDLE_VALUE) { return res ; } procEntry.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hSnap, &procEntry)) { goto _end; } do { if (_stricmp(procEntry.szExeFile, lpProcessName) == 0) { DWORD winlogonSessId = 0; if (ProcessIdToSessionId(procEntry.th32ProcessID, &winlogonSessId) && winlogonSessId == dwSessionId) { res = procEntry.th32ProcessID; break; } } } while (Process32Next(hSnap, &procEntry)); _end: CloseHandle(hSnap); return res; } BOOL LaunchAppIntoDifferentSession(LPSTR lpCmdLine) { PROCESS_INFORMATION pi; STARTUPINFO si; BOOL bResult = FALSE; DWORD dwSessionId = 0, winlogonPid = 0; HANDLE hUserToken, hUserTokenDup, hPToken, hProcess; DWORD dwCreationFlags; // Log the client on to the local computer. typedef DWORD (WINAPI *__pfnWTSGetActiveConsoleSessionId)(); typedef BOOL (WINAPI *__pfnWTSQueryUserToken)( ULONG SessionId, PHANDLE phToken ); __pfnWTSGetActiveConsoleSessionId pfnWTSGetActiveConsoleSessionId = (__pfnWTSGetActiveConsoleSessionId)GetProcAddress(LoadLibraryA("kernel32.dll"), "WTSGetActiveConsoleSessionId"); __pfnWTSQueryUserToken pfnWTSQueryUserToken = (__pfnWTSQueryUserToken)GetProcAddress(LoadLibraryA("Wtsapi32.dll"), "WTSQueryUserToken"); if(pfnWTSGetActiveConsoleSessionId == NULL) { WriteLog("Not found api: WTSGetActiveConsoleSessionId\n"); return 0; } if(pfnWTSQueryUserToken == NULL) { WriteLog("Not found api: WTSQueryUserToken\n"); return 0; } dwSessionId = pfnWTSGetActiveConsoleSessionId(); winlogonPid = FindSessionPid("explorer.exe", dwSessionId); if(winlogonPid == 0) { winlogonPid = FindSessionPid("winlogon.exe", dwSessionId); } if(winlogonPid == 0) { WriteLog("Can't Find Explorer\n"); return 0; } //////////////////////////////////////////////////////////////////////// dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE; ZeroMemory(&si, sizeof(STARTUPINFO)); si.cb= sizeof(STARTUPINFO); si.lpDesktop = "winsta0\\default"; ZeroMemory(&pi, sizeof(pi)); TOKEN_PRIVILEGES tp; LUID luid; LPVOID TokenInformation; DWORD RetLen = 0; if( !pfnWTSQueryUserToken(dwSessionId, &hUserToken) ) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, winlogonPid); if(!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P, &hPToken)) { char pTemp[121]; sprintf(pTemp, "Process token open Error: %u\n", GetLastError()); WriteLog(pTemp); } if(hPToken == NULL) { WriteLog("Process tokenError: \n"); } } else { hPToken = hUserToken; } if(GetTokenInformation(hPToken, TokenLinkedToken, &TokenInformation, 4, &RetLen)) { hUserTokenDup = TokenInformation; } else { if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) { char pTemp[121]; sprintf(pTemp, "Lookup Privilege value Error: %u\n", GetLastError()); WriteLog(pTemp); } if(!DuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hUserTokenDup)) { char pTemp[121]; sprintf(pTemp, "DuplicateTokenEx Error: %u\n", GetLastError()); WriteLog(pTemp); } } LPVOID pEnv = NULL; if(CreateEnvironmentBlock(&pEnv, hUserTokenDup, TRUE)) { dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; } else { WriteLog("CreateEnvironmentBlock Failed\n"); pEnv = NULL; } // Launch the process in the client's logon session. bResult = CreateProcessAsUser( hUserTokenDup, // client's access token NULL, // file to execute lpCmdLine, // command line NULL, // pointer to process SECURITY_ATTRIBUTES NULL, // pointer to thread SECURITY_ATTRIBUTES FALSE, // handles are not inheritable dwCreationFlags, // creation flags pEnv, // pointer to new environment block NULL, // name of current directory &si, // pointer to STARTUPINFO structure &pi // receives information about new process ); // End impersonation of client. //GetLastError Shud be 0 int iResultOfCreateProcessAsUser = GetLastError(); if(bResult == FALSE && iResultOfCreateProcessAsUser != 0) { char pTemp[121]; sprintf(pTemp, "CreateProcessAsUser Error: %u\n", GetLastError()); WriteLog(pTemp); } if(pi.hProcess) { CloseHandle(pi.hProcess); } if(pi.hThread) { CloseHandle(pi.hThread); } //Perform All the Close Handles task if(hProcess) { CloseHandle(hProcess); } if(hUserToken) { CloseHandle(hUserToken); } if(hUserTokenDup) { CloseHandle(hUserTokenDup); } if(hPToken) { CloseHandle(hPToken); } if(pEnv) { DestroyEnvironmentBlock(pEnv); } return bResult; } 调用方式: LaunchAppIntoDifferentSession("c:\\windows\\notepad.exe"); 前提是有个服务进程已经启动,然后服务进程会以管理员模式(不需要用户点UAC的框)启动一个新的可以创建窗口的进程。 安装这个服务需要点UAC的框,所以不是什么不可公开的思路。好处就一点:每次自启动的进程,不需要再让用户点UAC框了