【问题标题】:Catch application's pop-up message box捕获应用程序的弹出消息框
【发布时间】:2014-07-11 09:32:22
【问题描述】:

我必须使用 VB.Net 自动执行 Windows 应用程序的重复性任务(无 API)。

我所做的是模拟通常由用户完成的击键。 我正在使用System.Threading,并使用新进程启动应用程序。

我的问题是,这个应用程序在完成任务时会弹出一个消息框,并且这个消息框肯定会禁用主应用程序窗口,所以我需要知道这个消息框何时显示以模拟 ENTER 击键并继续下一个任务。

这是我的代码示例:

Imports System.Threading

Public Class Form1
    Dim a As New Process

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        a.StartInfo.FileName = "C:\Program Files (x86)\CE\CE.exe"
        a.Start()
        AppActivate(a.Id)

        For i = 1 To CInt(txt.Text)
            DoTask()
        Next
    End Sub

    Private Sub DoTask()
        Thread.Sleep(1000)

        SendKeys.SendWait("^(N)")
        Thread.Sleep(500)
        SendKeys.SendWait("{ENTER}")
        Thread.Sleep(500)
        SendKeys.SendWait("new check")
        Thread.Sleep(500)
        SendKeys.SendWait("{ENTER}")

        Do While True
            'Here I want to wait until a message box pops up by the application
            'If message box displayed then exit do
        Loop

        SendKeys.SendWait("{ENTER}")
    End Sub
End Class

请帮我解决这个问题。 谢谢

【问题讨论】:

  • 为什么这个标签是 C#? C# 解决方案也可以接受吗?
  • 是的,这是可以接受的,这就是原因。

标签: vb.net process popup automation


【解决方案1】:

我个人将 AutoIt 用于此类任务 - 有一个 WinWaitActive 函数,它会等待具有指定标题或类名的窗口打开并处于活动状态,然后您可以向它发送简单的击键。

https://www.autoitscript.com/autoit3/docs/functions/WinWaitActive.htm

在 VB 中,我认为您必须执行以下操作:等待具有指定标题或类名的窗口可见并被激活。

Determine Whether Program is the Active Window in .NET

如果您需要坚持使用 VB,您可以导入和使用 AutoIt DLL:

Running AutoIt3 Scripts in VB 2010

AutoIt 编辑器中有一个不错的工具,可让您检查窗口及其子控件并在脚本中使用类名。例如,我编写的代码等到带有结果集的 ALV 网格显示在 SAP 窗口中:

Func _WaitForALVGrid()
    Sleep(5000)
    _WinWaitActivate($windowName,"")
    Local $count = 0
    Do
        Sleep(5000) 
        $count = $count + 1
        $Text=ControlGetText("[CLASS:SAP_FRONTEND_SESSION]","","[CLASS:Afx:63DE0000:8:00010003:00000010:00000000]")
        if StringLeft($Text, 6) = "Nebyla" Then Return False 
        if $count>360 Then Return False
    Until StringInStr(WinGetClassList($windowName), "SapALVGrid")>0
    _WinWaitActivate($windowName,"")
    Sleep(5000)
    Return True
EndFunc

编辑:

VB.NET 中还有一种方法不使用 AutoIT——类似于 WinWaitActivate:

http://forums.codeguru.com/showthread.php?460402-C-General-How-do-I-activate-an-external-Window

Class Program
    <DllImportAttribute("User32.dll")> _
    Private Shared Function FindWindow(ClassName As [String], WindowName As [String]) As Integer
    End Function
    <DllImportAttribute("User32.dll")> _
    Private Shared Function SetForegroundWindow(hWnd As Integer) As IntPtr
    End Function
    Private Shared Sub Main(args As String())
        '**************************** CODE YOU SEEK?
        'Find the window, using the CORRECT Window Title, for example, Notepad            
        Dim hWnd As Integer = 0
        While hWnd = 0
            Thread.Sleep(1000)
            hWnd = FindWindow(Nothing, "Untitled - Notepad") 
        End While
        'If found activate it
        SetForegroundWindow(hWnd)
        '**************************** CODE YOU SEEK?
    End Sub
End Class

这里是另一个很好的例子:

close a message box from another program using c#

【讨论】:

  • 不客气。这种类型的编程是每个合理的编码人员都试图避免的,但有时没有其他办法——公司政策、封闭源代码等。
  • 你是对的。而且从我的测试来看,我仍然对性能有些担忧,我的程序似乎不可能在不担心错误的情况下运行,除非在执行过程中没有用户对 pc 进行任何操作!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-29
相关资源
最近更新 更多