tags:

views:

42

answers:

1

I have a single-instance app (c#, WPF, .net3.51). The check if the app is already instantiated is done via a Mutex. If the app is already running, I open a new window from within the already opened app-instance. This works fine so far.

However due to an app extension, I now must send the e.Args (or at least the first string of it) to the already running instance which resides in another process. How is this best done?

Additional Information
Currently I use a globaly registered Window-message that I send to all open apps via PostMessage (HWND_BROADCAST). My app looks for this message and opens a new window, if this message is received. An Idea would be to set a param of PostMessage. However I found a lot of bewildering information on this topic, therefore I had not the courage to go this way. Besides of that I thought of replacing the global PostMessage-call through another activation logic, since the global call seems to have some unlovely side-effects.

+4  A: 

You could use named pipes, which were added to the BCL in .NET 3.5.

Create the named pipe server (argument receiver) in the already-running instance and create the named pipe client (argument sender) in the duplicate app. Then, send the arguments from the client to server.

Either end of the named pipe can be created in C/C++ if needed. See the Win32 CreateNamedPipe function.

Below is a simple example with the client and server both running in a single program (the "FD1AF2B4..." GUID below is just a unique identifier to avoid colliding with already-existing named pipes on the system).

class Program
{
    static void Main(string[] args)
    {
        Thread writerThread = new Thread(new ThreadStart(WriterThread));
        writerThread.Start();

        Thread readerThread = new Thread(new ThreadStart(ReaderThread));
        readerThread.Start();
    }

    static void ReaderThread()
    {
        NamedPipeServerStream server = new NamedPipeServerStream("FD1AF2B4-575A-46E0-8DF5-8AB368CF6645");
        server.WaitForConnection();

        using (var reader = new BinaryReader(server))
        {
            string arguments = reader.ReadString();
            Console.WriteLine("Received: {0}", arguments);
        }
    }

    static void WriterThread()
    {
        NamedPipeClientStream client = new NamedPipeClientStream("FD1AF2B4-575A-46E0-8DF5-8AB368CF6645");
        client.Connect(Timeout.Infinite);

        using (var writer = new BinaryWriter(client))
        {
            writer.Write("/foo /bar:33 /baz:quux");
        }
    }
}
Chris Schmich
It's rather better to get `[assembly: Guid]` attribute value than hard-code someone
abatishchev
@Chris, I guess names pipe and sockets are only two reliable solutions, however, I prefer named pipes, can you tell me why you stated "overkill" , what is wrong with named pipe? I am just asking out of curiosity, otherwise your answer is perfect.
Akash Kava
@Akash: I suppose saying "overkill" was overkill :) Yes, it will work reliably. I think what I was trying to say was that this seems like a lot of code just to send a string from one app to another. It's certainly better than using the raw Win32 APIs though! I updated my response to remove the "overkill".
Chris Schmich
@Chris, thanks for your reply, I feel Win32 send message will not work in different workstations and different logins, and in non UI environment, but names pipes work everywhere so I prefer that, but if we want to limit it to one user only then send message is better deal, however both have same problems and advantages.
Akash Kava