By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,654 Members | 1,840 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,654 IT Pros & Developers. It's quick & easy.

sending events to another process

P: 3
Hi there,

I'm writing an application with forms. my main window can be hidden (minimize to a tray icon) like...Microsoft 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
Dec 9 '08 #1
Share this Question
Share on Google+
5 Replies


P: 52
Hi,

Try

Expand|Select|Wrap|Line Numbers
  1. using System;
  2. using System.Diagnostics;
  3. using System.Runtime.InteropServices;
  4. class AppMain
  5. {
  6.     [DllImport("user32.dll")] private static extern 
  7.         bool SetForegroundWindow(IntPtr hWnd);
  8.     [DllImport("user32.dll")] private static extern 
  9.         bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
  10.     [DllImport("user32.dll")] private static extern 
  11.         bool IsIconic(IntPtr hWnd);
  12.  
  13.     private const int SW_HIDE = 0;
  14.     private const int SW_SHOWNORMAL = 1;
  15.     private const int SW_SHOWMINIMIZED = 2;
  16.     private const int SW_SHOWMAXIMIZED = 3;
  17.     private const int SW_SHOWNOACTIVATE = 4;
  18.     private const int SW_RESTORE = 9;
  19.     private const int SW_SHOWDEFAULT = 10;
  20.  
  21.     static void Main()
  22.     {
  23.         // get the name of our process
  24.         string proc=Process.GetCurrentProcess().ProcessName;
  25.         // get the list of all processes by that name
  26.         Process[] processes=Process.GetProcessesByName(proc);
  27.         // if there is more than one process...
  28.         if (processes.Length > 1)
  29.         {
  30.             // Assume there is our process, which we will terminate, 
  31.             // and the other process, which we want to bring to the 
  32.             // foreground. This assumes there are only two processes 
  33.             // in the processes array, and we need to find out which 
  34.             // one is NOT us.
  35.  
  36.             // get our process
  37.             Process p=Process.GetCurrentProcess();
  38.             int n=0;        // assume the other process is at index 0
  39.             // if this process id is OUR process ID...
  40.             if (processes[0].Id==p.Id)
  41.             {
  42.                 // then the other process is at index 1
  43.                 n=1;
  44.             }
  45.             // get the window handle
  46.             IntPtr hWnd=processes[n].MainWindowHandle;
  47.             // if iconic, we need to restore the window
  48.             if (IsIconic(hWnd))
  49.             {
  50.                 ShowWindowAsync(hWnd, SW_RESTORE);
  51.             }
  52.             // bring it to the foreground
  53.             SetForegroundWindow(hWnd);
  54.             // exit our process
  55.             return;
  56.         }
  57.         // ... continue with your application initialization here.
  58.     }
  59. }
AniJos
Dec 9 '08 #2

P: 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].MainWindowHandle

is zero.

Thanx any way,

any other thoughts?

Uv
Dec 9 '08 #3

P: 52
Try Mutex.
You tried this also?

