0

I am currently writing a C# service to basically make sure a group of exes are running and if they aren't then relaunch them.

The service starts up automatically so I run in to the problem that it attempts to launch the exe when no one is logged in. I have a solution that works for non-VM systems as shown below:

ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT UserName FROM Win32_ComputerSystem");
ManagementObjectCollection collection = searcher.Get();
string loggedIn = (string)collection.Cast<ManagementBaseObject>().First()["UserName"];

I then check this against null or whitespace and then just don't check the process list if no user is logged in.

However, while running on a VM this section of code returns null when a user is logged in. So I need a way of checking for a logged in user on both a standard machine and VM. I also need it to work for XP and windows 7, and both 32bit and 64bit. I am using .Net 4.

1 Answers1

2

Official documentation to list sessions prescribes to use LsaLogOnSessions to enumerate them, refer to MSDN or to this CodeProject article for more examples.

That said if you just need to be sure there is at least one logged in user then you can simply check for default shell process. Default shell will always be loaded for each session:

bool loggedInUserExist = Process.GetProcessesByName("explorer").Any();

In this example I hard-coded value but you must read it from string value Shell in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon\, in case default shell has been overridden (or for Server Core installation when GUI isn't present).

If you don't need anything else then you're done. If you have to filter specific users then you have to get process' owner. It's not such easy in C# unless you use WMI to query Win32_Process, search for explorer in Name property and then call GetOwner() method of the ManagementObject (see this post here on SO). Note that you may use same query both to determine if there is any logged in user and who he is. As alternative you may P/Invoke for Windows API functions as described in this post (but in this case I'd go back to LsaLogOnSessions).

Community
  • 1
  • 1
Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Checking for the explorer process worked perfectly thanks. I will definitely keep the other options in mind for times when I actually need the username. Thanks for a great full answer. – harley_steel Jul 21 '14 at 12:55
  • @AdrianoRepetti, On the Windows Server Core there are no `explorer.exe` processes, I checked just now. – v.karbovnichy Jul 21 '14 at 13:41
  • @kpa6uk yes, of course not but there will be cmd.exe, if you hard-code explorer.exe it won't work but if you read registry value (HKLM\...\WinLogon\Shell) you'll always use right value. – Adriano Repetti Jul 21 '14 at 13:47
  • @AdrianoRepetti so please edit your answer to clarify that thing about "first read from registry value then use it but not hardcode `explorer`" – v.karbovnichy Jul 21 '14 at 13:51