Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get process name and title of the top window on Windows / C#

As in the topic... or better - how to get this information from events when the top window changes?

like image 985
Michal Czardybon Avatar asked Apr 14 '10 06:04

Michal Czardybon


3 Answers

Thanks for hints. So I should use P/Invoke anyhow. Here is the complete code:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace CuckooCoach
{
    class Monitor
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();

        [DllImport("user32.dll")]
        static extern int GetWindowTextLength(IntPtr hWnd);

        //  int GetWindowText(
        //      __in   HWND hWnd,
        //      __out  LPTSTR lpString,
        //      __in   int nMaxCount
        //  );
        [DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        //  DWORD GetWindowThreadProcessId(
        //      __in   HWND hWnd,
        //      __out  LPDWORD lpdwProcessId
        //  );
        [DllImport("user32.dll")]
        private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

        //HANDLE WINAPI OpenProcess(
        //  __in  DWORD dwDesiredAccess,
        //  __in  BOOL bInheritHandle,
        //  __in  DWORD dwProcessId
        //);
        [DllImport("kernel32.dll")]
        private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);

        [DllImport("kernel32.dll")]
        private static extern bool CloseHandle(IntPtr handle);

        //  DWORD WINAPI GetModuleBaseName(
        //      __in      HANDLE hProcess,
        //      __in_opt  HMODULE hModule,
        //      __out     LPTSTR lpBaseName,
        //      __in      DWORD nSize
        //  );
        [DllImport("psapi.dll")]
        private static extern uint GetModuleBaseName(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        //  DWORD WINAPI GetModuleFileNameEx(
        //      __in      HANDLE hProcess,
        //      __in_opt  HMODULE hModule,
        //      __out     LPTSTR lpFilename,
        //      __in      DWORD nSize
        //  );
        [DllImport("psapi.dll")]
        private static extern uint GetModuleFileNameEx(IntPtr hWnd, IntPtr hModule, StringBuilder lpFileName, int nSize);

        public static string GetTopWindowText()
        {
            IntPtr hWnd = GetForegroundWindow();
            int length = GetWindowTextLength(hWnd);
            StringBuilder text = new StringBuilder(length + 1);
            GetWindowText(hWnd, text, text.Capacity);
            return text.ToString();
        }

        public static string GetTopWindowName()
        {
            IntPtr hWnd = GetForegroundWindow();
            uint lpdwProcessId;
            GetWindowThreadProcessId(hWnd, out lpdwProcessId);

            IntPtr hProcess = OpenProcess(0x0410, false, lpdwProcessId);

            StringBuilder text = new StringBuilder(1000);
            //GetModuleBaseName(hProcess, IntPtr.Zero, text, text.Capacity);
            GetModuleFileNameEx(hProcess, IntPtr.Zero, text, text.Capacity);

            CloseHandle(hProcess); 

            return text.ToString();
        }

    }
}
like image 192
Michal Czardybon Avatar answered Nov 15 '22 21:11

Michal Czardybon


You can find window handle by process name using this code:

 Process[] processes = Process.GetProcessesByName(m.ProcessName);
                                    if (processes != null && processes.Length > 0)
                                    {
                                        Process process = processes[0];
                                        process.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
                                        process.Refresh();
                                        if (process.MainWindowHandle != IntPtr.Zero)
                                        { // process.mainwindows handle is needed for you

and than you can find window text by handle title = GetWindowTitle(process.MainWindowHandle);

private String GetWindowTitle(IntPtr hWn)
        {
            object LParam = new object();
            int WParam = 0;
            StringBuilder title = new StringBuilder(1024);
            SendMessage(hWn, WM_GETTEXT, WParam, LParam);
            GetWindowText(hWn, title, title.Capacity);
            return title.ToString();

        }

You need following declarations to call winapi functions:

 [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, object lParam);
like image 33
st78 Avatar answered Nov 15 '22 21:11

st78


I don't think there is a .Net way of doing this, so I think you will have use PInvoke.

Here's some sample code http://www.pinvoke.net/default.aspx/user32.getforegroundwindow

And as can be seen in that link there's a project (Managed Windows API) that wraps that up in managed code if you don't want to deal with the PInvoke code yourself.

like image 24
Hans Olsson Avatar answered Nov 15 '22 19:11

Hans Olsson