0

I wrote a Windows service. It is running at the system level. I used the following code to get the logged in user's username. But I want to get an environment variable for that user session. How can I do that?

DWORD sessionId = WTSGetActiveConsoleSessionId();
qInfo() << "session id = " << sessionId;

wchar_t* ppBuffer[100];
DWORD bufferSize;
WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppBuffer, &bufferSize);
qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppBuffer);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Finix
  • 131
  • 14
  • 1
    The good thing about a logged-in user is that the user profile is loaded. That means you can find them under HKEY_USERS (obviously not HKEY_CURRENT_USER since your service probably doesn't run under that user name). Other than that, see http://stackoverflow.com/questions/573817/where-are-environment-variables-stored-in-registry – MSalters Jul 24 '16 at 09:00
  • Cannot figure out which sub item under HKEY_USERS stands for the specified user. Also, some environment variable contains "%USERPROFILE%", but it looks like not easy to figure out the value of %USERPROFILE% for one sub item under HKEY_USERS. – Finix Jul 24 '16 at 09:22
  • It is not loaded, your service runs with whatever account it was configured to run. You'll have to know the user's SID so you can poke inside HKEY_USERS. That still only gives you the environment with which a user's session is initialized, it does not tell you anything about environment overrides that the user might have applied. You'd also have to deal with no users being logged-in or multiple users being logged-in. Dealing with user sessions in a service is a very bad idea. Use a plain program that you start with the Run registry key or a shortcut in the Startup folder. – Hans Passant Jul 24 '16 at 09:46
  • @HansPassant I think you are right. The problem I face is, the system service will be triggered by some condition to launch the specific program. However, the target program is installed per user. So their installation paths are different. I want the service to launch the active user's program. I'm not clear if that's feasible. I even don't know if 2 users remotely log on to trigger the launching-s separately, what will happen. I will do some test. I have one mechanism to let the service monitor log-on and log-off events. Not sure if that helps. – Finix Jul 24 '16 at 13:30
  • Assuming that the target program needs to be run as the logged-on user, it would probably be simpler to launch a proxy executable from your service (as the logged-on user) and have *that* executable locate and run the target program. – Harry Johnston Jul 24 '16 at 23:27

1 Answers1

2

Use WTSQueryUserToken() to get the logged in user token for the desired session ID, and then pass that token to CreateEnvironmentBlock() to get that user's environment variables.

You can then parse those strings as needed, or pass them (and the token) to CreateProcessAsUser() to launch a program as the user in the user's session.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770