检测外部进程的窗口是否闪烁/闪烁

Dea*_*one 5 c# windows hook winforms kernel32

我如何检测我无法控制的进程何时因某些通知而闪烁。我只见过专注于您可以控制的应用程序的解决方案。在我的情况下,可能有多个所述进程同时处于活动状态,其中一个可能正在闪烁。

这是我的尝试:

using (Process process = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.ToLower() == "..."))
using (ProcessModule module = process.MainModule)
{

    var a = GetModuleHandleEx(0x00000004, module.ModuleName, out var hModule);
    var hHook = SetWindowsHookEx(HookType.WH_SHELL, (code, param, lParam) =>
    {
        //test
        return IntPtr.Zero;
    }, hModule, 0);
}
Run Code Online (Sandbox Code Playgroud)

其中DLL导入如下:

public enum HookType : int
{
    WH_JOURNALRECORD = 0,
    WH_JOURNALPLAYBACK = 1,
    WH_KEYBOARD = 2,
    WH_GETMESSAGE = 3,
    WH_CALLWNDPROC = 4,
    WH_CBT = 5,
    WH_SYSMSGFILTER = 6,
    WH_MOUSE = 7,
    WH_HARDWARE = 8,
    WH_DEBUG = 9,
    WH_SHELL = 10,
    WH_FOREGROUNDIDLE = 11,
    WH_CALLWNDPROCRET = 12,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
}

delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool GetModuleHandleEx(UInt32 dwFlags, string lpModuleName, out IntPtr phModule);
Run Code Online (Sandbox Code Playgroud)

这里的问题是GetModuleHandleEx没有成功返回正确的句柄,可能是因为我没有进程是外部的,而且我没有将它加载到我的(这是不可能的)。

我正在使用 win 10 64 位,我的目标进程也是 64 位。

GLJ*_*GLJ 0

我本来打算将此作为评论,但我想提供一些代码来详细说明我的意思。

你说这个过程可能有多个实例。在您的代码中,您执行了 FirstOrDefault,获取您找到的与进程名称匹配的第一个实例。进程名称是否有可能重复?例如,我启动了 F# Interactive 并运行以下命令:

open System.Diagnostics;;
Process.GetProcesses() |> Array.map(fun(p) -> p.ProcessName);;

[|"chrome"; "fsiAnyCpu"; "svchost"; "InteractiveHost64"; "conhost"; "conhost"; "ServiceHub.RoslynCodeAnalysisService32"; "conhost"; "conhost"; ...|]
Run Code Online (Sandbox Code Playgroud)

“conhost”重复多次,意味着ProcessName可以重复。我建议尝试以下操作,删除带有Where的FirstOrDefault,确保您抓住符合您条件的每个进程。

    // First, lets grab all of the processes that match the desired name
    var flashingProcesses = Process.GetProcesses().Where(p => p.ProcessName.ToLower() == "...")
        // Next, lets Select what we want from these processes
        .Select(process =>
        {
            using (process)
            {

                using (ProcessModule module = process.MainModule)
                {

                    var moduleHandle = GetModuleHandleEx(0x00000004, module.ModuleName, out var hModule);
                    var hHook = SetWindowsHookEx(HookType.WH_SHELL, (code, param, lParam) =>
                    {
                        //test
                        return IntPtr.Zero;
                    }, hModule, 0);
                    return hHook;
                }
            }
        })
        // Finally, lets filter out the non-flashing proceses
        .Where(ptr => ptr != IntPtr.Zero);
    var count = flashingProcesses.Count();
    Console.WriteLine($"There are ${count} flashing processes");
Run Code Online (Sandbox Code Playgroud)

这可能不是确切的答案,但我希望它有所帮助。