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 
} 

堆栈跟踪:

Stack trace

+1

似乎更可能有在你的代码 –

+1

代码加入,也许你可以找到缺陷的缺陷。 –

+0

FindWindowEx,GetWindowText,GetClassName和GetWindow(以及其他pinvoke函数,如果我错过了它们)...您应该发布您的定义 – xanatos

您所使用的代码是不 “安全”。不能保证在调用FindWindowsExGetWindow(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"); 
+0

不错的代码,我的解决方案也是调用GetClassName第一,所以我绝不会碰到暂停的进程,但这不是我的问题的答案。 –

+0

GetWindowText可以返回0,如果没有赢的标题dow,所以这段代码总是会抛出一个异常。 替换** if(res == 0)** GetWindowText后 ** var errorNum = Marshal.GetLastWin32Error(); if(res == 0 && errorNum!= 0)** –

+0

@NickolaiNielsen对......我用一种不同的方式完成了它。 – xanatos