简体   繁体   English

Windows API EnumWindows和EnumChildWindows函数在Windows XP和7中的行为是否不同

[英]Do Windows API EnumWindows and EnumChildWindows functions behave differently in Windows XP and 7

I am using 2 Windows API exported functions from c#.NET 4.0. 我正在使用2个Windows API从c#.NET 4.0导出的函数。

private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";

I am searching for windows titles of Excel main windows' child windows (Excel has an MDI window of class XLMAIN containing 0, 1 or more child windows with EXCEL7 window class). 我正在搜索Excel主窗口的子窗口的窗口标题(Excel具有XLMAIN类的MDI窗口,其中包含0、1个或更多具有EXCEL7窗口类的子窗口)。

The goal is to find if a an excel workbook is being opened in any instances of Excel application. 目的是查找是否在Excel应用程序的任何实例中都打开了excel工作簿。 I did it by finding all XLMAIN IntPtr (pointers) and traversing children until I get a IntPtr with EXCEL7 window class at which point I can read child windows title and determine if a file is opened. 我通过查找所有XLMAIN IntPtr(指针)并遍历子级来完成此操作,直到获得带有EXCEL7窗口类的IntPtr,此时可以读取子级窗口标题并确定是否打开了文件。

Basically this works on Windows XP, but not on Windows 7. I didn't try in Windows Vista. 基本上,这在Windows XP上有效,但在Windows 7上无效。我没有在Windows Vista中尝试过。 What has changed? 有什么变化? Can someone debug the issue since I don't have Windows 7. Thanks Rad 有人可以调试问题,因为我没有Windows7。谢谢Rad

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace ExcelChildWindowsTitle
{
    public static void Main(string[] args)
    {
        //XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
        //IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
        //bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);

        bool excelProofFound = WindowTitleSearcher.SearchForWindow("icui-20110331.xls");
        if (excelProofFound)
            Console.Write(":)))))))) Proof File opened in an Excel process;");
        else
        {
            Console.Write(":|Proof File not found");
        }
    }

public static class WindowTitleSearcher
{
    private const string WINDOW_EXCEL7 = "XLMAIN";
    private const string CHILDWINDOW_XLMAIN = "EXCEL7";

    public static bool SearchForWindow(string title)
    {
        SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty};
        EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
        return (int)sd.hWnd > 0;
    }

    private static bool EnumProc(IntPtr hWnd, ref SearchData data)
    {
        const bool directOnly = false;
        // Check classname and title 
        // This is different from FindWindow() in that the code below allows partial matches
        StringBuilder sb1 = new StringBuilder(1024);
        GetClassName(hWnd, sb1, sb1.Capacity);
        Debug.WriteLine(sb1.ToString());
        if (sb1.ToString().StartsWith(data.Wndclass))
        {
            RecursiveEnumChildWindows(hWnd, directOnly, ref data);
            if ((int)data.hWnd > 0)
            {
                // Found the wnd, halt enumeration
                return false;
            }
        }
        return true;
    }

    private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
    {
        EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
        {
            bool add = true;
            if (directOnly)
            {
                add = GetParent(hwnd) == parentHwnd;
            }

            StringBuilder sb1 = new StringBuilder(1024);
            GetClassName(hwnd, sb1, sb1.Capacity);
            Debug.WriteLine("Child:" + sb1.ToString());

            if (add)
            {

                if (sb1.ToString().StartsWith(data1.ChildWndclass))
                {
                    sb1 = new StringBuilder(1024);
                    //Window Caption
                    GetWindowText(hwnd, sb1, sb1.Capacity);
                    if (sb1.ToString().Contains(data1.ChildTitle))
                    {
                        data1.hWnd = hwnd;
                        data1.WorkbookTitle = sb1.ToString();
                        return false; // Found the wnd, halt enumeration
                    }
                }
            }
            return true;
        }, ref data);
    }

    private struct SearchData
    {
        // You can put any vars in here...
        public string Wndclass;
        public string ChildWndclass;
        public string ChildTitle;
        public IntPtr hWnd;
        public string WorkbookTitle;
    }
    # region Windows API declarations
    private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);

    //private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);

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

    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    private static extern IntPtr GetParent(IntPtr hWnd);

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

Why use hacks like this when MS Office has documented automation support? 当MS Office已记录了自动化支持时,为什么要使用这种黑客手段?

You can use .NET , the older COM/OLE automation interfaces or the super old DDE interface . 您可以使用.NET ,较旧的COM / OLE 自动化 接口或较旧的DDE接口

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;


