- Run a process from a windows service as the current user
- 2 Answers 2
- How do you find the current user in a Windows environment?
- 15 Answers 15
- PowerShell
- Not the answer you’re looking for? Browse other questions tagged windows batch-file or ask your own question.
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
- How to start a process from windows service into currently logged in user’s session
- 8 Answers 8
Run a process from a windows service as the current user
I currently have a windows service that is running under the System Account. My problem is that i need to start certain processes from within the service as the current logged on user. I have all the code etc to get the current logged on user / Active session.
My problem is that i need spawn a process as the logged on user but will not know the user credentials etc.
The service is .net compiled service and i expect that i need to use some Pinvoke methods to get a handle of one of the current users process in order to duplicate it and lunch as process with the handle.
Unfortunately i cannot find any good documentation / solution on how to implement it?
If someone is able to give me some guidance / example i would highly appreciate it.
* Updated * I think i have explained this incorrectly and need to reajust according to what i actually require. I do not necessarily want to launch a new process, i just want to impersonate the logged on user. I have been so wrapped up at looking at CreateProcess etc i have lead myself down a path of create a new process as the current logged in user (which is not particularly what i want to do).
In turn i just want to run some code under the current user context (Impersonate the current Logged on user)?
2 Answers 2
One option is to have background application that automatically starts when user logs on and listens to commands from your service through WCF, or thrift, or by just monitoring some file and reading command from there.
Another option is to do what you originally asked for — launch using windows API. But the code is quite scary. Here is a sample, that you can use. It will execute any command line under currently active user session, with CreateProcessInConsoleSession method:
As is so common with these types of questions about Windows services, you’re operating in the mindset of a single-user operating system. The whole reason you decided to write your app as a service was because you were running into conflicts between your mental model of a single-user OS and the reality of a multi-user OS. Unfortunately, a service didn’t solve all of your problems and now you’re trying to figure out how to accomplish step two in the ultimately-doomed hacked design.
The fact is, you cannot be guaranteed that there is a «logged on user». If no one has logged on to the workstation, there will be no one logged on, yet your service will still be running.
Even if you somehow got past this by ensuring that someone will always be logged on (impossible), then you would run into the situation where multiple users are logged on. Then which one should your service start the process as? Should it just pick one of them randomly?
And is it necessary in your case to distinguish between users logged on locally to the console and those who are logged on remotely? Remember that remote users won’t have a local console.
If you could somehow get past all of these hurdles (unfortunately, probably by burying your head in the sand and continuing to pretend that Windows is a single-user OS), you could make use of the WTSGetActiveConsoleSessionId function to obtain the current session ID, the WTSQueryUserToken function to obtain the user token corresponding to that session ID, and then finally the CreateProcessAsUser function to launch your process in the context of that user. If there is one. And they have the appropriate privileges. And the physical console is not attached to a dummy session. And you’re not running a server SKU that allows multiple active console sessions. And…
If you could decide on a particular user whose account you wish to use to start the auxiliary process, you could log on that user, manipulate their user token, execute the process, and finally close the process and log out the user. The CreateProcessWithLogonUser function wraps up a lot of this drudgery for you, making the code a lot more svelte. But appearances can be deceiving, and this still has some massive security implications that you probably do not completely understand if you’re asking this question in the first place. And you really cannot afford to not understand security risks like this.
Besides, users that are logged in with LogonUser (which is done for you automatically when you use the CreateProcessWithLogonUser function) lack a window station and desktop on which they can launch interactive processes. So if the process you wish to launch in the context of that user will show any kind of UI, you’re out of luck. Windows will kill your app as soon as it tries to access a desktop for which it lacks the requisite permissions. There is no way, from a Windows service, to obtain the handle of a desktop that will be useful to you (which goes a long way towards explaining the general rule you probably already know, that services cannot display any type of UI).
How do you find the current user in a Windows environment?
When running a command-line script, is it possible to get the name of the current user?
15 Answers 15
You can use the username variable: %USERNAME%
Username:
Domainname:
You can get a complete list of environment variables by running the command set from the command prompt.
Just use this command in command prompt
It should be in %USERNAME% . Obviously this can be easily spoofed, so don’t rely on it for security.
Useful tip: type set in a command prompt will list all environment variables.
%USERNAME% is the correct answer in batch and other in Windows environments.
Another option is to use %USERPROFILE% to get the user’s path, like C:\Users\username .
The answer depends on which «command-line script» language you are in.
In the old cmd.exe command prompt or in a .bat or .cmd script, you can use the following:
%USERNAME% — Gets just the username.
%USERDOMAIN% — Gets the user’s domain.
PowerShell
In the PowerShell command prompt or a .ps1 or .psm1 script, you can use the following:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Name — Gives you the fully qualified username (e.g. Domain\Username). This is also the most secure method because it cannot be overridden by the user like the other $Env variables below.
$Env:Username — Gets just the username.
$Env:UserDomain — Gets the user’s domain.
$Env:ComputerName — Gets the name of the computer.
%USERNAME% will get you the username of the currently running process. Depending on how you are running your batch file, this is not necessarily the same as the name of the current user. For example, you might be running your batch file through a scheduled task, from a service, etc.
Here is a more sure way of getting the username of the currently logged on user by scraping the name of the user that started the explorer.exe task:
I use this method in writing batch files for testing.
Since you must include the password in plain text if authentication is required, I will only use it in a completely private environment where other users cannot view it or if a user seeing the password would bear no consequences.
Hope this helps someone out.
It’s always annoyed me how Windows doesn’t have some of more useful little scripting utilities of Unix, such as who/whoami, sed and AWK. Anyway, if you want something foolproof, get Visual Studio Express and compile the following:
And just use that in your batch file.
In most cases, the %USERNAME% variable will be what you want.
However, if you’re running an elevated cmd shell, then %USERNAME% will report the administrator name instead of your own user name. If you want to know the latter, run:
Just type whoami in command prompt and you’ll get the current username.
This is the main difference between username variable and whoami command:
In a standard context, each connected user holds an explorer.exe process: The command [tasklist /V|find «explorer»] returns a line that contains the explorer.exe process owner’s, with an adapted regex it is possible to obtain the required value. This also runs perfectly under Windows 7.
In rare cases explorer.exe is replaced by another program, the find filter can be adapted to match this case. If the command return an empty line then it is likely that no user is logged on. With Windows 7 it is also possible to run [query session|find «>»].
As far as find BlueBearr response the best (while I,m running my batch script with eg. SYSTEM rights) I have to add something to it. Because in my Windows language version (Polish) line that is to be catched by «%%a %%b»==»User Name:» gets REALLY COMPLICATED (it contains some diacritic characters in my language) I skip first 7 lines and operate on the 8th.
Via powershell (file.ps1) I use the following
It returns the name of the user in the «Domain\Username» format. If you just want the username just write
The advantage is that It works with windows 10 windows 8 server 2016. As far as I remember with also other OS like Win7 etc. (not older) . And yeah via batch you can simply use
Not the answer you’re looking for? Browse other questions tagged windows batch-file or ask your own question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
site design / logo © 2021 Stack Exchange Inc; user contributions licensed under cc by-sa. rev 2021.4.16.39093
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
How to start a process from windows service into currently logged in user’s session
I need to start a program from Windows Service. That program is a user UI application. Moreover that application should be started under specific user account.
The problem is that a Window Services run in session #0, but a logged in user sessions are 1,2 etc.
So the question is: how to start a process from a window service in such a way that it run in currently logged in user’s session?
I’d emphasis on that the question is not about how to start a process under specific account (it’s obvious — Process.Start(new ProcessStartInfo(«..») < UserName=. Password=..>)). Even if I install my windows to run under current user account the service will run in session #0 anyway. Setting «Allow service to interact with desktop» doesn’t help.
My windows service is .net-based.
UPDATE: first of all, .NET has nothing to do here, it’s actually pure Win32 thing. Here’s what I’m doing. The following code is in my windows service (C# using win32 function via P/Inkove, I skipped import signatures, they’re all here — http://www.pinvoke.net/default.aspx/advapi32/CreateProcessWithLogonW.html):
The code goes to the line «Notepad has been started by WatchdogService. Exitcode: » + exitCode. Exitcode is 3221225794. And there’s no any new notepad started. Where am I wrong?
8 Answers 8
The problem with Shrike’s answer is that it does not work with a user connected over RDP.
Here is my solution, which properly determines the current user’s session before creating the process. It has been tested to work on XP and 7.
Everything you need is wrapped up into a single .NET class with a static method:
It’s a terrific helpful post about starting a new process in interactive session from windows service on Vista/7.
For non-LocalSystem services, the basic idea is:
Enumerate the process to get the handle of the Explorer.
OpenProcessToken should give you the access token. Note : The account under which your service is running must have appropriate privileges to call this API and get process token.
Once you have the token call CreateProcessAsUser with this token. This token already have the right session Id.
It’s a bad idea to do so. Although probably not totally impossible, Microsoft did everything to make this as hard as possible, as it enables so-called Shatter Attacks. See what Larry Osterman wrote about it back in 2005:
The primary reason for this being a bad idea is that interactive services enable a class of threats known as «Shatter» attacks (because they «shatter windows», I believe).
If you do a search for «shatter attack», you can see some details of how these security threats work. Microsoft also published KB article 327618 which extends the documentation about interactive services, and Michael Howard wrote an article about interactive services for the MSDN Library. Initially the shatter attacks went after windows components that had background window message pumps (which have long been fixed), but they’ve also been used to attack 3rd party services that pop up UI.
The second reason it’s a bad idea is that the SERVICE_INTERACTIVE_PROCESS flag simply doesn’t work correctly. The service UI pops up in the system session (normally session 0). If, on the other hand, the user is running in another session, the user never sees the UI. There are two main scenarios that have a user connecting in another session — Terminal Services, and Fast User Switching. TS isn’t that common, but in home scenarios where there are multiple people using a single computer, FUS is often enabled (we have 4 people logged in pretty much all the time on the computer in our kitchen, for example).
The third reason that interactive services is a bad idea is that interactive services aren’t guaranteed to work with Windows Vista 🙂 As a part of the security hardening process that went into Windows Vista, interactive users log onto sessions other than the system session — the first interactive user runs in session 1, not session 0. This has the effect of totally cutting shatter attacks off at the knees — user apps can’t interact with high privilege windows running in services.
The proposed workaround would be to use an application in the system tray of the user.
If you can safely ignore the issues and warnings above, you might follow the instructions given here: