Search code examples
c#wpfipcnamed-pipeslauncher

C# - Inter-process Communication using Named Pipes (What Am I Doing Wrong?)


I'm trying to use IPC to allow my application to be opened exclusively via launcher. And for that I decided to use named pipes to pass a "request" and open my main application's login window after updates and checksum are done, but I'm quite new to C# and have run into some issues that I just can't seem to find where they're originating from...

After all updates are done and the launcher creates & request the application to open, the main application opens and then immediately closes without any error messages/logs. But if I try to open the application independently then it opens (And stays that way) but only in the processes' list, which by itself is another huge problem...

Launcher Side - MainWindow.xaml.cs:

private static async Task StarterAsync()
{
    string executablePath = "Application.exe";

    try
    {
        Process.Start(executablePath);

        using NamedPipeServerStream pipeServer = new("MyAppNP", PipeDirection.Out);
        await pipeServer.WaitForConnectionAsync();

        byte[] messageBytes = Encoding.UTF8.GetBytes("LaunchRequest");
        await pipeServer.WriteAsync(messageBytes);
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error: " + ex.Message);
    }
    finally
    {
        Application.Current.Shutdown();
    }
}

Main Application Side - App.xaml.cs:

namespace MyApp
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            string pipeName = "MyAppNP";
            using NamedPipeServerStream pipeServer = new(pipeName, PipeDirection.In);

            try
            {
                pipeServer.WaitForConnection();

                byte[] buffer = new byte[256];
                int bytesRead = pipeServer.Read(buffer, 0, buffer.Length);
                string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);

                if (message == "LaunchRequest")
                {
                    Login.Login loginWindow = new();
                    loginWindow.Show();
                }
                else
                {
                    MessageBox.Show("Launcher request mismatch. Exiting the application.");

                    pipeServer.Close();
                    Current.Shutdown();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message);

                pipeServer.Close();
                Current.Shutdown();
            }
        }
    }
}

Can someone with more experience help me find what is causing all these issues to happen?

I tried:

  • I checked some logs but couldn't find anything related to these problems.

  • I didn't try any debugging yet, I'm just too frustrated and want nothing more than to distance myself from anything code-related for the next 12 hours xD

I was expecting:

  • That after the launcher was done updating/checking important files it'd then send the request for the main application to open, when it did it'd close itself.

  • After that the Main application would run normally as it was before.


Solution

  • Both sides are creating a NamedPipeServerStream and waiting for the other side to connect; one of those should be NamedPipeClientStream and establishing the connection.

    Alternatively, you can use anonymous pipes (ProcessStartInfo.RedirectStandardOutput and friends). That's a more common approach when you have a parent/child process relationship.