Expand|Select|Wrap|Line Numbers
  1. using System.Windows.Forms;
  2.  
  3. using System.Runtime.InteropServices;
  4.  
  5. using System.Text;
  6.  
  7. using System.Diagnostics;
  8.  
  9. using System.Threading;
  10.  
  11. using System.Reflection;
  12.  
  13. using System.IO;
  14.  
  15. namespace BusLayer
  16.  
  17. {
  18.  
  19. /// <summary>
  20.  
  21. /// Summary description for SingleApp.
  22.  
  23. /// </summary>
  24.  
  25. public class SingleApplication
  26.  
  27. {
  28.  
  29. public SingleApplication()
  30.  
  31. {
  32.  
  33. }
  34.  
  35. /// <summary>
  36.  
  37. /// Imports 
  38.  
  39. /// </summary>
  40.  
  41.  
  42. [DllImport("user32.dll")]
  43.  
  44. private static extern int ShowWindow(IntPtr hWnd, int nCmdShow);
  45.  
  46. [DllImport("user32.dll")]
  47.  
  48. private static extern int SetForegroundWindow(IntPtr hWnd);
  49.  
  50. [DllImport("user32.dll")]
  51.  
  52. private static extern int IsIconic(IntPtr hWnd);
  53.  
  54. /// <summary>
  55.  
  56. /// GetCurrentInstanceWindowHandle
  57.  
  58. /// </summary>
  59.  
  60. /// <returns></returns>
  61.  
  62. private static IntPtr GetCurrentInstanceWindowHandle()
  63.  
  64.  
  65. IntPtr hWnd = IntPtr.Zero;
  66.  
  67. Process process = Process.GetCurrentProcess();
  68.  
  69. Process[] processes = Process.GetProcessesByName(process.ProcessName);
  70.  
  71. foreach(Process _process in processes)
  72.  
  73. {
  74.  
  75. // Get the first instance that is not this instance, has the
  76.  
  77. // same process name and was started from the same file name
  78.  
  79. // and location. Also check that the process has a valid
  80.  
  81. // window handle in this session to filter out other user's
  82.  
  83. // processes.
  84.  
  85. if (_process.Id != process.Id &&
  86.  
  87. _process.MainModule.FileName == process.MainModule.FileName &&
  88.  
  89. _process.MainWindowHandle != IntPtr.Zero) 
  90.  
  91. {
  92.  
  93. hWnd = _process.MainWindowHandle;
  94.  
  95. break;
  96.  
  97. }
  98.  
  99. }
  100.  
  101. return hWnd;
  102.  
  103. }
  104.  
  105. /// <summary>
  106.  
  107. /// SwitchToCurrentInstance
  108.  
  109. /// </summary>
  110.  
  111. private static void SwitchToCurrentInstance()
  112.  
  113.  
  114. IntPtr hWnd = GetCurrentInstanceWindowHandle();
  115.  
  116. if (hWnd != IntPtr.Zero) 
  117.  
  118.  
  119. // Restore window if minimised. Do not restore if already in
  120.  
  121. // normal or maximised window state, since we don't want to
  122.  
  123. // change the current state of the window.
  124.  
  125. if (IsIconic(hWnd) != 0)
  126.  
  127. {
  128.  
  129. ShowWindow(hWnd, SW_RESTORE);
  130.  
  131. }
  132.  
  133. // Set foreground window.
  134.  
  135. SetForegroundWindow(hWnd);
  136.  
  137. }
  138.  
  139. }
  140.  
  141. /// <summary>
  142.  
  143. /// Execute a form base application if another instance already running on
  144.  
  145. /// the system activate previous one
  146.  
  147. /// </summary>
  148.  
  149. /// <param name="frmMain">main form</param>
  150.  
  151. /// <returns>true if no previous instance is running</returns>
  152.  
  153. public static bool Run(System.Windows.Forms.Form frmMain)
  154.  
  155. {
  156.  
  157. if(IsAlreadyRunning())
  158.  
  159. {
  160.  
  161. //set focus on previously running app
  162.  
  163. SwitchToCurrentInstance();
  164.  
  165. return false;
  166.  
  167. }
  168.  
  169. Application.Run(frmMain);
  170.  
  171. return true;
  172.  
  173. }
  174.  
  175. /// <summary>
  176.  
  177. /// for console base application
  178.  
  179. /// </summary>
  180.  
  181. /// <returns></returns>
  182.  
  183. public static bool Run()
  184.  
  185. {
  186.  
  187. if(IsAlreadyRunning()) 
  188.  
  189. {
  190.  
  191. return false;
  192.  
  193. }
  194.  
  195. return true;
  196.  
  197. }
  198.  
  199. /// <summary>
  200.  
  201. /// check if given exe alread running or not
  202.  
  203. /// </summary>
  204.  
  205. /// <returns>returns true if already running</returns>
  206.  
  207. private static bool IsAlreadyRunning()
  208.  
  209. {
  210.  
  211. string strLoc = Assembly.GetExecutingAssembly().Location;
  212.  
  213. FileSystemInfo fileInfo = new FileInfo(strLoc);
  214.  
  215. string sExeName = fileInfo.Name;
  216.  
  217. bool bCreatedNew;
  218.  
  219. mutex = new Mutex(true, "Global\\"+sExeName, out bCreatedNew);
  220.  
  221. if (bCreatedNew)
  222.  
  223. mutex.ReleaseMutex();
  224.  
  225. return !bCreatedNew;
  226.  
  227. }
  228.  
  229.  
  230. static Mutex mutex;
  231.  
  232. const int SW_RESTORE = 9;
  233.  
  234. }
  235.  
  236. }
Dec 9 '08 #4

P: 3
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?
Dec 9 '08 #5

nukefusion
Expert 100+
P: 221
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.

Expand|Select|Wrap|Line Numbers
  1.         [DllImport("user32.dll", SetLastError = true)]
  2.         static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
  3.  
  4.         [DllImport("user32.dll", SetLastError=true)]
  5.         static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
  6.  
  7.         [DllImport("user32.dll")]
  8.         static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
  9.         private const int SW_RESTORE = 9;
  10.  
  11.         public void restoreWindow(uint procIDtoFind)
  12.         { 
  13.             uint processID;
  14.             IntPtr hwnd = IntPtr.Zero;
  15.             // Loop through windows
  16.             do
  17.             {
  18.                 processID = 0;
  19.                 // Get HWND
  20.                 hwnd = FindWindowEx(IntPtr.Zero, hwnd, null, null);
  21.                 // Get process ID
  22.                 GetWindowThreadProcessId(hwnd, out processID);
  23.                 if (processID == procIDtoFind)
  24.                 {
  25.                     // restore the window
  26.                     ShowWindow(hwnd, SW_RESTORE);
  27.                     break;
  28.                 }
  29.             } 
  30.             while (!hwnd.Equals(IntPtr.Zero));
  31.         }
  32.  
Dec 9 '08 #6

Post your reply

Sign in to post your reply or Sign up for a free account.