C# Windows API EnumWindows和EnumChildWindows函数在Windows XP和7中的行为是否不同
我正在使用2个从c#.NET 4.0导出的Windows API函数 我正在搜索Excel主窗口的子窗口的窗口标题(Excel有一个XLMAIN类的MDI窗口,包含0个、1个或多个Excel 7窗口类的子窗口) 目标是查找是否在excel应用程序的任何实例中打开excel工作簿。我通过查找所有XLMAIN IntPtr(指针)并遍历子对象,直到得到一个带有EXCEL7窗口类的IntPtr,在该类中,我可以读取子窗口标题并确定是否打开了文件 基本上,这在Windows XP上有效,但在Windows 7上不起作用。我没有在Windows Vista中尝试。 发生了什么变化?有人可以调试这个问题,因为我没有Windows7。 谢谢 拉德C# Windows API EnumWindows和EnumChildWindows函数在Windows XP和7中的行为是否不同,c#,windows,windows-7,.net-4.0,windows-xp,C#,Windows,Windows 7,.net 4.0,Windows Xp,我正在使用2个从c#.NET 4.0导出的Windows API函数 我正在搜索Excel主窗口的子窗口的窗口标题(Excel有一个XLMAIN类的MDI窗口,包含0个、1个或多个Excel 7窗口类的子窗口) 目标是查找是否在excel应用程序的任何实例中打开excel工作簿。我通过查找所有XLMAIN IntPtr(指针)并遍历子对象,直到得到一个带有EXCEL7窗口类的IntPtr,在该类中,我可以读取子窗口标题并确定是否打开了文件 基本上,这在Windows XP上有效,但在Window
既然MS Office已经记录了自动化支持,为什么还要使用这样的黑客呢
您可以使用旧版或超旧版。既然MS Office已经记录了自动化支持,为什么还要使用这样的黑客
您可以使用旧版或超旧版。什么“不起作用”?我没有Excel,所以无法为您调试代码。试着打电话给您的医生,说“我的手臂不工作,怎么了?”然后看看是否有答案。我保证,如果没有更多的信息,你不会的。类似地,您转储了一堆代码并说“这不起作用”,希望得到帮助。如果没有关于“不起作用”的详细说明,你将无法理解它。你收到错误信息了吗?Windows有蓝屏吗?Excel是否会弹出一个对话框,上面写着“BZZT!我没告诉你!Nanner Nanner!”?请记住,我们看不到您的屏幕,看不到您的心思,也不知道您没有告诉我们的任何问题。谢谢。:)XP和7都是32位还是64位操作系统?可能这段代码在其他版本的Office上会中断…很抱歉不清楚。ExcelProofFind适用于XP(32位)计算机,适用于Windows 7(64位)计算机。Excel自动化的问题是,我只能获取一个Excel实例,而我的文件可能会在另一个实例中打开。我正准备使用远程调试(因为Windows7机器是一台测试/UAT机器)来调试这个问题。什么“不起作用”?我没有Excel,所以无法为您调试代码。试着打电话给您的医生,说“我的手臂不工作,怎么了?”然后看看是否有答案。我保证,如果没有更多的信息,你不会的。类似地,您转储了一堆代码并说“这不起作用”,希望得到帮助。如果没有关于“不起作用”的详细说明,你将无法理解它。你收到错误信息了吗?Windows有蓝屏吗?Excel是否会弹出一个对话框,上面写着“BZZT!我没告诉你!Nanner Nanner!”?请记住,我们看不到您的屏幕,看不到您的心思,也不知道您没有告诉我们的任何问题。谢谢。:)XP和7都是32位还是64位操作系统?可能这段代码在其他版本的Office上会中断…很抱歉不清楚。ExcelProofFind适用于XP(32位)计算机,适用于Windows 7(64位)计算机。Excel自动化的问题是,我只能获取一个Excel实例,而我的文件可能会在另一个实例中打开。我正准备使用远程调试来调试该问题(因为Windows 7计算机是一台测试/UAT计算机)。Excel automation的问题是,我只能在一个Excel实例中获取,而我的文件可能会在另一个实例中打开。是否有一些类和方法可以帮助我在普通、最小化和最大化视图中查找Excel 2003/2007的所有运行实例及其工作簿的所有标题。@Rad,我还在寻找一种查找所有运行实例的方法;您曾经解决过这个问题吗?Excel automation的问题是,我只能在一个Excel实例中获取,而我的文件可能会在另一个实例中打开。是否有一些类和方法可以帮助我在普通、最小化和最大化视图中查找Excel 2003/2007的所有运行实例及其工作簿的所有标题。@Rad,我还在寻找一种查找所有运行实例的方法;您是否曾经解决过此问题?虽然此代码可以回答此问题,但提供有关如何和/或为什么解决此问题的其他上下文将提高答案的长期价值。虽然此代码可以回答此问题,提供关于如何和/或为什么解决问题的附加上下文将提高答案的长期价值。
private const string WINDOW_EXCEL7 = "XLMAIN";
private const string CHILDWINDOW_XLMAIN = "EXCEL7";
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
}
}
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