记录Windows中已关闭的所有Windows

我想在.NET中创建一个shell扩展或应用程序,记录所有关闭的窗口。 日志应包含创建窗口的进程名称。

我对如何做到这一点没有任何想法。 有什么指针吗?

这需要一个钩子,由SetWindowsHookEx,WH_SHELL钩子类型设置。 这种钩子类型需要一个可以注入进程的DLL,这样的DLL不能用C#编写。 64位操作系统和UAC也会产生很多障碍。 这个项目可以帮助你。

虽然你当然可以挂钩程序,但这对你想做的事情来说似乎有些过分。 这段代码应该让你非常接近(你必须做一些其他事情来查询Windows资源管理器进程的当前目录,我还没有这样做)。 此外,我的需求与您的不同,因为我的需求不仅仅是您对Window的定义(工具提示弹出在技术上是一个’ Window ‘)。 Explorer.exe,Chrome和Internet Explorer都可以为一个进程提供多个窗口,这两个窗口都会关闭。 根据您的需要,您可能需要查看:

枚举像alt-tab这样的窗口

EnumWindows仅过滤到alt-tab上显示的窗口

 using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; namespace ConsoleApplication { class Program { static void Main(string[] args) { ProcessListModel processes = Program.GetProccesses(); foreach (ProcessModel process in processes.Items) { Console.WriteLine("Program: " + process.Filename + "[" + process.IsWindowsExplorer.ToString() + "]"); Console.WriteLine("- Window Text: " + process.WindowText); } Console.ReadKey(); } [DllImport("user32")] public static extern int EnumWindows(EnumWindowsDelegate CallBack, ProcessListModel Processes); [DllImport("user32.dll")] private static extern IntPtr GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); [DllImport("user32")] internal static extern int GetAncestor(int hwnd, int gaFlags); [DllImport("user32")] internal static extern int GetLastActivePopup(int hWnd); [DllImport("user32")] internal static extern bool IsWindowVisible(int hWnd); [DllImport("User32.Dll")] public static extern void GetWindowText(int h, StringBuilder s, int nMaxCount); internal delegate bool EnumWindowsDelegate(int Hwnd, ProcessListModel Processes); internal static bool EnumWindowsCallBack(int Hwnd, ProcessListModel Processes) { ProcessModel model = new ProcessModel(); // Visible != Minimized (I think) if (!IsWindowVisible(Hwnd)) return true; // Can the Window be shown by using alt-tab if (IsAltTabWindow(Hwnd)) { model.WindowsHandle = Hwnd; try { int pid = 0; Program.GetWindowThreadProcessId(Hwnd, out pid); if (pid > 0) { try { model.ProcessID = pid; Process p = Process.GetProcessById(pid); if (p != null) { string filename = p.MainModule.FileName; filename = System.IO.Path.GetFileName(filename); model.Filename = filename; StringBuilder windowText = new StringBuilder(256); Program.GetWindowText(Hwnd, windowText, 256); model.WindowText = windowText.ToString(); if (filename.Contains("explorer.exe")) { model.IsWindowsExplorer = true; } Processes.Items.Add(model); } } // Do something or not, // catch probably if window process // is closed while querying info catch { } } } // Do something or not, // catch probably if window process // is closed while querying info catch { } } return true; } internal static bool IsAltTabWindow(int hwnd) { // Start at the root owner int hwndWalk = GetAncestor(hwnd, 3); // See if we are the last active visible popup int hwndTry; while ((hwndTry = GetLastActivePopup(hwndWalk)) != hwndTry) { if (IsWindowVisible(hwndTry)) break; hwndWalk = hwndTry; } return hwndWalk == hwnd; } public static ProcessListModel GetProccesses() { ProcessListModel processes = new ProcessListModel(); EnumWindowsDelegate enumCallback = new EnumWindowsDelegate(EnumWindowsCallBack); EnumWindows(enumCallback, processes); return processes; } public class ProcessListModel { public ProcessListModel() { this.Items = new List(); } public List Items { get; private set; } } public class ProcessModel { public int WindowsHandle { get; set; } public int ProcessID { get; set; } public string Filename { get; set; } public bool IsWindowsExplorer { get; set; } public string WindowText { get; set; } } } } 

输出:(我打开了很多窗口,这只是一小部分)

在此处输入图像描述

注意 :这不会枚举子窗口,所以如果我在IE中打开Internet Options并关闭它,那将是一个子窗口,而不是进程主窗口。 如果你需要子窗口,那么你必须以类似的方式实现EnumChildWindowsfunction 。

您所要求的实际上很难,没有直接的方法可以完全按照您的要求进行操作。

这是一篇较旧的文章,但我在过去使用它时成功使用.NET中的钩子:

Windows框架中的Windows挂钩