Please see my comments on what it can be. First of all, you need to be sure that the application started as a separate process will eventually show some main window of the Windowed application; not sure it can be the regular system console.
In view of my comments above, try this:
Process proc = new Process();
proc.StartInfo.FileName = link;
proc.StartInfo.UseShellExecute = false;
proc.Start();
ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback( (state) => {
proc.WaitForInputIdle();
while (true) {
try {
IntPtr handle = proc.MainWindowHandle;
return;
} catch (System.InvalidOperationException) {
System.Threading.Thread.Sleep(0);
} catch (System.System.NotSupportedException){
System.Threading.Thread.Sleep(0);
}
}
}));
Please see, pay attention for exceptions:
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx[
^],
http://msdn.microsoft.com/en-us/library/8d7363e2.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle.aspx[
^].
This should explain why
UseShellExecute = false
:
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute.aspx[
^].
This is not all. You should organize proper exchange of data between different threads. You share one variable,
proc
and probably need to share at least one more object, the handle to the separate process's main window, if found. As to
proc
, what you have done is not interlocked, so it's questionable, but I
think is should work in this specific case. However, should you modify this code slightly, you can make it extremely dangerous. To stay away from the sin, you should interlock all shared object. The schema is simple: make those objects fields, add properties backed by these fields and use the
lock
statement. Here is the schema:
IntPtr handle;
object handleLock = new object();
IntPtr Handle {
get { lock(handleLock) { return handle; } }
set { lock(handleLock) { handle = value; } }
}
Different objects can be interlocked with separate lock object or with the same: it depends what do you lock from what. You need to consider appropriate state diagram to decide. Shared lock can be slower but protect more, unless you "design" a deadlock, which is not likely with just the
lock
statements.
Same thing goes about the criterion for wait for completion of the pooled thread, if you use collaborative approach. If you simply wait for it in the blocking call, there are no benefits of an extra thread. You can use
lazy approach: wait for the thread completion (
Thread.Join
) only when a handle is about to be used. Please see:
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx[
^],
http://msdn.microsoft.com/en-us/library/95hbf2ta.aspx[
^],
http://msdn.microsoft.com/en-us/library/6b1kkss0.aspx[
^],
http://en.wikipedia.org/wiki/Lazy_evaluation[
^].
You can greatly improve and simplify inter-thread communications if you use my pattern of the thread wrapper. Please see my past answers with the code and explanations:
How to pass ref parameter to the thread[
^],
change paramters of thread (producer) after it started[
^] (this one with lock).
Finally, I should tell you that the whole idea of using a separate process is very questionable: processes are well isolated. You control of another process via main windows handle is limited; its hard to maintain in any reliable way. Also, this is a weird Windows-specific way of IPC created when Windows was not an operating system but worked over the single-process DOS. Such tricks are not portable, they won't work on any other system where CLI is implemented, for example, via Mono.
(
http://en.wikipedia.org/wiki/Common_Language_Infrastructure[
^],
http://en.wikipedia.org/wiki/Mono_%28software%29[
^],
http://www.mono-project.com/Main_Page[
^].)
The best way of integration is no integration. If you want to use collaboration between different process, the other process should be designed for it. One example, albeit not most reasonable on, is automation interfaces. Ideally, it should be a library, so you could use it "in-proc". I do understand: sometimes you don't need better choice. But it's important to understand: then, it's a bad choice.
Good luck,
—SA