BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Windows Programming
.NET 2.0+

Getting the Active Process

When developing software that monitors running processes, it can be useful to obtain details of the currently active application. The .NET framework does not provide methods to permit this so Platform Invocation Services (P/Invoke) must be used.

Referencing the API Functions

When using Microsoft Windows, there can only be one active, or foreground, window. This is the window that can receive input from the user and whose owning thread has a slightly higher priority than other open windows. In some situations it can be useful to identify the active process that owns this window.

The .NET framework provides a class, named "Process", that allows you to examine the details of a running process. However, this class cannot be used to identify the program that is currently in use. In order to identify the foreground window and obtain a Process object linked to it, you must use Platform Invocation Services (P/Invoke) to call functions from the Windows API.

In this article we will create a simple application that identifies the active process. To begin, create a console application project.

Creating the API Declarations

In order to declare the API functions so that they can be called from C#, the DllImport attribute from the System.Runtime.InteropServices namespace is used. To simplify the code, add the following using directive to the code:

using System.Runtime.InteropServices;

The first of the API functions that we will use is "GetForegroundWindow". This function returns the handle of the foreground window, or null if no window is active. To declare the function, add the following to the class:

[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

The handle returned by the GetForegroundWindow function provides insufficient information to create a Process object. However, it can be passed to a second function, named "GetWindowThreadProcessId". This function returns the identifier for the thread that created a window and, optionally, the process identifier of the window. The handle of the window to interrogate is passed as a parameter. The process ID that we require is returned via an output parameter.

[DllImport("user32.dll")]
private static extern Int32 GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

Obtaining a Process Object for the Active Process

In this section of the article we will create a method that can be used to identify the active process and return a Process object that is linked to it. The Process class is found in the System.Diagnostics namespace so add the following using directive to the code:

using System.Diagnostics;

To begin, we will add the method declaration to the code. The method will return a Process object, or null if there is no active process. In the sample code below the method is static so that you can call it from the Main method of the console application without creating any other objects.

private static Process GetActiveProcess()
{
}

The first task is to call the GetForegroundWindow function to obtain the handle of the active window. To do so, add the following to the GetActiveProcess method:

IntPtr hwnd = GetForegroundWindow();

If the returned pointer is null, the method will return null. If not, some further processing is required. We can perform this check and return either null or a Process object from another method using the conditional operator and a ternary expression.

return hwnd != null ? GetProcessByHandle(hwnd) : null;

Finally, we need to create the GetPtrocessByHandle method. This method uses the GetWindowThreadProcessId API function to obtain the process ID and then the GetProcessById method of the Process class to obtain a Process object. The entire operation should be contained within a try / catch block in case a problem occurs when trying to obtain the process. This is unlikely but may happen if the active window is closed before the call is made.

private static Process GetProcessByHandle(IntPtr hwnd)
{
    try
    {
        uint processID;
        GetWindowThreadProcessId(hwnd, out processID);
        return Process.GetProcessById((int)processID);
    }
    catch { return null; }
}

Testing the Method

To test the method we will call it repeatedly in a while loop. After each call we will output the title of the active window and then pause the thread for a second. The pausing will use the Thread class from the System.Threading namespace so add the following directive:

using System.Threading;

To create the loop, add the following to the Main method.

while (true)
{
    Process currentProcess = GetActiveProcess();
    if (currentProcess != null)
        Console.WriteLine(currentProcess.MainWindowTitle);
    Thread.Sleep(1000);
}

You can now execute the program. Once running, try opening and closing windows and switching between applications before viewing the output in the console.

14 January 2010