namespace ExcelChildWindowsTitle
{
    class Program
    {
        static void Main(string[] args)
        {
            //XLMAIN/EXCELDESK/EXCEL7 as seen by Spy++ VS 2010 utility
            //IntPtr hWnd = WndSearcher.SearchForWindow("XLMAIN", "EXCEL7", "icui-20110331.xls", ref workbookTitle);
            //bool excelProofFound = WindowTitleSearcher.SearchForWindow("XLMAIN", "EXCEL7", "testfileopenedinEXCEL.xls", ref workbookTitle);

            bool excelProofFound = WindowTitleSearcher.SearchForWindow("file name here");
            if (excelProofFound)
                Console.Write(":)))))))) Proof File opened in an Excel process;");
            else
            {
                Console.Write(":|Proof File not found");
            }
        }

        public static class WindowTitleSearcher
        {
            private const string WINDOW_EXCEL7 = "XLMAIN";
            private const string CHILDWINDOW_XLMAIN = "EXCEL7";

            public static bool SearchForWindow(string title)
            {
                SearchData sd = new SearchData { Wndclass = WINDOW_EXCEL7, ChildWndclass = CHILDWINDOW_XLMAIN, ChildTitle = title, WorkbookTitle = String.Empty };
                EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
                return (int)sd.hWnd > 0;
            }

            private static bool EnumProc(IntPtr hWnd, ref SearchData data)
            {
                const bool directOnly = false;
                // Check classname and title 
                // This is different from FindWindow() in that the code below allows partial matches
                StringBuilder sb1 = new StringBuilder(1024);
                GetClassName(hWnd, sb1, sb1.Capacity);
                Debug.WriteLine(sb1.ToString());
                if (sb1.ToString().StartsWith(data.Wndclass))
                {
                    RecursiveEnumChildWindows(hWnd, directOnly, ref data);
                    if ((int)data.hWnd > 0)
                    {
                        // Found the wnd, halt enumeration
                        return false;
                    }
                }
                return true;
            }

            private static void RecursiveEnumChildWindows(IntPtr parentHwnd, bool directOnly, ref SearchData data)
            {
                EnumChildWindows(parentHwnd, delegate(IntPtr hwnd, ref SearchData data1)
                {
                    bool add = true;
                    if (directOnly)
                    {
                        add = GetParent(hwnd) == parentHwnd;
                    }

                    StringBuilder sb1 = new StringBuilder(1024);
                    GetClassName(hwnd, sb1, sb1.Capacity);
                    Debug.WriteLine("Child:" + sb1.ToString());

                    if (add)
                    {

                        if (sb1.ToString().StartsWith(data1.ChildWndclass))
                        {
                            sb1 = new StringBuilder(1024);
                            //Window Caption
                            GetWindowText(hwnd, sb1, sb1.Capacity);
                            if (sb1.ToString().Contains(data1.ChildTitle))
                            {
                                data1.hWnd = hwnd;
                                data1.WorkbookTitle = sb1.ToString();
                                return false; // Found the wnd, halt enumeration
                            }
                        }
                    }
                    return true;
                }, ref data);
            }

            private struct SearchData
            {
                // You can put any vars in here...
                public string Wndclass;
                public string ChildWndclass;
                public string ChildTitle;
                public IntPtr hWnd;
                public string WorkbookTitle;
            }
            # region Windows API declarations
            private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, ref SearchData data);

            //private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);

            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, ref SearchData data);

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

            [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
            private static extern IntPtr GetParent(IntPtr hWnd);

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

/////////////////////Work good on Windows 10 64 bit

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么System.Drawing.Image.GetPropertyItem在Windows XP / 2003上的行为与Windows 7相比有所不同 - Why does System.Drawing.Image.GetPropertyItem behave differently on Windows XP / 2003 compared to Windows 7 Windows XP上的Windows API Codepack向后兼容性 - Windows API Codepack Backwards Compatibility on Windows XP 带有 Windows API 代码包的 Windows XP 上的 EntryPointNotFoundException - EntryPointNotFoundException on Windows XP with Windows API Code Pack Metro应用程序可以在Windows XP或Windows 7上运行吗? - Do Metro apps work on Windows XP or Windows 7? EnumWindows不显示Windows 8 Metro中的应用 - EnumWindows doesnt show apps from windows 8 metro Windows XP中的Windows 7样式 - Windows 7 Style in Windows XP Windows XP上的IIS 7托管代码管理API - IIS 7 Managed Code Administration API on Windows XP Windows XP机器上的Windows API代码包功能 - Windows API Code Pack features on windows xp machine MSMQ + C#,接收带有编码字节 [] 正文的消息在 Windows 7 与 Windows XP 上的行为不同 - MSMQ + C#, receiving a message with encoded byte[] body behaves differently on Windows 7 vs. Windows XP 为什么SmtpClient在XP / Vista / Win7上的行为会有所不同 - Why would SmtpClient behave differently on XP/Vista/Win7
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM