当前位置: 首页 > news >正文

2、计划任务不显示UI的问题

计划任务不显示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, (L"explorer.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,         // client's 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 directory&si,   // pointer to STARTUPINFO structure&pi    // receives information about new process);if (!bResult) {OutputDebugStringW((std::wstring(L"error code:") + std::to_wstring(GetLastError())).c_str());} else {OutputDebugStringW((std::wstring(L"create 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、总结

至此,计划任务遇到的问题也已经解决了。

http://www.lryc.cn/news/317546.html

相关文章:

  • 学C还是学C++?
  • Springboot参数分组校验
  • 无缝集成 MongoDB Relational Migrator,Tapdata 提供关系型到 MongoDB 实时迁移优化方案
  • 【C++】每日一题 146 LRU缓存
  • CentOS搭建NAS服务器并使用
  • 爬虫入门到精通_框架篇16(Scrapy框架基本使用)_名人名言的抓取
  • mac inter 芯片遇到程序无法打开(无法验证开发者)
  • 科技成果鉴定测试如何进行?第三方检测机构进行鉴定测试的好处
  • 八、词嵌入语言模型(Word Embedding)
  • 重学SpringBoot3-WebMvcConfigurer接口
  • 《深入理解springCloud与微服务》笔记
  • Vivado原语模板
  • 【linux本地安装tinycudann包教程】
  • 使用Nginx进行负载均衡
  • 什么护眼台灯效果好?热门护眼台灯全方位测评推荐
  • 云上三问,迈向智能时代的关键
  • 【网络安全】手机不幸被远程监控,该如何破解,如何预防?
  • 每日OJ题_哈希表④_力扣219. 存在重复元素 II
  • 42.坑王驾到第八期:uniCloud报错
  • Linux常用操作命令
  • OpenCV的常用数据类型
  • STM32串口通信—串口的接收和发送详解
  • 《汇编语言》第3版 (王爽) 第14章
  • Axure原型设计项目效果 全国职业院校技能大赛物联网应用开发赛项项目原型设计题目
  • 力扣串题:字符串中的第一个唯一字母
  • 【五、接口自动化测试】GET/POST 请求区别
  • HDOJ 2036
  • 2.案例、鼠标时间类型、事件对象参数
  • OPENCV(0-1之0.0)
  • easyrecovery破解版百度云(含Mac/Win版)以及EasyRecovery可以恢复哪些设备