Capture Text from CMD Window That Is Already Runni

2019-02-28 00:57发布

问题:

There is an application that runs pretty much 24/7 on this computer. It is run inside a command prompt Window. I would like to be able to capture all of the text currently displayed in the window.

The application is already running (and for unrelated reasons, can't be launched from within VB), so I can't just redirect the output of the process to save the text.

My current method for capturing the text is with the following code:

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

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

The above code sends a select all command to the window (it sends it twice, otherwise the entire windows text isn't captured). It then hits the enter key to load it into the clipboard. I then save the clipboard contents to a variable. It works well, but the major problem is that it requires the window to be in focus.

Is there anyway to capture the text from the CMD window if it is currently out of focus?

Edit: I think I'm getting close to finding a workaround using sendmessage/postmessage. Here is the current code:

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

The problem is that instead of sending Ctrl + A to the command window, it just sends the text ^A. Any ideas?

回答1:

I've written a library called InputHelper which could come in handy here. It includes different methods of performing input simulation, one being sending it to a specific window.

Download from GitHub:
https://github.com/Visual-Vincent/InputHelper/releases

Its wiki is sadly far from complete, but the library itself includes XML documentation describing every method inside it (which is automatically shown by Visual Studio's IntelliSense when you select a method or member in the members list that pops up while typing).

The library currently consists of four main categories:

  • InputHelper.Hooks: Classes for capturing system-wide (some times referred to as global) mouse and keyboard input. Can be used to make for instance hot keys.

  • InputHelper.Keyboard: Methods for simulating real keyboard input/key strokes.

  • InputHelper.Mouse: Methods for simulating real mouse input.

  • InputHelper.WindowMessages: Methods for simulating mouse and keyboard input at a more virtual level, for instance targeting specific windows. This utilizes window messages (thus SendMessage() and PostMessage()).

The last one mentioned would be the one of your interest. Using InputHelper.WindowMessages.SendKeyPress() you can send a specific key stroke to a window of your choice or, if omitted, the currently active window.

Something like this should work:

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)

Note that doing Keys.Control Or Keys.A sends the combination CTRL + A, however this works only when using either Keys.Control, Keys.Shift or Keys.Alt (or a combination of them). Using any other keys (for instance Keys.A Or Keys.B or Keys.ControlKey Or Keys.A) won't work.



标签: vb.net cmd