GetWindowText挂在Windows 10上
TL; DR:GetWindowText win32 api在Windows 10上更改行为?GetWindowText挂在Windows 10上
我有一些代码循环浏览桌面上的所有窗口,以找到标题包含一些文本的窗口。
当此代码通过类“URL Moniker通知窗口”命名为“”的窗口时,它挂在GetWindowText上。
GetWindowText正试图发送消息,我的猜测是WM_GETTEXT。
此窗口是exe文件的一部分“SearchUI.exe”,该进程被暂停,无法处理消息。
当阅读:https://blogs.msdn.microsoft.com/oldnewthing/20030821-00/?p=42833/ 根据规则2,这应该不会发生。
此代码多年来一直运行良好。 (win 7,8,8.1)
那么GetWindowText在Windows 10中的变化行为呢?
更新: 有问题的代码。
public static int HwndGet(string partialTitle, string klassenavn)
{
partialTitle = partialTitle ?? "";
var cTitleTemp = new StringBuilder(255);
var hWndTemp = FindWindowEx((IntPtr)0, (IntPtr)0, null, null);
var nypartialTitle = partialTitle.ToUpper();
while (hWndTemp != (IntPtr)0)
{
GetWindowText(hWndTemp, cTitleTemp, cTitleTemp.Capacity);
string sTitleTemp = cTitleTemp.ToString();
sTitleTemp = sTitleTemp.ToUpper();
if (sTitleTemp.StartsWith(nypartialTitle, StringComparison.CurrentCultureIgnoreCase))
{
var className = new StringBuilder(255);
GetClassName(hWndTemp, className, 255);
//sTitleTemp: " + sTitleTemp + " ClassName: " + ClassName);
if (className.ToString().StartsWith(klassenavn, StringComparison.CurrentCultureIgnoreCase))
{
return (int)hWndTemp;
}
}
hWndTemp = GetWindow(hWndTemp, GwHwndnext);
}
return 0; // does not find the window
}
堆栈跟踪:
您所使用的代码是不 “安全”。不能保证在调用FindWindowsEx
和GetWindow(GwHwndnext)
之间窗口的顺序不会改变。由于这个原因,另一个API是EnumWindows
,它是“安全的”。你可以尝试一下。
这里有一个示例程序(基于发现的一个here)。
public static class WndSearcher
{
public static IntPtr SearchForWindow(string wndclass, string title)
{
var sd = new SearchData { Wndclass = wndclass, Title = title };
EnumWindows(sd.EnumWindowsProc, IntPtr.Zero);
return sd.hWndFound;
}
private class SearchData
{
// You can put any dicks or Doms in here...
public string Wndclass;
public string Title;
public IntPtr hWndFound;
public bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam)
{
// Check classname and title
var sb = new StringBuilder(1024);
int res = GetClassName(hWnd, sb, sb.Capacity);
if (res == 0)
{
throw new Win32Exception();
}
if (sb.ToString().StartsWith(Wndclass, StringComparison.CurrentCultureIgnoreCase))
{
sb.Clear();
res = GetWindowText(hWnd, sb, sb.Capacity);
if (res == 0)
{
int error = Marshal.GetLastWin32Error();
if (error != 0)
{
throw new Win32Exception(error);
}
}
if (sb.ToString().StartsWith(Title, StringComparison.CurrentCultureIgnoreCase))
{
hWndFound = hWnd;
// Found the wnd, halt enumeration
return false;
}
}
return true;
}
}
[return: MarshalAs(UnmanagedType.Bool)]
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
}
,然后使用它像
IntPtr ptr = WndSearcher.SearchForWindow("classname", "windowname");
不错的代码,我的解决方案也是调用GetClassName第一,所以我绝不会碰到暂停的进程,但这不是我的问题的答案。 –
GetWindowText可以返回0,如果没有赢的标题dow,所以这段代码总是会抛出一个异常。 替换** if(res == 0)** GetWindowText后 ** var errorNum = Marshal.GetLastWin32Error(); if(res == 0 && errorNum!= 0)** –
@NickolaiNielsen对......我用一种不同的方式完成了它。 – xanatos
似乎更可能有在你的代码 –
代码加入,也许你可以找到缺陷的缺陷。 –
FindWindowEx,GetWindowText,GetClassName和GetWindow(以及其他pinvoke函数,如果我错过了它们)...您应该发布您的定义 – xanatos