A: 

In a word, "don't".

Services typically run with reduced privileges and NOT as the current user. As such, in Vista+ they're not allowed to interact with the users desktop. On top of all that, services get a null Window Station.

You used to be able to check a box that said something like "Allow to interact with the desktop" but not anymore. It's bad practice.

Your best bet is to create a helper app that runs in the users context and communicates with the service via a named pipe, LRPC or a socket, then have your helper app launch the program for the user. This is the way most anti-virus now works.

Also, read this whitepaper from Microsoft on the subject. Services can't run in anything other than session 0.

NOTE: a little research seems to indicate that you need to duplicate the token using something like this:

DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,
    SecurityIdentification,TokenPrimary,&hTokenDup);
Mystere Man
This is being done for debug purposes, not for normal operation. In the field, these processes will run in session 0. We only want to bring them up for viewing debug dialogs. I'll edit the question to make this clear.
Bob Moore
Read a little further in that thread - you'l find an MS engineer correcting that code. WTSQueryUserToken returns a primary token, so duplication isn't necessary.
Bob Moore
A: 

It looks as if you're trying to break Session Isolation. Like Mystere Man said, I don't think it's the right thing to do.

http://support.microsoft.com/?scid=kb%3Ben-us%3B165194&x=5&y=3 might be useful if you really want to do this. In the code sample over there, they seem to initialize more thing than you do.


EDIT If it's for debugging purposes, i-e VS 2008 step-in, just add a wait loop at the beginning, and launch VS with administrator rights. You can attach to your service process without encountering system isolation.

Johan Buret
That's an interesting link, especially the part about GUI drawing failing. But if that were the problem, native mode apps would fail as well, and as I said, they work fine. The problem is just with .Net winforms apps.
Bob Moore
A: 

Like "Mystere Man" did my suggestion is use PIPE. This links is useful:

.NET 3.5 Adds Named Pipes Support
Interprocess Communication using Named Pipes in C#

lsalamon
+1  A: 

Despite the evident hysteria there is nothing wrong with launching an application from a service into an interactive session provided it is done with the same privileges as the interactive user or lower. Since you are launching as the interactive user there can be no privilege escalation.

What you are doing does work. I suspect that the issue has something to do with your STARTUPINFO struct. You appear to be creating your sui on the stack but you don't show what you are doing with it. Are you initializing it to all 0s, if not you may be getting some garbage from the stack that is causing the window not to show or to show at some co-ordinates off the screen.

Stephen Martin
I am zeroing out the sui, it's just above the code I clipped. I'll add it to the sample for everyone to see. Thanks for the rationality :-)
Bob Moore
Native apps work fine, as observed in the question. I suspect it's just the .Net runtime being anal. We have no .Net server apps, so it's really just an exercise in curiosity for my own benefit...
Bob Moore
So the exact same code works for native apps but not .Net apps? There's no possibility that you're getting a different value from GetWinStartState? I just whipped up a simplified version of this launching a .Net app from a .Net service and it worked fine. In theory there should be no difference...
Stephen Martin
... between a .Net app and a native app as far as CreateProcessAsUser is concerned. This is intriguing. When I have a little more time later on I will look into this more closely, if you haven't figured it out by then.
Stephen Martin
BINGO - I retested with a small mod to sui, thanks to you. Oh boy this is dumb. When I was doing some testing I accidentally swapped the script files that drive my service. So it wasn't even trying to launch the .Net test app I was worrying about. Shoot.
Bob Moore
"Oh boy this is dumb". If I had a dollar for every time I've said that about something I've done I'd be sipping margaritas in the sun instead of slipping on the ice every time I try to take two steps outdoors:-)
Stephen Martin
Oh - I think it got into the state where I could see the process on Process Explorer, but didn't get a window, because the original script file I *was* using had the window state set wrong. Technically your answer is spot-on, so I've marked it answered. Thanks.
Bob Moore
I just realised that this means the .Net runtime actually respects the ShowWindow setting in STARTUPINFO. Wow. That must make it one of the 0.000001% of apps that do :-)
Bob Moore