I use System.Diagnostic.Process
class to start processes on my server pc using .Net WCF web service. They start smooth, I can see them running from task manager, but no window is displayed. How do you guys think that I can overcome this problem?

- 7,112
- 11
- 58
- 91
-
Services cannot be interactive (for many many reasons, security and robustness at first). Check [this post here on SO](http://stackoverflow.com/questions/4516200/how-can-a-windows-service-start-a-process-when-a-timer-event-is-raised) for workarounds. – Adriano Repetti Jul 06 '12 at 12:08
-
Can you post some code showing how you are starting the process – Matt Wilko Jul 06 '12 at 12:09
3 Answers
If you want to display a GUI and the user to be able to interact with it, you have to start an interactive process. It's currently probably not the case with your web service.
You Shouldn't Be Doing This, but ...
You CAN launch programs in as the user in the current session
IntPtr UserTokenHandle = IntPtr.Zero;
WTSQueryUserToken ( WTSGetActiveConsoleSessionId(), ref UserTokenHandle);
PROCESS_INFORMATION ProcInfo = new PROCESS_INFORMATION();
STARTUPINFOW StartInfo = new STARTUPINFOW();
StartInfo.cb = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(StartInfo));
CreateProcessAsUser ( UserTokenHandle, @"C:\dir\MyApp.exe",
IntPtr.Zero,
IntPtr.Zero,
IntPtr.Zero,
false,
0,
IntPtr.Zero,
null,
ref StartInfo,
ref ProcInfo);
if (!(UserTokenHandle == IntPtr.Zero))
{
CloseHandle ( UserTokenHandle);
}
Required imports and structs:
[DllImport("kernel32.dll", EntryPoint = "WTSGetActiveConsoleSessionId", SetLastError = true)]
public static extern uint WTSGetActiveConsoleSessionId ();
[DllImport("Wtsapi32.dll", EntryPoint = "WTSQueryUserToken", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool WTSQueryUserToken ( uint SessionId, ref IntPtr phToken );
[DllImport("kernel32.dll", EntryPoint = "CloseHandle", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle ( [InAttribute()]
IntPtr hObject );
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUserW", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CreateProcessAsUser (
[InAttribute()]
IntPtr hToken,
[InAttribute(), MarshalAs(UnmanagedType.LPWStr)]
string lpApplicationName, System.IntPtr lpCommandLine,
[InAttribute()]
IntPtr lpProcessAttributes,
[InAttribute()]
IntPtr lpThreadAttributes,
[MarshalAs(UnmanagedType.Bool)]
bool bInheritHandles, uint dwCreationFlags,
[InAttribute()]
IntPtr lpEnvironment,
[InAttribute(), MarshalAsAttribute(UnmanagedType.LPWStr)]
string lpCurrentDirectory,
ref STARTUPINFOW lpStartupInfo,
ref PROCESS_INFORMATION lpProcessInformation );
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public uint nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFOW
{
public uint cb;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpReserved;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpDesktop;
[MarshalAs(UnmanagedType.LPWStr)]
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public ushort wShowWindow;
public ushort cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}

- 7,112
- 11
- 58
- 91

- 11,522
- 5
- 41
- 58
-
even if I write this code it will be still working as a service which will not be any useful to me. I should use some other strategy. – Tolga Evcimen Jul 06 '12 at 12:36
-
No. That code will execute the application AS the user IN the current logged on session. – hometoast Jul 06 '12 at 13:04
-
I've tried this code but it didnt work either :/ process starts without any gui :/ – Tolga Evcimen Jul 06 '12 at 14:42
-
The service needs to run as "LocalSystem". Sorry it doesn't work for you. It Works For Me (tm). – hometoast Jul 06 '12 at 15:15
You are talking about a web service, and so it is probably running as a Windows Service as well? In that case you can start processes, but you won't see any forms, ever.
Windows Services are designed to run on your computer, even when no user is logged in. Therefor, it could never know where to show the application that you want to run!
You could fiddle around with a setting called 'Allow interactions with the desktop' (or something similar) but Services aren't meant to be used that way.

- 30,492
- 6
- 73
- 100
-
I've advised with that setting solution but i didn't like it either :/ You sound like I shouldn't be doing this, so what is the alternative way of launching applications on a remote machine? By the way the remote machine im using is WindowsServer2008. – Tolga Evcimen Jul 06 '12 at 12:15
-
what if I use batch files to start applications, and start the batch files through the web service? – Tolga Evcimen Jul 06 '12 at 12:37
-
Probably not going to work either because the started process will be a child of the (invisible) batch file! But don't really know this for a fact.. – Gerald Versluis Jul 06 '12 at 12:42