本文介绍了从其他程序中捕获MessageBox的内容文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 大家好, 经过长时间的研究,我想向你提交我的问题... 我想从其他程序中读取MessageBox(或弹出窗口)窗口的文本,但问题是,这个MessageBox不是他主程序的子项,所以我无法访问它... 这是我尝试没有成功的... hwndChild = FindWindowEx(hwnd, IntPtr .Zero, null , null ); while (hwndChild!= IntPtr .Zero) { GetWindowText(hwndChild,bld, 255 ); Console.WriteLine(bld.ToString()); // SendMessage(hwndChild,WM_SYSCOMMAND,SC_CLOSE,0); hwndChild = FindWindowEx(hwnd,hwndChild, null , null ); } hwndChild = FindWindowEx(hwnd, IntPtr .Zero, null , null ); while (hwndChild!= IntPtr .Zero) { IntPtr lgTexte = SendMessage(hwndChild,WM_GETTEXTLENGTH, 0 , 0 ); #if STRING string sbTitre = new string (' 0' ,lgTexte); #else StringBuilder sbTitre = new StringBuilder(( INT )lgTexte); #endif GetControlText(( int )hwndChild,WM_GETTEXT,( int )lgTexte + 1 ,sbTitre); Console.WriteLine( hwnd = {0} => {1}, hwndChild,sbTitre); hwndChild = FindWindowEx(hwnd,hwndChild, null , null ); } 解决方案 让我告诉你,你的生意很糟糕。应用程序是彼此隔离的,并不是为了做这样的技巧。从技术上讲,它很可能,但为什么这样做呢?结果不可靠;应用程序实现中的微小变化将毁掉你棘手的工作。结果总是很难看。 如果你只是为了一些调查,我能理解它。 没有窗口是儿童或程序的东西。您可以从流程开始查找所有内容。让我们假设您从进程列表中找到了一个进程(不可靠,因为您只能通过已知名称识别它,但没有任何东西可以保证您的名称是唯一的)或者从获得它System.Diagnostics.Process.Start : http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx [ ^ ](参见 GetProcesses ), http://msdn.microsoft.com/en-us/library/e8zac0ca.aspx [ ^ ]。 首先,您可以找到主窗口(如果可用)。你应该明白这个调用会抛出异常: http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle.aspx [ ^ ]。 现在,棘手的部分:该过程显示一个模态窗口。你需要使用P / Invoke这样一个棘手的方法,如 GetLastActivePopup :http://msdn.microsoft.com/en-us/library/windows/desktop/ms633507%28v=vs。 85%29.aspx [ ^ ]。 我假设对话框的父级是应用程序的主窗口;你应该使用它的句柄作为参数。这涵盖了大多数情况,但父窗口可以是其他窗口。在这种情况下,您需要从main开始遍历应用程序窗口的层次结构: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633514%28v=vs.85%29.aspx [ ^ ], http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515%28v=vs.85%29.aspx [ ^ ](使用 GW_CHILD )。 -SA 你好,谢谢你的回答 我这样做是因为我想监督一个程序,它不会返回任何错误代码,只显示一个messageBox(它是一个API的设计)。我想收到此错误消息,因为我想报告它(例如通过电子邮件) 我可以自动点击此消息框上的确定,但我不会知道错误... 感谢您的提示我会看看 AP 确定。有一种方法可以获得你期望得到的东西。尝试这种方法对我有用。 1.首先使用类名或标题查找窗口(我在测试中使用了messagebox标题) 2.对于查找窗口传递,将ParentHandle和ChildHandle设置为Null(IntPtr.Zero),因此它使用desktopwindow作为父窗口并搜索所有打开的窗口。 3.获取windowHandle from step 2枚举其子窗口 4.使用GetWindowTextLength和GetWindowText的组合来获取文本。 示例代码 // 包含这些dll导入作为您的第一步类和调用如下所述 [DllImport( user32.dll ,CharSet = CharSet.Unicode)] 静态 extern IntPtr FindWindowEx ( IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle); [DllImport( user32,CharSet = CharSet.Auto,SetLastError = true )] 内部 静态 extern int GetWindowText( IntPtr hWnd ,[Out,MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount); [DllImport( user32.dll,CharSet = CharSet.Auto ,ExactSpelling = true )] public static extern bool IsChild( IntPtr hWndParent, IntPtr hwnd); private delegate bool EnumWindowsProc( IntPtr hWnd, IntPtr lParam); [DllImport( user32.dll)] [返回:MarshalAs(UnmanagedType.Bool)] 静态 extern bool EnumChildWindows( IntPtr hwndParent,EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport( user32.dll,SetLastError = true ,CharSet = CharSet.Auto)] static extern int GetWindowTextLength( IntPtr hWnd); 方法定义 public static List< intptr> GetChildWindows(IntPtr parent) { List< intptr> result = new List< intptr>(); GCHandle listHandle = GCHandle.Alloc(结果); try { EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow); EnumChildWindows(parent,childProc,GCHandle.ToIntPtr(listHandle)); } 最后 { if(listHandle.IsAllocated) listHandle.Free(); } 返回结果; } private static bool EnumWindow(IntPtr句柄,IntPtr指针) { GCHandle gch = GCHandle.FromIntPtr(指针); List< intptr> list = gch.Target as List< intptr> ;; if(list == null) {抛出新的InvalidCastException(GCHandle Target无法转换为List< intptr>;); } list.Add(handle); //您可以修改此项以检查是否要取消操作,然后在此处返回null return true; } private void button1_Click(object sender,EventArgs e) { IntPtr windowHandle = FindWindowEx(IntPtr.Zero,IntPtr.Zero,null,Save as ); //我的留言框有标题另存为你可以根据你的要求改变这个 List< intptr> childs = GetChildWindows(windowHandle); foreach(孩子们的IntPtr孩子) { bool isChild = IsChild(windowHandle,child); int length = GetWindowTextLength(child); StringBuilder bb = new StringBuilder(length + 1); GetWindowText(child,bb,bb.Capacity); } }< / intptr>< / intptr>< / intptr>< / intptr>< / intptr>< / intptr>< / intptr> Hi everybody,After long researches I want to submit you my problem...I want to read the text of a MessageBox (or pop-up) window from an other program but the thing is, this MessageBox is not a child of his main program so i can''t access to it...this is what I tried without success...hwndChild = FindWindowEx(hwnd, IntPtr.Zero, null, null); while (hwndChild != IntPtr.Zero) { GetWindowText(hwndChild, bld, 255); Console.WriteLine(bld.ToString()); //SendMessage(hwndChild, WM_SYSCOMMAND, SC_CLOSE, 0); hwndChild = FindWindowEx(hwnd, hwndChild, null, null); }ORhwndChild = FindWindowEx(hwnd, IntPtr.Zero, null, null); while (hwndChild != IntPtr.Zero) { IntPtr lgTexte = SendMessage(hwndChild, WM_GETTEXTLENGTH, 0, 0); #if STRING string sbTitre = new string('0',lgTexte); #else StringBuilder sbTitre = new StringBuilder((int)lgTexte); #endif GetControlText((int)hwndChild, WM_GETTEXT, (int)lgTexte + 1, sbTitre); Console.WriteLine("hwnd={0} => {1}", hwndChild, sbTitre); hwndChild = FindWindowEx(hwnd, hwndChild, null, null); } 解决方案 Let me tell you that you are doing a bad business. Applications are isolated one from another and are not designed to do such tricks. Technically, its quite possible, but why doing it? The results cannot be reliable; a tiny change in the application implementation will ruin your tricky work. And the results will always be ugly.If you doing it all only for some investigation, I can understand it.There is no such thing as a window which is a child or a "program". You can find everything starting from the process. Let''s assume that you found a process from a list of processes (unreliable, because you can only identify it by known name, but nothing can guarantee you that this name is unique) or got it from the System.Diagnostics.Process.Start:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx[^] (see GetProcesses),http://msdn.microsoft.com/en-us/library/e8zac0ca.aspx[^].First, you can find main window, if it is available. You should understand that this call can throw an exception:http://msdn.microsoft.com/en-us/library/system.diagnostics.process.mainwindowhandle.aspx[^].Now, the tricky part: the process shows a modal window. You need to use P/Invoke for such a tricky method asGetLastActivePopup: http://msdn.microsoft.com/en-us/library/windows/desktop/ms633507%28v=vs.85%29.aspx[^].I assumed that the dialog''s parent is the main window of the application; you should use its handle as a parameter. This covers most cases, but the parent window can be some other one. In this case, you will need to walk through the hierarchy of the application windows starting from main:http://msdn.microsoft.com/en-us/library/windows/desktop/ms633514%28v=vs.85%29.aspx[^],http://msdn.microsoft.com/en-us/library/windows/desktop/ms633515%28v=vs.85%29.aspx[^] (use GW_CHILD).—SAHi, thanks for your answerWell i''m doing this because I want to "supervise" a "program" which doesn''t return any error codes, and only display a messageBox (it was desgin to be an API). I want to get this error message cause I want to report it (e.g. by email)I can automatically click "Ok" on this messageBox, but I will not be aware about the error...Thank you for your tips I will take a lookAPOk. there exists a way to get what you expected to get. try this method it works for me.1. First Find your window using class name or title (i used messagebox title in my test)2. For Finding your window pass set ParentHandle and ChildHandle both to Null(IntPtr.Zero) so it uses desktopwindow as the parent window and search through all the opened windows.3. on getting the windowHandle from step 2 Enumerate through its child windows 4. Use the combination of GetWindowTextLength and GetWindowText to get your text.sample code//include these dll imports as first step in your class and call as explained below[DllImport("user32.dll", CharSet = CharSet.Unicode)]static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);[DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]public static extern bool IsChild(IntPtr hWndParent, IntPtr hwnd);private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);[DllImport("user32.dll")][return: MarshalAs(UnmanagedType.Bool)]static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]static extern int GetWindowTextLength(IntPtr hWnd);Method definitionspublic static List<intptr> GetChildWindows(IntPtr parent){ List<intptr> result = new List<intptr>(); GCHandle listHandle = GCHandle.Alloc(result); try { EnumWindowsProc childProc = new EnumWindowsProc(EnumWindow); EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle)); } finally { if (listHandle.IsAllocated) listHandle.Free(); } return result;}private static bool EnumWindow(IntPtr handle, IntPtr pointer){ GCHandle gch = GCHandle.FromIntPtr(pointer); List<intptr> list = gch.Target as List<intptr>; if (list == null) { throw new InvalidCastException("GCHandle Target could not be cast as List<intptr>;"); } list.Add(handle); // You can modify this to check to see if you want to cancel the operation, then return a null here return true;}private void button1_Click(object sender, EventArgs e){ IntPtr windowHandle = FindWindowEx(IntPtr.Zero, IntPtr.Zero, null, "Save As"); // My Message box has caption "Save As" you may change this as per your requirement List<intptr> childs = GetChildWindows(windowHandle); foreach (IntPtr child in childs) { bool isChild = IsChild(windowHandle, child); int length = GetWindowTextLength(child); StringBuilder bb = new StringBuilder(length+1); GetWindowText(child, bb, bb.Capacity); }}</intptr></intptr></intptr></intptr></intptr></intptr></intptr> 这篇关于从其他程序中捕获MessageBox的内容文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
10-29 15:30