如何在C#中确定当前聚焦进程的名称

10
例如,如果用户当前正在运行VS2008,则我希望该值为VS2008。

VS 2008 的进程是 devenv.exe。你认为从哪里可以获得 "VS2008"? - JRoppert
2个回答

18

我假设您想获取拥有当前聚焦窗口的进程名称。可以使用一些P/Invoke:

// The GetForegroundWindow function returns a handle to the foreground window
// (the window  with which the user is currently working).
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

// The GetWindowThreadProcessId function retrieves the identifier of the thread
// that created the specified window and, optionally, the identifier of the
// process that created the window.
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern Int32 GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

// Returns the name of the process owning the foreground window.
private string GetForegroundProcessName()
{
    IntPtr hwnd = GetForegroundWindow();

    // The foreground window can be NULL in certain circumstances, 
    // such as when a window is losing activation.
    if (hwnd == null)
        return "Unknown";

    uint pid;
    GetWindowThreadProcessId(hwnd, out pid);

    foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
    {
        if (p.Id == pid)
            return p.ProcessName;
    }

    return "Unknown";
}

2
小优化:Process p = Process.GetProcessById((int)pid); - thijs
当前窗口改变时,我能否收到事件通知? - manishKungwani
我认为它与编程有关,所以在这里询问了一下,无论如何,在这里找到了解决方案(未经验证):https://dev59.com/2G025IYBdhLWcg3wqXxo - manishKungwani
检查不应该是hwnd == IntPtr.Zero吗? - Ry-

4
using System;
using System.Windows;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace FGHook
{
    class ForegroundTracker
    {
        // Delegate and imports from pinvoke.net:

        delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
            IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);

        [DllImport("user32.dll")]
        static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
           hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
           uint idThread, uint dwFlags);

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

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


        [DllImport("user32.dll")]
        static extern bool UnhookWinEvent(IntPtr hWinEventHook);



        // Constants from winuser.h
        const uint EVENT_SYSTEM_FOREGROUND = 3;
        const uint WINEVENT_OUTOFCONTEXT = 0;

        // Need to ensure delegate is not collected while we're using it,
        // storing it in a class field is simplest way to do this.
        static WinEventDelegate procDelegate = new WinEventDelegate(WinEventProc);

        public static void Main()
        {
            // Listen for foreground changes across all processes/threads on current desktop...
            IntPtr hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
                    procDelegate, 0, 0, WINEVENT_OUTOFCONTEXT);

            // MessageBox provides the necessary mesage loop that SetWinEventHook requires.
            MessageBox.Show("Tracking focus, close message box to exit.");

            UnhookWinEvent(hhook);
        }

        static void WinEventProc(IntPtr hWinEventHook, uint eventType,
            IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
        {
            Console.WriteLine("Foreground changed to {0:x8}", hwnd.ToInt32());
            //Console.WriteLine("ObjectID changed to {0:x8}", idObject);
            //Console.WriteLine("ChildID changed to {0:x8}", idChild);
            GetForegroundProcessName();

        }
        static void GetForegroundProcessName()
        {
            IntPtr hwnd = GetForegroundWindow();

            // The foreground window can be NULL in certain circumstances, 
            // such as when a window is losing activation.
            if (hwnd == null)
                return;

            uint pid;
            GetWindowThreadProcessId(hwnd, out pid);

            foreach (System.Diagnostics.Process p in System.Diagnostics.Process.GetProcesses())
            {
                if (p.Id == pid)
                {
                    Console.WriteLine("Pid is: {0}",pid);
                    Console.WriteLine("Process name is {0}",p.ProcessName);
                    return;
                }
                //return;
            }

             Console.WriteLine("Unknown");
        }
    }
}

通过这段代码,您将收到每个前台变化的通知,并且控制台将打印出进程 PID 和名称。我敢打赌这个回答已经相当晚了,但是...这就是生活 :P - user2533527

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接