以Windows系统服务得到活动用户的用户名、UserProfile与环境变量
来源:互联网 发布:linux修改ssh端口号 编辑:程序博客网 时间:2024/06/02 12:52
在之前的一篇博文中(http://blog.csdn.net/nirendao/article/details/51194003),介绍了如何使用QT写一个Windows下的Service. 这篇文章试图在此基础上,解决一个问题:如何在这个系统级别的Windows service里面获得活动用户的一些信息,比如用户名,环境变量。本篇文章并未完全解决这些问题,因为很可能是基本没有什么好的方法的。
首先,要明了Windows系统的一些特性,比如Fast User Switching(https://msdn.microsoft.com/en-us/library/windows/desktop/bb776893(v=vs.85).aspx),它指的是在Windows XP之前版本的Windows OS,一个用户要登录,就必须等待其他用户登出(Log off);但是自从Windows XP开始,就可以做到:一个用户在使用的时候,并不需要登出(Log off),而只是切换用户,就可以允许其他用户登录了。这就是Fast User Switching. 另外,也允许真正的多个远程用户登录了(以前只是Windows 2003 Server版才可以). 这里要注意的是:虽然不需要用户登出(Log off),但是能看到桌面的在同一时刻只会有一个用户。比如远程登录桌面,远程者如果看到桌面,需要现有的桌面拥有者允许并退出桌面(不是Log off,只是类似切换用户)。
虽然有Fast User Switching这样的特性,允许多个用户同时登录,但是很可能依然有活动用户的概念(Active User),即看到桌面的那个用户。–这仅仅是笔者的猜测,并未在网上找到相应的文档。那么如何在一个系统级别的进程(如system level service)中得到active user的用户名和环境变量呢?本文分步骤来探讨这个问题。
第一步是如何得到active user的用户名。笔者做了以下的尝试,最终能够实现目标。
尝试-1:
使用QT中的qgetenv()方法获取环境变量%UserName%
qInfo() << "User Name = " << qgetenv("UserName");
可惜这样得到的结果是: hostname$, 如”FINIX-LAPTOP$”. 很明显,这样得到的是和系统相关的信息,而不是特定用户的用户名。
尝试-2:
使用Windows API GetUserName()来得到环境变量%UserName%
wchar_t acUserName[200];DWORD nUserName = sizeof(acUserName);if (GetUserName(acUserName, &nUserName)){ // Translate wchar_t * to QString qInfo() << "Windows User Name = " << QString::fromWCharArray(acUserName);}
得到的结果是”SYSTEM”. 很显然,仍然认为自己是系统进程,而没有去取活动用户的环境变量%UserName%.
尝试-3:
先去获得活动控制台的session id,然后再去获得相关信息,如用户名。
DWORD sessionId = WTSGetActiveConsoleSessionId();qInfo() << "session id = " << sessionId;wchar_t* ppBuffer[100];DWORD bufferSize;WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppBuffer, &bufferSize);
这次尝试成功了。成功地获取到了Active User的用户名。
在第一步成功获得active user的用户名之后,第二步就是:
我们要试图来获得active用户的Home Location,或者也称为%UserProfile%,即一般为C:\Users\
尝试-4:
QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation);qInfo() << homePath.first().split(QDir::separator()).last();
这里得到的结果是: “C:/Windows/system32/config/systemprofile”,这其实是系统级别的%UserProfile%.
尝试-5:
wchar_t envVar[] = L"UserProfile";wchar_t result[100];GetEnvironmentVariable(envVar, result, sizeof(result)/sizeof(wchar_t));qInfo() << "USER PROFILE = " << QString::fromWCharArray(result);
得到的依然是: “C:/Windows/system32/config/systemprofile”.
尝试-6:
同尝试-3. 但是对WTSQuerySessionInformation()使用不同的参数,比如WTSWorkingDirectory或WTSClientDirectory. 然而,得到都是空字符串。
其实我最终想做到的是在此系统级别service中得到某个指定用户或active用户的环境变量,而这里的尝试-5正是调用了Windows获取环境变量的API,可惜获取的仍是系统级别的环境变量,而不是当前活动用户的环境变量。所以这一部分尝试是失败了。
最终的解决方法是这样的:
先用WTSQueryUserToken()获得给定session的登入用户的token,然后将token传给CreateEnvironmentBlock()以获取该用户的环境信息。最后,就可以根据CreateEnvironmentBlock()的输出参数lpEnvironment来获取环境变量了;也可以调用CreateProcessAsUser()来以该用户的身份启动某进程。
最后,我做了一个实验,给这个Windows service添加了一个新功能,就是监控用户的登入、登出、lock、unlock的事件,当有登入或unlock事件发生的时候,在log里打印出当前active user的user name. 实验显示,打印的用户名是正确的。
本文的实验代码如下:
https://github.com/FinixLei/QtProjects/tree/master/TestWindowsService
- 以Windows系统服务得到活动用户的用户名、UserProfile与环境变量
- 在Windows系统上以C++打印出当前活动用户的环境变量
- 从Windows系统服务获取活动用户的注册表信息
- ,如%USERPROFILE% 指当前用户的配置文件目录 系统路径%ProgramFiles% %windir% %windows% %Temp% 等的解释
- 获取WINDOWS下当前用户路径 USERPROFILE
- 获取WINDOWS下当前用户路径 USERPROFILE
- windows系统环境变量和用户环境变量的区别
- 以用户友好的方式管理Windows服务的工具
- django1.6 使用userprofile 以及一些关于用户系统的总结
- 服务,活动均可以使用的sharePreference
- 取得BCB环境变量与Windows用户环境变量
- Windows系统服务与用户进程共享内存
- Windows的系统环境变量
- Windows 10 系统设置系统环境变量和用户环境变量
- 【ThinkingInJava】22、得到系统的环境变量
- java环境变量中 用户变量与系统变量的区别
- windows server 2012 活动目录部署系列(九)域用户与组用户的管理
- windows系统自动以某用户登录
- 从Aactivity跳转到Bactivity的指定的fragment
- 集合详解(一)----Collection和Map接口
- python核心编程第十章练习
- Android之Handler用法总结
- CODEVS 3731 寻找道路
- 以Windows系统服务得到活动用户的用户名、UserProfile与环境变量
- 取出一个字符串中字母出现的次数。如:字符串:"abcdekka27qoq" ,输出格式为:a(2)b(1)k(2)..
- Mysql锁的优化
- 开始记日记
- 情感分析
- MySQL数据库学习笔记(一)----MySQL 5.6.21的安装和配置(setup版)
- SQLite的基本知识
- lua 字符串处理
- 智能社JS实现图片淡入淡出效果