// internal const int PacketFixedSize = 29;

        public static SubsequentProcessPacket FromStream(Stream stream)
        {
            SubsequentProcessPacket result = new SubsequentProcessPacket();
            var buffer = result.BuildPacket();

            if (stream.Read(buffer, 0, buffer.Length) == buffer.Length)
            {
                int sizeofInt  = sizeof(int),
                    sizeofBool = sizeof(bool),
                    sizeofLong = sizeof(long);

                byte[] guiddata = new byte[buffer.Length - sizeofInt - sizeofBool - sizeofLong];
                Buffer.BlockCopy(buffer, sizeofInt + sizeofBool, guiddata, 0, guiddata.Length);

                result.ArgumentCount   = BitConverter.ToInt32(buffer, 0);
                result.IsMemorySharing = BitConverter.ToBoolean(buffer, sizeofInt);
                result.SharedID        = new Guid(guiddata);
                result.DataLength      = BitConverter.ToInt64(buffer, sizeofInt + sizeofBool + guiddata.Length);

                return(result);
            }
            else
            {
                return(null);
            }
        }
        private void CreateSingleInstanceModel(string[] args)
        {
            SubsequentProcessPacket packetHolder = new SubsequentProcessPacket();

            byte[] dummypacket = packetHolder.BuildPacket();
            using (Mutex mutex = new Mutex(true, Path.Combine("Global", this._instanceID), out var isNewInstanceJustForMeHuh))
                using (EventWaitHandle waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset, this._instanceID))
                {
                    RegisteredWaitHandle waiter = null;
                    try
                    {
                        if (isNewInstanceJustForMeHuh)
                        {
                            using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew(this._instanceID + "-args", dummypacket.Length, MemoryMappedFileAccess.ReadWrite))
                            {
                                waiter = ThreadPool.RegisterWaitForSingleObject(waitHandle, new WaitOrTimerCallback((sender, signal) =>
                                {
                                    using (var stream = mmf.CreateViewStream(0, dummypacket.Length))
                                    {
                                        var packet       = SubsequentProcessPacket.FromStream(stream);
                                        string[] theArgs = new string[packet.ArgumentCount];

                                        string readerIDstring = packet.SharedID.ToString();
                                        if (EventWaitHandle_TryOpenExisting(this._instanceID + "-argreader" + readerIDstring, out var argWaiter))
                                        {
                                            try
                                            {
                                                if (packet.ArgumentCount != 0)
                                                {
                                                    using (MemoryMappedFile argdata = MemoryMappedFile.OpenExisting(this._instanceID + "-argdata" + readerIDstring, MemoryMappedFileRights.Read))
                                                        using (BinaryReader br = new BinaryReader(argdata.CreateViewStream(0, packet.DataLength, MemoryMappedFileAccess.Read)))
                                                        {
                                                            int biggestbuffer = br.ReadInt32();
                                                            byte[] buffer     = new byte[biggestbuffer];

                                                            for (int i = 0; i < theArgs.Length; i++)
                                                            {
                                                                int bufferlength = br.ReadInt32();
                                                                br.Read(buffer, 0, bufferlength);
                                                                theArgs[i] = System.Text.Encoding.Unicode.GetString(buffer, 0, bufferlength);
                                                            }
                                                        }
                                                }

                                                this.OnStartupNextInstance(new StartupNextInstanceEventArgs(theArgs));
                                            }
                                            catch (Exception ex)
                                            {
                                                if (System.Diagnostics.Debugger.IsAttached)
                                                {
                                                    throw;
                                                }
                                                else
                                                {
                                                    this.OnStartupNextInstance(new StartupNextInstanceEventArgs(ex));
                                                }
                                            }
                                            finally
                                            {
                                                argWaiter.Set();
                                                argWaiter.Dispose();
                                            }
                                        }
                                    }
                                    // this._instanceID + "-argreader" + readerID
                                    // this.OnStartupNextInstance(e);
                                }), null, -1, false);
                                this.OnStartup(new StartupEventArgs(args));
                            }
                        }
                        else
                        {
                            Guid readerID = Guid.NewGuid();
                            using (Mutex writerMutex = new Mutex(true, Path.Combine("Global", this._instanceID + "-argwriter"), out var isNewWriterMutex))
                            {
                                if (!isNewWriterMutex)
                                {
                                    while (!writerMutex.WaitOne())
                                    {
                                    }
                                }
                                using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(this._instanceID + "-args", MemoryMappedFileRights.Write))
                                    using (var accessor = mmf.CreateViewStream(0, dummypacket.Length, MemoryMappedFileAccess.Write))
                                    {
                                        try
                                        {
                                            if (args.Length == 0)
                                            {
                                                using (EventWaitHandle argWaiter = new EventWaitHandle(false, EventResetMode.ManualReset, this._instanceID + "-argreader" + readerID.ToString(), out var newInstanceForArgs))
                                                {
                                                    if (newInstanceForArgs)
                                                    {
                                                        packetHolder.ArgumentCount   = args.Length;
                                                        packetHolder.IsMemorySharing = true;
                                                        packetHolder.SharedID        = readerID;
                                                        packetHolder.DataLength      = 0;

                                                        int size = packetHolder.BuildPacket(dummypacket, 0);

                                                        accessor.Write(dummypacket, 0, size);
                                                        waitHandle.Set();
                                                        // wait until the reader finished get the args
                                                        // May cause deadlock if the main instance fail to call Set(). So a timeout is required.
                                                        // 10-second is overkill but it's safe???
                                                        argWaiter.WaitOne(TimeSpan.FromSeconds(10));
                                                    }
                                                    else
                                                    {
                                                        accessor.Write(dummypacket, 0, dummypacket.Length);
                                                        waitHandle.Set();
                                                    }
                                                }
                                            }
                                            else
                                            {
                                                int sizeofInt = sizeof(int);
                                                // Ensure that the buffer will never be below 4-byte integer so that we can use the buffer for the int->byte conversion.
                                                int  biggestSize = 0;
                                                long datasize    = (args.Length * sizeofInt) + sizeofInt;
                                                for (int i = 0; i < args.Length; i++)
                                                {
                                                    int aaaaaa = System.Text.Encoding.Unicode.GetByteCount(args[i]);
                                                    if (biggestSize < aaaaaa)
                                                    {
                                                        biggestSize = aaaaaa;
                                                    }
                                                    datasize += aaaaaa;
                                                }

                                                biggestSize += sizeofInt;
                                                if (biggestSize < dummypacket.Length)
                                                {
                                                    biggestSize = dummypacket.Length;
                                                }

                                                packetHolder.ArgumentCount   = args.Length;
                                                packetHolder.IsMemorySharing = true;
                                                packetHolder.SharedID        = readerID;
                                                packetHolder.DataLength      = datasize;

                                                using (MemoryMappedFile argData = MemoryMappedFile.CreateNew(this._instanceID + "-argdata" + readerID.ToString(), datasize, MemoryMappedFileAccess.ReadWrite))
                                                    using (EventWaitHandle argWaiter = new EventWaitHandle(false, EventResetMode.ManualReset, this._instanceID + "-argreader" + readerID.ToString(), out var newInstanceForArgs))
                                                    {
                                                        if (newInstanceForArgs)
                                                        {
                                                            byte[] buffer = new byte[biggestSize];
                                                            using (var datastream = argData.CreateViewStream(0, datasize, MemoryMappedFileAccess.Write))
                                                            {
                                                                GetBytesFromIntToBuffer(biggestSize, buffer, 0);

                                                                datastream.Write(buffer, 0, sizeofInt);

                                                                for (int i = 0; i < args.Length; i++)
                                                                {
                                                                    int encodedbytelength = System.Text.Encoding.Unicode.GetBytes(args[i], 0, args[i].Length, buffer, sizeofInt);
                                                                    GetBytesFromIntToBuffer(encodedbytelength, buffer, 0);

                                                                    datastream.Write(buffer, 0, encodedbytelength + sizeofInt);
                                                                }

                                                                datastream.Flush();
                                                            }

                                                            int packetsize = packetHolder.BuildPacket(buffer, 0);
                                                            accessor.Write(buffer, 0, packetsize);
                                                            buffer = null;
                                                            waitHandle.Set();
                                                            // wait until the reader finished get the args
                                                            // May cause deadlock if the main instance fail to call Set(). So a timeout is required.
                                                            // 10-second is overkill but it's safe???
                                                            argWaiter.WaitOne(TimeSpan.FromSeconds(10));
                                                        }
                                                        else
                                                        {
                                                            //
                                                            throw new Exception();
                                                        }
                                                    }
                                            }
                                        }
                                        catch
                                        {
                                            accessor.Write(dummypacket, 0, dummypacket.Length);
                                            waitHandle.Set();

                                            if (System.Diagnostics.Debugger.IsAttached)
                                            {
                                                throw;
                                            }
                                        }
                                    }

                                if (isNewWriterMutex)
                                {
                                    writerMutex.ReleaseMutex();
                                }
                            }
                        }
                    }
                    finally
                    {
                        if (waiter != null)
                        {
                            waiter.Unregister(null);
                        }

                        // Is this required since the mutext is disposed and the instance is exited anyway?
                        // Better safe than sorry.
                        if (isNewInstanceJustForMeHuh)
                        {
                            mutex.ReleaseMutex();
                        }
                    }
                }
        }