简体   繁体   English

如何在Windows / C#上获取顶部窗口的进程名称和标题

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

如同主题......或更好 - 如何在顶部窗口更改时从事件中获取此信息?

Thanks for hints. 谢谢你的提示。 So I should use P/Invoke anyhow. 所以无论如何我应该使用P / Invoke。 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();
        }

    }
}

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); 而且你可以通过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: 您需要以下声明才能调用winapi函数:

 [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);

I don't think there is a .Net way of doing this, so I think you will have use PInvoke. 我不认为有这样的.Net方式,所以我认为你将使用PInvoke。

Here's some sample code http://www.pinvoke.net/default.aspx/user32.getforegroundwindow 这是一些示例代码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. 从该链接中可以看出,如果您不想自己处理PInvoke代码,则会有一个项目(托管Windows API)将其包装在托管代码中。

For the window title, you'll have to do a P/Invoke of GetWindowText with the HWND returned from GetForegroundWindow(). 对于窗口标题,您必须使用从GetForegroundWindow()返回的HWND进行GetWindowText的P / Invoke。

As for the process info, I believe that P/Invoking GetWindowModuleFileName should work. 至于进程信息,我相信P / Invoking GetWindowModuleFileName应该可行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM