0

i need to access to full properties, methods of GUI FORM from the process that are not the first one launched.

   [MTAThread]
    static void Main(string[] args)
    {

        //check if the app is already running
        running = Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location)).Length > 1;
        Console.WriteLine("ALready running? " + running);

        if (running) // not first process
        {

            MessageBox.Show("Application already running in background!!!");
            closing = false;

            // HERE I NEED TO ACCESS TO gui-form defined by the first process and call some methods, modify properties ...
        }
        else { //first process
            if (!closing)// there are no process active
            {
                string selected = null;

                if (args.Length == 1) //apertura da context menu
                {
                    selected = args[0];
                    pathSend = selected;
                }
                Console.WriteLine("ALready running: opening " + pathSend);
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                //create userManagerUnit
                umu = new UserManagerUnit();

                //create a ManualResetEvent used from Server's Threads
                // true -> server start work  ||  false -> server stop work
                mre = new ManualResetEvent(true);

                // create Server istance
                //  active server
                server = new Server();
                serverThread = new Thread(server.EntryPoint) { Name = "serverThread" };
                serverThread.IsBackground = true;
                serverThread.Start();

                //create new client
                client = new Client();

                // create gui istance
                gui = new GUI(selected);

                //run application
                Application.Run(gui);


            }
        }    
    }

I tried with delegates, but i cannot delegate something that exist in an another process. My app is launched both from .exe/right click menu(on file/directory) So i can launch it N times, and each time i need to reload my gui with different parameters but i don't need to create N gui, just update the one created at first. Thanks

  • Possible duplicate of [Updating TextBox text from another process](https://stackoverflow.com/questions/10172035/updating-textbox-text-from-another-process) – Ian H. Oct 04 '17 at 14:24
  • What you want to achieve is inter-process communication, can you please check this? https://stackoverflow.com/questions/84855/what-is-the-best-choice-for-net-inter-process-communication – Oguz Ozgul Oct 04 '17 at 14:47
  • No Ian H. It is not about cross-thread invocation. – Oguz Ozgul Oct 04 '17 at 14:49
  • resolved! Thanks Oguz Ozgul, i've used MemoryMappedFile – Matteo Arzani Oct 04 '17 at 18:28

2 Answers2

0

One way would be with windows messages. Something like this:

[DllImport("user32.dll")]
static extern uint RegisterWindowMessage(string lpString);

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

private uint msgId = RegisterWindowMessage("notification");

// Transmitter
private void button1_Click(object sender, EventArgs e)
{
    Process[] myInstances = Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location));

    if (myInstances.Length == 0) return;

    foreach (Process instance in myInstances)
    {
        IntPtr handle = instance.MainWindowHandle;
        SendMessage(handle, (int)msgId, IntPtr.Zero, IntPtr.Zero);
    }            
}

// Receiver
protected override void WndProc(ref Message msg)
{
    if (msg.Msg == msgId) MessageBox.Show("well, notification is here now.");
    base.WndProc(ref msg);
}

This sends "notification" messages to all instances of the application, including itself.

Avo Nappo
  • 620
  • 4
  • 9
0

I have resolved with a MemoryMappedFile !!! Basically 1) the main process create the file; 2) other process write in first line of file: (int32)length + buffer containing the label to pass my gui 3) in the gui i read from the memory mapped file and i retrieve the label to update

    [MTAThread]
    static void Main(string[] args)
    {

        //check if the app is already running
        running = Process.GetProcessesByName(System.IO.Path.GetFileNameWithoutExtension(System.Reflection.Assembly.GetEntryAssembly().Location)).Length > 1;
        Console.WriteLine("ALready running? " + running);

        if (running)
        {

            string selected = null;

            if (args.Length == 1) //apertura da context menu
            {
                selected = args[0];
                pathSend = selected;
            }
            // open the memory-mapped 
            MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("myMappedFile");
            // declare accessor to write on file
            MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor();
            if (selected != null)
            {
                //write in the file: Length|Path
                //4 offset cause length is on 32 bit
                byte[] Buffer = ASCIIEncoding.ASCII.GetBytes(selected);
                accessor.Write(0, Buffer.Length);
                accessor.Flush();
                accessor.WriteArray(4, Buffer, 0, Buffer.Length);
                accessor.Flush();
                //write path in the memory mapped file
            }
            else
            {
                //write in the file: Lenght|Path
                accessor.Write(0, 0);
            }

            //MessageBox.Show("Application already running in background!!!");
            closing = false;

        }
        else {
            if (!closing)// there are no process active
            {
                // create a memory-mapped file of length 1000 bytes and give it a 'map name' of 'test'
                MemoryMappedFile mmf = MemoryMappedFile.CreateNew("myMappedFile", 1000);

                string selected = null;

                if (args.Length == 1) //apertura da context menu
                {
                    selected = args[0];
                    pathSend = selected;
                }
                Console.WriteLine("ALready running: opening " + pathSend);
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                //create userManagerUnit
                umu = new UserManagerUnit();

                //create a ManualResetEvent used from Server's Threads
                // true -> server start work  ||  false -> server stop work
                mre = new ManualResetEvent(true);

                // create Server istance
                //  active server
                server = new Server();
                serverThread = new Thread(server.EntryPoint) { Name =   "serverThread" };
                serverThread.IsBackground = true;
                serverThread.Start();

                //create new client
                client = new Client();

                // create gui istance
                gui = new GUI(selected);

                //run application
                Application.Run(gui);


            }
        }    
    }

.... GUI form part: (in a function that is called periodically for update) ... //LAUNCH GUI WITH NEW PATH SEND IF THE USER INTERACT WITH NEW FILES/DIRECTORIES WITH RIGTH CLICK ON THEM //....

            // read the integer value at position 500
            MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor();
            int l = accessor.ReadInt32(0);
            accessor.Flush();
            // print it to the console
            //Console.WriteLine("The memory mapped value is {0}", l);
            if (l != 0)
            {
                //get path as bytes
                byte[] Buffer = new byte[l];
                accessor.ReadArray(4, Buffer, 0, Buffer.Length);
                accessor.Flush();
                //convert bytes to string
                string newPath = ASCIIEncoding.ASCII.GetString(Buffer);
               // Console.WriteLine("The newPath is " + newPath);

                if (newPath.CompareTo(LANSharingApp.pathSend) != 0)// it's a new path
                {
                    LANSharingApp.pathSend = newPath;
                    this.pathBox.Text = newPath;
                    LANSharingApp.umu.clearMetroButtons();
                    base.SetVisibleCore(true);
                    this.WindowState = FormWindowState.Normal;
                }
            }

....

Thanks a lot all