sending events to another process

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • uvklein
    New Member
    • Dec 2008
    • 3

    sending events to another process

    Hi there,

    I'm writing an application with forms. my main window can be hidden (minimize to a tray icon) like...Microsof t Outlook for example.

    this application can run only one instance (again like outlook) - meaning that on initialization, I check if there is another process running and if so I exit from the new one.

    in case the main window is hidden and the user tries to open the application again (from the start menu or desktop icon...), I want to re-display the main window and bring it to foreground as if it was restored from the tray icon (who's keep saying outlook???)

    my problem is that I don't know how to do so. I can send a window message in case the main window is minimized by using windows API but how can this be done if the window is hidden????

    Thanx in advance,

    Uv
  • anijos
    New Member
    • Nov 2008
    • 52

    #2
    Hi,

    Try

    Code:
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    class AppMain
    {
        [DllImport("user32.dll")] private static extern 
            bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")] private static extern 
            bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        [DllImport("user32.dll")] private static extern 
            bool IsIconic(IntPtr hWnd);
    
        private const int SW_HIDE = 0;
        private const int SW_SHOWNORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;
        private const int SW_SHOWMAXIMIZED = 3;
        private const int SW_SHOWNOACTIVATE = 4;
        private const int SW_RESTORE = 9;
        private const int SW_SHOWDEFAULT = 10;
    
        static void Main()
        {
            // get the name of our process
            string proc=Process.GetCurrentProcess().ProcessName;
            // get the list of all processes by that name
            Process[] processes=Process.GetProcessesByName(proc);
            // if there is more than one process...
            if (processes.Length > 1)
            {
                // Assume there is our process, which we will terminate, 
                // and the other process, which we want to bring to the 
                // foreground. This assumes there are only two processes 
                // in the processes array, and we need to find out which 
                // one is NOT us.
    
                // get our process
                Process p=Process.GetCurrentProcess();
                int n=0;        // assume the other process is at index 0
                // if this process id is OUR process ID...
                if (processes[0].Id==p.Id)
                {
                    // then the other process is at index 1
                    n=1;
                }
                // get the window handle
                IntPtr hWnd=processes[n].MainWindowHandle;
                // if iconic, we need to restore the window
                if (IsIconic(hWnd))
                {
                    ShowWindowAsync(hWnd, SW_RESTORE);
                }
                // bring it to the foreground
                SetForegroundWindow(hWnd);
                // exit our process
                return;
            }
            // ... continue with your application initialization here.
        }
    }
    AniJos

    Comment

    • uvklein
      New Member
      • Dec 2008
      • 3

      #3
      Thanx anijos for your reply but I've already done that. if the window is minimized it works fine but in my case the window is not visible and the window's handle return from the call

      IntPtr hWnd=processes[n].MainWindowHand le

      is zero.

      Thanx any way,

      any other thoughts?

      Uv

      Comment

      • anijos
        New Member
        • Nov 2008
        • 52

        #4
        Try Mutex.
        You tried this also?

        Code:
        using System.Windows.Forms;
        
        using System.Runtime.InteropServices;
        
        using System.Text;
        
        using System.Diagnostics;
        
        using System.Threading;
        
        using System.Reflection;
        
        using System.IO;
        
        namespace BusLayer
        
        {
        
        /// <summary>
        
        /// Summary description for SingleApp.
        
        /// </summary>
        
        public class SingleApplication
        
        {
        
        public SingleApplication()
        
        {
        
        }
        
        /// <summary>
        
        /// Imports 
        
        /// </summary>
        
        
        [DllImport("user32.dll")]
        
        private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
        
        [DllImport("user32.dll")]
        
        private static extern int SetForegroundWindow(IntPtr hWnd);
        
        [DllImport("user32.dll")]
        
        private static extern int IsIconic(IntPtr hWnd);
        
        /// <summary>
        
        /// GetCurrentInstanceWindowHandle
        
        /// </summary>
        
        /// <returns></returns>
        
        private static IntPtr GetCurrentInstanceWindowHandle()
        
        { 
        
        IntPtr hWnd = IntPtr.Zero;
        
        Process process = Process.GetCurrentProcess();
        
        Process[] processes = Process.GetProcessesByName(process.ProcessName);
        
        foreach(Process _process in processes)
        
        {
        
        // Get the first instance that is not this instance, has the
        
        // same process name and was started from the same file name
        
        // and location. Also check that the process has a valid
        
        // window handle in this session to filter out other user's
        
        // processes.
        
        if (_process.Id != process.Id &&
        
        _process.MainModule.FileName == process.MainModule.FileName &&
        
        _process.MainWindowHandle != IntPtr.Zero) 
        
        {
        
        hWnd = _process.MainWindowHandle;
        
        break;
        
        }
        
        }
        
        return hWnd;
        
        }
        
        /// <summary>
        
        /// SwitchToCurrentInstance
        
        /// </summary>
        
        private static void SwitchToCurrentInstance()
        
        { 
        
        IntPtr hWnd = GetCurrentInstanceWindowHandle();
        
        if (hWnd != IntPtr.Zero) 
        
        { 
        
        // Restore window if minimised. Do not restore if already in
        
        // normal or maximised window state, since we don't want to
        
        // change the current state of the window.
        
        if (IsIconic(hWnd) != 0)
        
        {
        
        ShowWindow(hWnd, SW_RESTORE);
        
        }
        
        // Set foreground window.
        
        SetForegroundWindow(hWnd);
        
        }
        
        }
        
        /// <summary>
        
        /// Execute a form base application if another instance already running on
        
        /// the system activate previous one
        
        /// </summary>
        
        /// <param name="frmMain">main form</param>
        
        /// <returns>true if no previous instance is running</returns>
        
        public static bool Run(System.Windows.Forms.Form frmMain)
        
        {
        
        if(IsAlreadyRunning())
        
        {
        
        //set focus on previously running app
        
        SwitchToCurrentInstance();
        
        return false;
        
        }
        
        Application.Run(frmMain);
        
        return true;
        
        }
        
        /// <summary>
        
        /// for console base application
        
        /// </summary>
        
        /// <returns></returns>
        
        public static bool Run()
        
        {
        
        if(IsAlreadyRunning()) 
        
        {
        
        return false;
        
        }
        
        return true;
        
        }
        
        /// <summary>
        
        /// check if given exe alread running or not
        
        /// </summary>
        
        /// <returns>returns true if already running</returns>
        
        private static bool IsAlreadyRunning()
        
        {
        
        string strLoc = Assembly.GetExecutingAssembly().Location;
        
        FileSystemInfo fileInfo = new FileInfo(strLoc);
        
        string sExeName = fileInfo.Name;
        
        bool bCreatedNew;
        
        mutex = new Mutex(true, "Global\\"+sExeName, out bCreatedNew);
        
        if (bCreatedNew)
        
        mutex.ReleaseMutex();
        
        return !bCreatedNew;
        
        }
        
        
        static Mutex mutex;
        
        const int SW_RESTORE = 9;
        
        }
        
        }

        Comment

        • uvklein
          New Member
          • Dec 2008
          • 3

          #5
          anijos, again, thanks for your help.

          this code won't contribute to the solution I seek for because the "already running" process's window is not visible, hence no handle is found. I think the solution should be something like firing an event to the process in order to notify it should restore the non-visible window. do you know if such thing can be done?

          Comment

          • nukefusion
            Recognized Expert New Member
            • Mar 2008
            • 221

            #6
            How about this. Identify the already existing process using code similar to that in the first sample posted by Anijos. Then use some code like the following sample to loop all windows and identify those that share the process ID, restoring them if necessary. You may want to tweak it slightly, i.e. to check whether a window is actually a notify icon or not, etc.

            Code:
                    [DllImport("user32.dll", SetLastError = true)]
                    static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
                    
                    [DllImport("user32.dll", SetLastError=true)]
                    static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
                    
                    [DllImport("user32.dll")]
                    static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
                    private const int SW_RESTORE = 9;
            
                    public void restoreWindow(uint procIDtoFind)
                    { 
                        uint processID;
                        IntPtr hwnd = IntPtr.Zero;
                        // Loop through windows
                        do
                        {
                            processID = 0;
                            // Get HWND
                            hwnd = FindWindowEx(IntPtr.Zero, hwnd, null, null);
                            // Get process ID
                            GetWindowThreadProcessId(hwnd, out processID);
                            if (processID == procIDtoFind)
                            {
                                // restore the window
                                ShowWindow(hwnd, SW_RESTORE);
                                break;
                            }
                        } 
                        while (!hwnd.Equals(IntPtr.Zero));
                    }

            Comment

            Working...