It's the Process, Stupid!
(SetActiveWindow and SwitchToThisWindow)
by Peter A. Bromberg, Ph.D.

Peter Bromberg

"A distributed system is one in which the failure of a computer you didn't even know existed
can render your own computer unusable." -- Leslie Lamport

A common request I see both on our messageboard forums here as well as at many other sites (and, recently, in the office, where I have discovered to my surprise that there is actually intelligent life!) is "How do I make another program (on the desktop or in the tray) come alive and be the foreground window?"



Since it just showed up yesterday once again on our forums, I thought it would be high time to whip up some API calls and a little helper class with a few static methods and "write it all up". Now the first thing I will advise, if you are interested in Windows API's and PInvoke, is to go visit (and please contribute to) PInvoke.Net a marvelous Flexwiki site created by Adam Nathan. Adam is a Lead Software Design Engineer on the .NET Framework Quality Assurance team at Microsoft. He is the author of .NET and COM: The Complete Interoperability Guide (SAMS, 2002), and a co-author of ASP.NET: Tips, Tutorials, and Code (SAMS, 2001). PInvoke.Net is now 1 year old and has literally thousands of online PInvoke API signatures many of which have been contributed by "viewers like you".

There are actually three classes we need to perform the neat trick decribed above, two of them are API calls that reside in User32.dll, and the third is the .NET Process class, which lives in the System.Diagnostics namespace. Without further ado, here is some code to look at. First my "very ultra simple no frills or extras" ProcUtils class:

using System;
using System.Diagnostics ;
using System.Runtime.InteropServices ;
namespace Utils
{ 
 public class ProcUtils
 {
  [DllImport("user32.dll")]
  static extern IntPtr SetActiveWindow(IntPtr hWnd);
  [DllImport("user32.dll", SetLastError=true)]
  static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

  public static Process[] GetRunningProcesses(string machineName)
  {  
   if(machineName==null || machineName==String.Empty) machineName=".";
   Process[] procs= System.Diagnostics.Process.GetProcesses(machineName);
   return procs;
  }

  public static void ActivateWindow(string ProcessName)
  {
           ActivateWindow(ProcessName,".");
  }
   
  public static void ActivateWindow(string ProcessName, string ComputerName)
  {
   try
   {
    Process myProc=null;
    Process[] procs= System.Diagnostics.Process.GetProcessesByName(ProcessName,ComputerName);    
    if(procs.Length ==0)
    {
     Process.Start(ProcessName);
     return;
    }
    else
    {
     myProc=procs[0];
     IntPtr hWnd =  myProc.MainWindowHandle;
     IntPtr ptr =SetActiveWindow(hWnd);
     SwitchToThisWindow(hWnd,true);
    }
   }
   catch 
   {
    throw new InvalidOperationException("Process Not Found");    
   }
  }
 }
}

And now, a simple C# Console app to "exercise" the methods:

using System;
using Utils;
namespace ProcessActivateTest
{ 
 class Tester
 {
  [STAThread]
  static void Main(string[] args)
  {
  System.Diagnostics.Process[] procs=Utils.ProcUtils.GetRunningProcesses(null);
  foreach(System.Diagnostics.Process p in procs)
   Console.WriteLine(p.ProcessName);

   Console.WriteLine("Press a key to continue.");
   Console.ReadLine(); 
        Utils.ProcUtils.ActivateWindow("IEXPLORE",".");   
  }
 }
}

The above will list the names of all running processes. Then when you press a key, it will either bring up Internet Explorer if it is already running along with the current page it was on, or start a new one and bring it to the foreground window position.

Obviously, there are many more APIs to study and a lot more you can do with the .NET Process class; this is just a starter to get you thinking. Cheers!

Download the Visual Studio.NET Solution that accompanies this article

 

 


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: