You can use P/Invoke to access the Win32 CreateEvent API to create named
events. I created this test app fairly quicklly that seems to work...
in project 1
using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool
bManualReset,
bool bInitialState, string lpName);
[DllImport("kernel32.dll")]
static extern bool SetEvent(IntPtr hEvent);
[DllImport("kernel32.dll")]
static extern bool ResetEvent(IntPtr hEvent);
[DllImport("kernel32.dll", SetLastError=true)]
static extern int CloseHandle(IntPtr hObject);
const int ERROR_ALREADY_EXISTS = 183;
/// <summary>
///
/// </summary>
[STAThread]
static void Main(string[] args)
{
string file =
@"..\..\..\ConsoleApplication2\bin\debug\ConsoleApplication2.exe";
if ( !System.IO.File.Exists(file) )
{
Print("Unable to locate file {0}",file);
return;
}
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo(file,"2");
p.StartInfo = psi;
IntPtr handle;
bool createdNew;
if ( !CreateManagedEvent(out handle,out createdNew) )
{
Print("Error creating named event.");
return;
}
if ( !createdNew )
{
Print("App2 already running. Press any key to exit...");
Console.ReadLine();
return;
}
else
{
Console.WriteLine("Starting other app");
ManualResetEvent _evt = new ManualResetEvent(false);
_evt.Handle = handle;
_evt.Reset();
DateTime start = DateTime.Now;
p.Start();
Print("Waiting....");
_evt.WaitOne(TimeSpan.FromSeconds(15),false);
TimeSpan elapsed = DateTime.Now - start;
Print("Done waiting; it took {0} seconds...",elapsed.Seconds);
}
Print("All done");
}
/// <summary>
/// Creates a named event in the win32 space. This is a manual
/// reset event that is initially not signalled.
/// </summary>
/// <param name="handle"></param>
/// <param name="createdNew">true if it created a new one, false if it
opened an existing one</param>
/// <returns>true if it succeeds, otherwise false</returns>
static bool CreateManagedEvent(out IntPtr handle,out bool createdNew)
{
createdNew = false;
handle = CreateEvent(IntPtr.Zero, true,false, "MyNamedEvent");
int error = Marshal.GetLastWin32Error();
if ( handle == IntPtr.Zero )
return false;
createdNew = (error != ERROR_ALREADY_EXISTS);
return true;
}
static void Print(string format,params object[] args)
{
string msg = string.Format(format,args);
Trace.WriteLine(msg);
Console.WriteLine(msg);
}
}
}
in project 2
using System;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class2
{
[DllImport("kernel32.dll", SetLastError=true)]
static extern IntPtr CreateEvent(IntPtr lpEventAttributes, bool
bManualReset,
bool bInitialState, string lpName);
[DllImport("kernel32.dll")]
static extern bool SetEvent(IntPtr hEvent);
[DllImport("kernel32.dll")]
static extern bool ResetEvent(IntPtr hEvent);
[DllImport("kernel32.dll", SetLastError=true)]
static extern int CloseHandle(IntPtr hObject);
const int ERROR_ALREADY_EXISTS = 183;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
IntPtr handle;
bool createdNew;
if ( !CreateManagedEvent(out handle,out createdNew) )
{
Print("Error creating named event.");
return;
}
if ( createdNew )
{
Print("App1 not running yet, exiting after a 10 second wait...");
Thread.Sleep( TimeSpan.FromSeconds(10) );
return;
}
Print("Sleeping for a few seconds...");
Thread.Sleep( TimeSpan.FromSeconds(2) );
Print("Done sleeping, setting event...");
ManualResetEvent _evt = new ManualResetEvent(false);
_evt.Handle = handle;
_evt.Set();
Print("Sleeping for 10 more seconds...");
Thread.Sleep( TimeSpan.FromSeconds(10) );
Print("Done");
}
/// <summary>
/// Creates a named event in the win32 space. This is a manual
/// reset event that is initially not signalled.
/// </summary>
/// <param name="handle"></param>
/// <param name="createdNew">true if it created a new one, false if it
opened an existing one</param>
/// <returns>true if it succeeds, otherwise false</returns>
static bool CreateManagedEvent(out IntPtr handle,out bool createdNew)
{
createdNew = false;
handle = CreateEvent(IntPtr.Zero, true,false, "MyNamedEvent");
int error = Marshal.GetLastWin32Error();
if ( handle == IntPtr.Zero )
return false;
createdNew = (error != ERROR_ALREADY_EXISTS);
return true;
}
static void Print(string format,params object[] args)
{
string msg = string.Format(format,args);
Trace.WriteLine(msg);
Console.WriteLine(msg);
}
}
}
[quoted text, click to view] "Chris B" <ChrisB@discussions.microsoft.com> wrote in message
news:B6006574-375B-47F2-AEBC-86235B690C0D@microsoft.com...
> I have the following situation:
>
> Process 1 creates Process 2 (using Process.Start(startInfo)
> Process 1 needs to wait until Process 2 is initialized before Process 1
can continue to execute
> Both processes are non-GUI processes.
>
> The problem that I am running into is that the Process.Start(startInfo)
returns immediately to Process 1. Therefore, process 1 does not wait on its
own for Process 2 to initialize.
[quoted text, click to view] >
> Process 2 can take a few seconds to intialize. Process 1 needs to halt
its execution until Process 2 is initialized. How can process 1 and 2
signal eachother to accomplish what I'm after?
[quoted text, click to view] >
> In process 1 I tried using a Mutex:
>
> Process process = Process.Start(startInfo);
>
> if (process != null)
> {
> Mutex m = new Mutex(false, "Mutex");
> m.WaitOne();
> ...
> }
>
> Process 2:
>
> Main...
> {
> bool mutexWasCreated = false;
> Mutex m = new Mutex(true, "Mutex", out mutexWasCreated);
> if (mutexWasCreated)
> {
> ...
> m.ReleaseMutex();
> }
> }
>
> this doesn't come close to working because process 1 gets the mutex before