• Win32Api -- 关闭当前应用


    本文介绍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
    
    转载请注明出处,欢迎交流。
  • 相关阅读:
    Redis从0到精通Redis持久化
    Redis从0到精通事务
    Redis从0到精通Nosql概述
    LAMP源码MySQL集群版搭建 枯木
    Apache mod_cband 流量控制 枯木
    MySQL簇概述 枯木
    RHEL6 sysbench libtool error 枯木
    shell脚本不换行刷新数据 枯木
    MySQLCluster 枯木
    MFS部署 枯木
  • 原文地址:https://www.cnblogs.com/louzixl/p/14381984.html
Copyright © 2020-2023  润新知