从已经运行的CMD窗口捕获文本(VB.NET)

时间:2018-04-01 19:44:42

标签: vb.net cmd

有一个应用程序在这台计算机上运行很多24/7。它在命令提示符Window中运行。我希望能够捕获窗口中当前显示的所有文本。

应用程序已经运行(并且由于无关原因,无法从VB中启动),因此我不能只重定向进程的输出以保存文本。

我目前捕获文本的方法是使用以下代码:

SendKeys.SendWait("^(a)")
SendKeys.SendWait("^(a)")
SendKeys.SendWait("{enter}")

Dim CmdText As String = Clipboard.GetText
Clipboard.Clear()

上面的代码向窗口发送一个select all命令(它发送两次,否则不捕获整个windows文本)。然后按Enter键将其加载到剪贴板中。然后我将剪贴板内容保存到变量中。它运作良好,但主要问题是它需要窗口聚焦。

如果目前没有焦点,是否有从CMD窗口捕获文本?

编辑:我想我已经接近使用sendmessage / postmessage找到解决方法。这是当前的代码:

Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As Long

Private Const WM_CHAR As Long = &H102
Private Const VK_CONTROL = &H11
Private Const VK_RETURN = &HD

Public Function GetWindowHandle(ByVal processName As String) As IntPtr
    processName = System.IO.Path.GetFileNameWithoutExtension(processName)
    Dim p() = Process.GetProcessesByName(processName)
    Return If(p.Length > 0, p(0).MainWindowHandle, IntPtr.Zero)
End Function

Private Sub GetText()

Dim h As Long = GetWindowHandle("programname.exe")
SendMessage(h, WM_CHAR, 1, 0) 'suppose to simulate Ctrl + A
SendMessage(h, WM_CHAR, 1, 0) 'suppose to simulate Ctrl + A

PostMessage(h, WM_KEYDOWN, VK_RETURN, 0) 'sends enter key to load text into clipboard

End Sub

问题是,它不是将Ctrl + A发送到命令窗口,而是发送文本^ A.有什么想法吗?

1 个答案:

答案 0 :(得分:2)

我写了一个名为InputHelper的图书馆,可以在这里派上用场。它包括执行输入模拟的不同方法,一种是将其发送到特定窗口。

  

从GitHub下载:
  https://github.com/Visual-Vincent/InputHelper/releases

它的wiki遗憾地远未完成,但是库本身包含描述其中每个方法的XML文档(当您在弹出的成员列表中选择方法或成员时,Visual Studio的IntelliSense会自动显示该文档在输入时。)

图书馆目前包含四个主要类别:

  • InputHelper.Hooks :用于捕获系统范围(有时称为全局)鼠标和键盘输入的类。可用于制作热键。

  • InputHelper.Keyboard :模拟真实键盘输入/击键的方法。

  • InputHelper.Mouse :模拟真实鼠标输入的方法。

  • InputHelper.WindowMessages :用于在更虚拟级别模拟鼠标和键盘输入的方法,例如针对特定窗口。这利用了窗口消息(因此SendMessage()PostMessage())。

提到的最后一个是您感兴趣的。使用InputHelper.WindowMessages.SendKeyPress(),您可以将特定的击键发送到您选择的窗口,如果省略,则可以发送当前活动的窗口。

这样的事情应该有效:

Dim hWnd As IntPtr = GetWindowHandle("programname.exe")

'Send CTRL + A twice.
InputHelper.WindowMessages.SendKeyPress(hWnd, Keys.Control Or Keys.A)
InputHelper.WindowMessages.SendKeyPress(hWnd, Keys.Control Or Keys.A)

'Send ENTER.
InputHelper.WindowMessages.SendKeyPress(hWnd, Keys.Enter)

请注意,执行Keys.Control Or Keys.A会发送组合 CTRL + A ,但在使用Keys.ControlKeys.Shift时,这只会 Keys.Alt(或它们的组合)。使用任何其他密钥(例如Keys.A Or Keys.BKeys.ControlKey Or Keys.A)将无效。