1

I have an application that I have successfully applied a mutex to ensure only one instance of the application runs at once. It is pretty much a straight up copy of the solution here: What is the correct way to create a single-instance application?

The problem lies with the command line arguments of the second instance. I'd like to pass it to the first instance and I decided to try to use a MemoryMappedFile to accomplish this. I've modified the above mutex solution to try to accomplish this, but I get a FileNotFoundException when trying to "OpenExisting". I've tried a number of different solutions to try to resolve this, but none seem to work. What have I done wrong? (I intend to write the arg to the MMF, but for now I'm just writing in binary as a test):

namespace MyApplication
{
    static class Program
    {

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        static Mutex mutex = new Mutex(true, "{E6FD8A59-1754-4EA5-8996-2F1BC3AC5D87}");
        [STAThread]
        static void Main(string[] args)
        {
            if (mutex.WaitOne(TimeSpan.Zero, true))
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                if (args.Length == 1)
                {
                    Application.Run(new Form1(args[0]));
                }
                else
                {
                    Application.Run(new Form1());
                }

                mutex.ReleaseMutex();
            }
            else
            {
                NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_SHOWME, IntPtr.Zero, IntPtr.Zero);

                if (args.Length == 1)
                {
                    if (File.Exists(args[0]))
                    {
                        MemoryMappedFile mmf = MemoryMappedFile.CreateNew("filetoopen", 10000);

                        using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                        {
                            BinaryWriter writer = new BinaryWriter(stream);
                            writer.Write(1);
                        }
                        NativeMethods.PostMessage((IntPtr)NativeMethods.HWND_BROADCAST, NativeMethods.WM_OPENFILE, IntPtr.Zero, IntPtr.Zero);

                    }
                }
            }
        }
    }

    internal class NativeMethods
    {
        public const int HWND_BROADCAST = 0xffff;
        public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
        public static readonly int WM_OPENFILE = RegisterWindowMessage("WM_OPENFILE");
        [DllImport("user32.dll")]
        public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
        [DllImport("user32.dll")]
        public static extern int RegisterWindowMessage(string message);
    }
}

And the relevant code from Form1:

protected override void WndProc(ref Message m)
{
    if (m.Msg == NativeMethods.WM_SHOWME)
    {
            ShowMe(); //This works fine. Method excluded.
    }
    else if (m.Msg == NativeMethods.WM_OPENFILE)
    {

       try
       {
            MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("Global\\filetoopen"); 
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryReader reader = new BinaryReader(stream);
                MessageBox.Show(reader.ReadBoolean().ToString());
            }
       }
       catch (FileNotFoundException)
       {
           MessageBox.Show("File not found.");
       }

    }
    base.WndProc(ref m);
}
Community
  • 1
  • 1
matthew_b
  • 739
  • 1
  • 7
  • 18
  • All of this is already implemented in the .NET Framework, avoid inventing your own. Use the WindowsFormsApplicationBase class, you'll like its IsSingleInstance property and the StartupNextInstance event. – Hans Passant Mar 18 '16 at 13:33
  • I've looked into this, but can't seem to get it to work. I can reference Microsoft.VisualBasic in my application just fine, but not Microsoft.VisualBasic.ApplicationServices. When I do, I get the error: "The type or namespace name 'ApplicationServices' does not exist in the namespace 'Microsoft.VisualBasic' (are you missing an assembly reference?)" – matthew_b Mar 18 '16 at 13:41
  • Ask a team member or friend to look over your shoulder. Some odds he'll exclaim "read the error message dude!" but we can't see it as well as he can. – Hans Passant Mar 18 '16 at 13:47

0 Answers0