河南英文网站建设公司,设计师招聘网站,网站系统建设招标公告,wordpress自定义文章参数计划任务不显示UI的问题
1、原因#xff1a;
在windows7以上系统#xff0c;使用system权限启动的进程默认是没有ui界面#xff0c;这是windows系统出于安全考虑的限制。防止用户在高权限下误删重要的文件。
2、解决方案#xff1a;
1、降权
解决的办法#xff1a;降…计划任务不显示UI的问题
1、原因
在windows7以上系统使用system权限启动的进程默认是没有ui界面这是windows系统出于安全考虑的限制。防止用户在高权限下误删重要的文件。
2、解决方案
1、降权
解决的办法降权即将权限降低。
下面给出降权的实例代码
本质上是拿到当前用户的token才能降权成功。
DWORD GetActiveSessionID() {DWORD dwSessionId 0;PWTS_SESSION_INFO pSessionInfo NULL;DWORD dwCount 0;WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, pSessionInfo,dwCount);for (DWORD i 0; i dwCount; i) {WTS_SESSION_INFO si pSessionInfo[i];if (WTSActive si.State) {dwSessionId si.SessionId;break;}}WTSFreeMemory(pSessionInfo);return dwSessionId;
}const wstring GetAppPath() {static wstring szRootPath;if (szRootPath (L)) {TCHAR szPath[_MAX_PATH];GetModuleFileName(NULL, szPath, _MAX_PATH);wstring strFullPath szPath;szRootPath strFullPath;}return szRootPath;
}BOOL TriggerAppExecute(std::wstring wstrCmdLine /*, INT32 n32ExitResult*/) {DWORD dwProcesses 0;BOOL bResult FALSE;DWORD dwSid GetActiveSessionID();DWORD dwRet 0;PROCESS_INFORMATION pi;STARTUPINFO si;HANDLE hProcess NULL, hPToken NULL, hUserTokenDup NULL;if (!WTSQueryUserToken(dwSid, hPToken)) {PROCESSENTRY32 procEntry;DWORD dwPid 0;HANDLE hSnap CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (hSnap INVALID_HANDLE_VALUE) {return FALSE;}procEntry.dwSize sizeof(PROCESSENTRY32);if (Process32First(hSnap, procEntry)) {do {if (_wcsicmp(procEntry.szExeFile, (Lexplorer.exe)) 0) {DWORD exeSessionId 0;if (ProcessIdToSessionId(procEntry.th32ProcessID, exeSessionId) exeSessionId dwSid) {dwPid procEntry.th32ProcessID;break;}}} while (Process32Next(hSnap, procEntry));}CloseHandle(hSnap);// explorer进程不存在if (dwPid 0) {return FALSE;}hProcess ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwPid);if (hProcess NULL) {return FALSE;}if (!::OpenProcessToken(hProcess, TOKEN_ALL_ACCESS_P, hPToken)) {CloseHandle(hProcess);return FALSE;}}if (hPToken NULL) {return FALSE;}TOKEN_LINKED_TOKEN admin;bResult GetTokenInformation(hPToken, (TOKEN_INFORMATION_CLASS)TokenLinkedToken,admin, sizeof(TOKEN_LINKED_TOKEN), dwRet);if (!bResult) // vista 以前版本不支持TokenLinkedToken{TOKEN_PRIVILEGES tp;LUID luid;if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, luid)) {tp.PrivilegeCount 1;tp.Privileges[0].Luid luid;tp.Privileges[0].Attributes SE_PRIVILEGE_ENABLED;}//复制tokenDuplicateTokenEx(hPToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification,TokenPrimary, hUserTokenDup);} else {hUserTokenDup admin.LinkedToken;}LPVOID pEnv NULL;DWORD dwCreationFlags CREATE_PRESERVE_CODE_AUTHZ_LEVEL;// hUserTokenDup为当前登陆用户的令牌if (CreateEnvironmentBlock(pEnv, hUserTokenDup, TRUE)) {//如果传递了环境变量参数CreateProcessAsUser的// dwCreationFlags参数需要加上CREATE_UNICODE_ENVIRONMENT//这是MSDN明确说明的dwCreationFlags | CREATE_UNICODE_ENVIRONMENT;} else {//环境变量创建失败仍然可以创建进程//但会影响到后面的进程获取环境变量内容pEnv NULL;}ZeroMemory(si, sizeof(si));si.cb sizeof(si);si.dwFlags STARTF_USESHOWWINDOW;si.wShowWindow SW_SHOW;ZeroMemory(pi, sizeof(pi));bResult CreateProcessAsUser(hUserTokenDup, // clients access tokenGetAppPath().c_str(), // file to execute(LPTSTR)wstrCmdLine.c_str(), // command lineNULL, // pointer to process SECURITY_ATTRIBUTESNULL, // pointer to thread SECURITY_ATTRIBUTESFALSE, // handles are not inheritabledwCreationFlags, // creation flagspEnv, // pointer to new environment blockNULL, // name of current directorysi, // pointer to STARTUPINFO structurepi // receives information about new process);if (!bResult) {OutputDebugStringW((std::wstring(Lerror code:) std::to_wstring(GetLastError())).c_str());} else {OutputDebugStringW((std::wstring(Lcreate as user ok:)).c_str());}if (pi.hProcess) {CloseHandle(pi.hThread);CloseHandle(pi.hProcess);}if (hUserTokenDup ! NULL) CloseHandle(hUserTokenDup);if (hProcess ! NULL) CloseHandle(hProcess);if (hPToken ! NULL) CloseHandle(hPToken);if (pEnv ! NULL) DestroyEnvironmentBlock(pEnv);return TRUE;
}int main(int argc, char *argv[])
{bool result TriggerAppExecute(parameter);// 如果成功 直接返回失败if (result) {OutputDebugStringW(L降权失败等待。。。。);}return 0;
}2、降权失败
上面降权有个前置条件就是用户必须是登录的状态。
举个例子如果用户把机器开起来了。但是没有登录到系统中。此时由于拿不到当前的用户的token所以会造成降权失败。
那该怎么办
试想下如果用户没有登录那么你的UI是不是没有必要显示。即使是显示了也没有人看。
所以用户登录到系统中此时再显示ui时机刚刚好。
那么问题来了如何知道用户登录到了系统。
嘿嘿windows中有个消息通知我们可以注册回调函数。只要用户登录了就会收到消息。此时你在进行降权操作就没有问题。
给出实例代码新建一个控制程序
进程启动后先把退出系统再输入账号和密码此时就会打印attention, user logon消息说明消息监听成功。
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,LPARAM lParam) {switch (uMsg) {case WM_WTSSESSION_CHANGE: {// 处理用户登录和注销消息switch (wParam) {case WTS_SESSION_LOGON:// 用户登录printf(attention, user logon)break;case WTS_SESSION_LOGOFF:// 用户注销printf(attention, user logoff)break;}} break;}// 调用默认窗口过程函数处理其他消息return DefWindowProc(hwnd, uMsg, wParam, lParam);
}int main() {// 注册回调函数bool result WTSRegisterSessionNotification(GetConsoleWindow(),NOTIFY_FOR_ALL_SESSIONS);SetWindowLongPtr(GetConsoleWindow(), GWLP_WNDPROC, (LONG_PTR)WindowProc);getchar();// 取消消息监听WTSUnRegisterSessionNotification(GetConsoleWindow());return 0;
}3、总结
至此计划任务遇到的问题也已经解决了。