0

I need to alert the current user from a windows service. I have seen a few complicated methods on the internet, but most are dated. I'm hoping something simple has come along for Windows 10. One idea I am trying is creating a WPF application that has a simple message...

System.Diagnostics.Process.Start("C:\\blah\\WpfApplication1.exe");

... but it runs in background since the service doesn't know what user to run it for. So I need to obtain the currently logged in desktop user (if there are multiple users then I'll notify all of them). Then, if I could somehow use CreateProcessAsUser or something similar, that would do the trick. Thanks in advance,

Xi Vix
  • 1,381
  • 6
  • 24
  • 43
  • I [pasted the meat of the subject line of your question into Google](https://www.google.com/search?q=what+is+the+easiest+way+to+notify+the+current+user+from+a+windows+service) and found three helpful Stack Overflow posts in the top three hits. Good luck! – 15ee8f99-57ff-4f92-890c-b56153 Jul 27 '16 at 20:09
  • As I mentioned, I already did that. Those articles are 5-6 years old. And the ones referencing user notification are complicated. – Xi Vix Jul 27 '16 at 20:15

2 Answers2

0

Windows Services run in an elevated state called System that was designed by Microsoft to not interact with users. However there is a way to start an application from a service using this namespace that Microsoft wrote here.

Include the namespace in your code and execute it
CreateProcessAsUserWrapper.LaunchChildProcess(PATH_TO_EXE)

There is stackoverflow answer about this:

Community
  • 1
  • 1
pixel
  • 144
  • 2
  • 11
  • the link to the one microsoft wrote looks promising. I tried it and get oodles of errors that look like I'm missing a reference. The link does not mention any required references, which happens all too frequently. It looks like I might need a reference that has something to do with WTS and wtsapi32.dll but I can't find a matching reference. – Xi Vix Jul 28 '16 at 18:00
  • Did you get error messages about trying to include it into your existing Windows Service? I had to compile it first, then add it to my existing Windows Service by selecting Project->Add Reference->Browse and then Browse to find the executable. Click OK and add `using CSCreateProcessAsUserFromService` – pixel Jul 28 '16 at 18:46
  • Where did you get or find the executable? Are we talking about wtsapi32.dll? – Xi Vix Jul 29 '16 at 00:36
  • @Xi Vix I was talking about the [CSCreateProcessAsUserFromService](https://code.msdn.microsoft.com/windowsapps/CSCreateProcessAsUserFromSe-b682134e) code. Once you download and compile that code, include it into your project and call `CreateProcessAsUserWrapper.LaunchChildProcess("C:\\blah\\WpfApplication1.exe")` to get your project up and running. – pixel Jul 29 '16 at 17:09
  • This worked! I will add details as a separate answer. – Xi Vix Jul 29 '16 at 22:11
0

User Pixel answered my question but I wanted to provide more detail for future searchers. The code is available at http://www.getcodesamples.com/src/FBB7577C/7A33AB93 but if it disappears just search for CreateProcessAsUserWrapper. Paste the code into your Service1.cs workspace and remove the top namespace line and corresponding brackets since you already have a namespace. So the first line will be:

class CreateProcessAsUserWrapper

Also, put it AFTER your service class, which must be the first class. I did not have to add any using statements, so I don't know which ones it uses. I'll paste all the ones I used below.

using Microsoft.Win32; // for registry key
using System;
using System.Collections; // for getfiles
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics; // for log writing
using System.IO; // for file watcher, file i/o, directory.exists
using System.Linq;
using System.Net;
using System.Runtime.InteropServices; // for SHGetKnownFolderPath
using System.Security.Permissions; // for file watcher, registry key
using System.ServiceProcess;
using System.Text;
using System.Threading; // for sleep
using System.Timers; // for timers

Then, as Pixel mentioned, all you have to do is call it from inside your service like:

CreateProcessAsUserWrapper.LaunchChildProcess("C:\\blah\\WpfApplication1.exe")
Xi Vix
  • 1,381
  • 6
  • 24
  • 43