本文介绍Windows系统下使用Win32API获取当前应用并关闭的方法。

思路
  1. 使用EnumWindows接口枚举当前窗口;
  2. 过滤掉不可用、隐藏、最小化的窗口;
  3. 过滤掉子窗口;
  4. 通过标题、类名过滤掉系统窗口;
  5. 使用PostMessage发送关闭窗口信息。
具体实现
// 过滤掉系统的一些窗口
private static string[] filterTitles = new string[1] { "program manager"};
private static string[] filterClasses = new string[5] { "shell_traywnd", "workerw", "button", "progman", "windows.ui.core.corewindow"};

private void CloseCurrentApp()
{
    CallBack sort = new CallBack(EnumCallback);
    EnumWindows(sort, 0);
    return;
}

private bool EnumCallback(IntPtr hwnd, int lParam)
{
    string title = GetWindowText(hwnd);
    StringBuilder className = new StringBuilder(256);
    int nRet = GetClassName(hwnd, className, className.Capacity);
    if (nRet == 0)
        className.Append("");

    if (!IsWindowVisible(hwnd))
        return true;

    if (!IsWindowEnabled(hwnd))
        return true;

    if (IsIconic(hwnd))
        return true;

    // 过滤掉子窗口
    IntPtr parent = GetParent(hwnd);
    string parentTitle = GetWindowText(parent);
    if (parent != IntPtr.Zero)
    {
        if (IsWindowVisible(parent) && IsWindowEnabled(parent))
            return true;
    }

    IntPtr owner = GetWindow(hwnd, GW_OWNER);
    if (owner != IntPtr.Zero)
    {
        if (IsWindowVisible(owner) && IsWindowEnabled(owner))
            return true;
    }

    if (!filterTitles.Contains(title.ToLower()) && !filterClasses.Contains(className.ToString().ToLower()))
    {
        PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0);
        Console.WriteLine("关闭窗口(句柄:{0}, 标题:{1})!", hwnd, title);

        #region 获取窗口信息
        int processID = -1;
        long threadID = -1;
        processID = GetWindowThreadProcessId(hwnd, out threadID);
        bool isiconic = IsIconic(hwnd);
        uint gwlStyle = (uint)GetWindowLong(hwnd, GWL_STYLE);

        IntPtr hProcess = OpenProcess(ProcessAccessFlags.QueryInformation, false, processID);
        string fullPath = "";
        if (hProcess != IntPtr.Zero)
        {
            int capacity = 1024;
            StringBuilder processName = new StringBuilder(capacity);
            QueryFullProcessImageName(hProcess, 0, processName, ref capacity);
            fullPath = processName.ToString(0, capacity);
            CloseHandle(hProcess);
        }

        Console.WriteLine("-------------------窗口info:---------------");
        Console.WriteLine("====标题:{0} 句柄:{1}====", title, hwnd);
        Console.WriteLine("====父窗口标题:{0} 父窗口句柄:{1}====", parentTitle, parent);
        Console.WriteLine("====进程ID:{0} 类名:{1}====", processID, className.ToString());
        Console.WriteLine("====进程名:{0}====", fullPath);
        Console.WriteLine("====isiconic:{0} 样式:{1}====", isiconic, gwlStyle);
        WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
        placement.length = System.Runtime.InteropServices.Marshal.SizeOf(placement);
        GetWindowPlacement(hwnd, ref placement);
        Console.WriteLine("====placement:{0}====", placement.showCmd);
        EnumPropsDelegate prop = new EnumPropsDelegate(EnumPropsProc);
        EnumProps(hwnd, prop);
        #endregion 获取窗口信息

        return false;
    }

    return true;
}

private bool EnumPropsProc(IntPtr hwnd, IntPtr lpszString, IntPtr hData)
{
    string propName = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(lpszString);
    Console.WriteLine("====属性:{0} 数据:{1}====", propName, hData);
    return true;
}

#region Win32Api
public const int GWL_STYLE = (-16);
public const int GWL_EXSTYLE = (-20);
public const int GW_OWNER = 4;
public const int WS_EX_TOOLWINDOW = 0x00000080;
public const int WM_SYSCOMMAND = 0x0112;
public const int WM_CLOSE = 0x10;
public const int SC_CLOSE = 0xF060;

public delegate bool CallBack(IntPtr hwnd, int lparam);
public delegate bool EnumPropsDelegate(IntPtr hwnd, IntPtr lpszString, IntPtr hData);

[DllImport("user32.dll")]
public static extern int EnumWindows(CallBack x, int y);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern int GetWindowText(IntPtr hWnd, System.Text.StringBuilder lpString, int nMaxCount);

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetWindowTextLength(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int GetClassName(IntPtr hWnd, System.Text.StringBuilder lpClassName, int nMaxCount);

[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hwnd);

[DllImport("user32.dll")]
public static extern bool IsWindowEnabled(IntPtr hwnd);

[DllImport("user32.dll", EntryPoint = "IsIconic")]
public static extern bool IsIconic(IntPtr hWnd);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hwnd);

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetWindow(IntPtr hwndParent, int nCmd);

[DllImport("user32.dll", EntryPoint = "GetWindowLongA", SetLastError = true)]
public static extern long GetWindowLong(IntPtr hwnd, int nIndex);

[DllImport("user32.dll", EntryPoint = "PostMessageA", SetLastError = true)]
public static extern bool PostMessage(IntPtr hwnd, uint Msg, uint wParam, uint lParam);

[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true,
     CharSet = CharSet.Unicode, ExactSpelling = true,
     CallingConvention = CallingConvention.StdCall)]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out long lpdwProcessId);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
     ProcessAccessFlags processAccess,
     bool bInheritHandle,
     int processId
);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags,
    [Out]System.Text.StringBuilder lpExeName, ref int lpdwSize);

[DllImport("coredll.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseHandle(IntPtr hObject);

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);

[DllImport("user32.dll")]
public static extern int EnumProps(IntPtr hWnd, EnumPropsDelegate lpEnumFunc);

public struct WINDOWPLACEMENT
{
    public int length;
    public int flags;
    public int showCmd;
    public System.Drawing.Point ptMinPosition;
    public System.Drawing.Point ptMaxPosition;
    public System.Drawing.Rectangle rcNormalPosition;
}

[Flags]
public enum ProcessAccessFlags : uint
{
    All = 0x001F0FFF,
    Terminate = 0x00000001,
    CreateThread = 0x00000002,
    VirtualMemoryOperation = 0x00000008,
    VirtualMemoryRead = 0x00000010,
    VirtualMemoryWrite = 0x00000020,
    DuplicateHandle = 0x00000040,
    CreateProcess = 0x000000080,
    SetQuota = 0x00000100,
    SetInformation = 0x00000200,
    QueryInformation = 0x00000400,
    QueryLimitedInformation = 0x00001000,
    Synchronize = 0x00100000
}

public static string GetWindowText(IntPtr hwnd)
{
    int capacity = GetWindowTextLength(hwnd) * 2;
    System.Text.StringBuilder lpString = new System.Text.StringBuilder(capacity);
    GetWindowText(hwnd, lpString, lpString.Capacity);
    if (lpString.Length > 0)
    {
        return lpString.ToString();
    }
    return string.Empty;
}
#endregion Win32Api

louzi
10 声望2 粉丝

努力做个优秀的程序员,写得一手漂亮的代码~