如何从.net中的win32弹出窗口中检测并获取文本

时间:2012-07-02 21:09:48

标签: vb.net api

我已经查看了几个尝试在stackoverflow上列出的示例,但是我没有找到任何列出如何为.NET编码执行此操作的示例。此外,我需要它来检测弹出窗口,一旦找到弹出窗口,然后拉出窗口的标题,弹出窗口中的文本。

我尝试使用帖子: how-can-i-change-text-on-a-win32-window

但我没有运气试图找到如何“获取文本”只是如何查看弹出窗口是否存在。我试图从中获取文本的窗口是一个标准的Windows错误窗口(#32770)a.k.a WIN32关键弹出窗口(一个红色X)。我知道错误窗口的标题总是“TLP2011”

我只需要能够阅读标题,文本,然后单击错误按钮上的“确定”。

原因?有一个我运行IT的软件,用于减少入站呼叫成本我希望编写一个程序,在弹出时检测错误,然后一旦检测到它就关闭错误窗口并告诉用户错误将自动修复。 (我的新程序必须能够从错误窗口中读取文本,以确定如何自动修复错误,以便不再显示此错误)

----------编辑显示最新发现------------

感谢GX发布以下链接How can I get functionality similar to Spy++ in my C# app?

现在我确定我需要以下内容:

Dim pProcess() As Process = Process.GetProcessesByName("TLP2011")

    For Each p As Process In pProcess
        For Each threadInfo As ProcessThread In p.Threads

            ' uncomment to dump thread handles
            'Console.WriteLine("\tthread {0:x}", threadInfo.Id);
            Dim windows As IntPtr() = GetWindowHandlesForThread(threadInfo.Id)
            If windows IsNot Nothing AndAlso windows.Length > 0 Then
                For Each hWnd As IntPtr In windows
                    Console.WriteLine(vbTab & "window {0:x} text:{1} caption:{2}", hWnd.ToInt32(), GetText(hWnd), GetEditText(hWnd))
                Next
            End If
        Next
    Next

现在列出实际程序本身的所有内容。每一段文字和一切。任何人都知道只需单击弹出框的技巧吗?

以下是显示内容的示例

window 3d21aa text:Select Package caption:
window 551176 text: caption:
window e8147c text:Do Not Auto Show  caption:Do Not Auto Show 
window 8e21c6 text:&Select All caption:&Select All
window 2300e10 text:&Help caption:&Help
window 762164 text:Cancel caption:Cancel
window 330f0e text:OK caption:OK
window e8147c text:Do Not Auto Show  caption:Do Not Auto Show 
window 8e21c6 text:&Select All caption:&Select All
window 2300e10 text:&Help caption:&Help
window 762164 text:Cancel caption:Cancel
window 330f0e text:OK caption:OK
window 10f20a6 text: caption:
window 5f122ce text: caption:
window 1824e2 text: caption:
window 1824e2 text: caption:
window 5f122ce text: caption:
window 1824e2 text: caption:
window 1824e2 text: caption:
window 6e1be4 text: caption:
window 342162 text: caption:
window 1c1b92 text: caption:
window 65105a text: caption:Admin
window 291f72 text: caption:
window 375104e text: caption:
window 375104e text: caption:
window 1c1b92 text: caption:
window 65105a text: caption:Admin
window 291f72 text: caption:
window 375104e text: caption:
window 375104e text: caption:
window 242308 text:Form Filter caption:
window 9ee294e text: caption:
window 8ff0f54 text: caption:All Status
window 468273c text: caption:
window 1d110c text: caption:
window 1d110c text: caption:
window 8ff0f54 text: caption:All Status
window 468273c text: caption:
window 1d110c text: caption:
window 1d110c text: caption:
window b90bea text:cbEngine caption:
window 5b17b0 text: caption:
window ee24c6 text: caption:
window ee24c6 text: caption:
window fc1ae0 text: caption:
window 141cfc text:TLP2011 caption:
window d51928 text:OK caption:OK
window 2c1223c text: caption:
window 100f08 text:Access violation at address 6CABC667 in module 'tlpcore.dll'. Write of address F8FFFF86. caption:Access violation at address 6CABC667 in module 'tlpcore.dll'. Write of address F8FFFF86.
window b2a214e text: caption:

任何人都知道更好的方法来尝试找到错误框吗?我不认为搜索“TLP2011”然后使用接下来的3行来尝试确定msgbox文本是一个非常“可靠”的方法。有人知道怎么单独出来吗?

----添加了更多想法----

通过所有不同的线程(每10秒钟)对此进行一次检查,似乎会给系统带来巨大的损失。这真的是最合乎逻辑的做法吗?

1 个答案:

答案 0 :(得分:0)

加埃塔诺的回答是正确的

static void Main(string[] args)
{
    foreach (Process procesInfo in Process.GetProcesses())
    {
        Console.WriteLine("process {0} {1:x}", procesInfo.ProcessName, procesInfo.Id);
        foreach (ProcessThread threadInfo in procesInfo.Threads)
        {
            // uncomment to dump thread handles
            //Console.WriteLine("\tthread {0:x}", threadInfo.Id);
            IntPtr[] windows = GetWindowHandlesForThread(threadInfo.Id);
            if (windows != null && windows.Length > 0)
                foreach (IntPtr hWnd in windows)
                    Console.WriteLine("\twindow {0:x} text:{1} caption:{2}",
                        hWnd.ToInt32(), GetText(hWnd), GetEditText(hWnd));
        }
    }
    Console.ReadLine();
}

private static IntPtr[] GetWindowHandlesForThread(int threadHandle)
{
    _results.Clear();
    EnumWindows(WindowEnum, threadHandle);
    return _results.ToArray();
}

// enum windows

private delegate int EnumWindowsProc(IntPtr hwnd, int lParam);

[DllImport("user32.Dll")]
private static extern int EnumWindows(EnumWindowsProc x, int y);
[DllImport("user32")]
private static extern bool EnumChildWindows(IntPtr window, EnumWindowsProc callback, int lParam);
[DllImport("user32.dll")]
public static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

private static List<IntPtr> _results = new List<IntPtr>();

private static int WindowEnum(IntPtr hWnd, int lParam)
{
    int processID = 0;
    int threadID = GetWindowThreadProcessId(hWnd, out processID);
    if (threadID == lParam)
    {
        _results.Add(hWnd);
        EnumChildWindows(hWnd, WindowEnum, threadID);
    }
    return 1;
}

// get window text

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

private static string GetText(IntPtr hWnd)
{
    int length = GetWindowTextLength(hWnd);
    StringBuilder sb = new StringBuilder(length + 1);
    GetWindowText(hWnd, sb, sb.Capacity);
    return sb.ToString();
}

// get richedit text 

public const int GWL_ID = -12;
public const int WM_GETTEXT = 0x000D;

[DllImport("User32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int index);
[DllImport("User32.dll")]
public static extern IntPtr SendDlgItemMessage(IntPtr hWnd, int IDDlgItem, int uMsg, int nMaxCount, StringBuilder lpString);
[DllImport("User32.dll")]
public static extern IntPtr GetParent(IntPtr hWnd);

private static StringBuilder GetEditText(IntPtr hWnd)
{
    Int32 dwID = GetWindowLong(hWnd, GWL_ID);
    IntPtr hWndParent = GetParent(hWnd);
    StringBuilder title = new StringBuilder(128);
    SendDlgItemMessage(hWndParent, dwID, WM_GETTEXT, 128, title);
    return title;
}