HowTo: Capture Text Output (Redirect StdIO) 
Author Message
 HowTo: Capture Text Output (Redirect StdIO)

Dear All

Have seen several threads recently on how to capture the text output from
console apps such as ping, tracert etc. The only solutions ever given
involve piping the output to a text file, and then reading the text file
(works with limitations, but can be messy). I have included some source that
I have written below, which when pasted into a .bas module will allow you to
redirect the Standard Input/Output of an application. The functions will
work with console and windows apps, but the examples under Sub Main(), only
cater for console apps. If you wish to run the exsamples, start a new vb
project, add a module and paste in the code. Then make sure the Startup
object under project properties is set to 'Sub Main' and the code should
run. The code should work for VB4-32 and above.

Any comments/suggestions welcome.

Wayne Cornish

' ---------- Start of Code ----------
Option Explicit

Private Const NORMAL_PRIORITY_CLASS = &H20
Private Const REALTIME_PRIORITY_CLASS = &H100
Private Const HIGH_PRIORITY_CLASS = &H80
Private Const IDLE_PRIORITY_CLASS = &H40

Private Const STARTF_FORCEOFFFEEDBACK = &H80
Private Const STARTF_FORCEONFEEDBACK = &H40
Private Const STARTF_RUNFULLSCREEN = &H20        '  ignored for non-x86
platforms
Private Const STARTF_USECOUNTCHARS = &H8
Private Const STARTF_USEFILLATTRIBUTE = &H10
Private Const STARTF_USEPOSITION = &H4
Private Const STARTF_USESHOWWINDOW = &H1
Private Const STARTF_USESIZE = &H2
Private Const STARTF_USESTDHANDLES = &H100

Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As Long
    lpDesktop As Long
    lpTitle As Long
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Public Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Public Type PIPE_INFORMATION
    hStdInRead As Long
    hStdInWrite As Long
    hStdOutRead As Long
    hStdOutWrite As Long
End Type

Private Declare Function CreatePipe Lib "kernel32" _
    (phReadPipe As Long, phWritePipe As Long, _
    lpPipeAttributes As Any, ByVal nSize As Long) As Long

Private Declare Function CreateProcess Lib "kernel32" _
    Alias "CreateProcessA" (ByVal lpApplicationName As Long, _
    ByVal lpCommandLine As String, lpProcessAttributes As Any, _
    lpThreadAttributes As Any, ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, lpStartupInfo As Any, _
    lpProcessInformation As Any) As Long

Private Declare Function ReadFile Lib "kernel32" _
    (ByVal hFile As Long, ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToRead As Long, lpNumberOfbytes_read As Long, _
    ByVal lpOverlapped As Any) As Long

Private Declare Function WriteFile Lib "kernel32" _
    (ByVal hFile As Long, ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToWrite As Long, _
    lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long

Public Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, _
     ByVal dwMilliseconds As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Public Function ShellPipeApp(pathname As String, _
    procInfo As PROCESS_INFORMATION, _
    pipeInfo As PIPE_INFORMATION) As Long

Dim securityA As SECURITY_ATTRIBUTES
Dim procAttr As STARTUPINFO

' set return to fail
ShellPipeApp = False

' set security attributes
securityA.nLength = Len(securityA)
securityA.bInheritHandle = 1&
securityA.lpSecurityDescriptor = 0&

' create stdIn pipe
If CreatePipe(pipeInfo.hStdInRead, pipeInfo.hStdInWrite, _
securityA, 0) = 0 Then Exit Function

' create stdOut pipe
If CreatePipe(pipeInfo.hStdOutRead, pipeInfo.hStdOutWrite, _
securityA, 0) = 0 Then
    'error checking required
    CloseHandle pipeInfo.hStdInRead
    CloseHandle pipeInfo.hStdInWrite
    Exit Function
End If

' set process attributes
procAttr.cb = Len(procAttr)
procAttr.dwFlags = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW
procAttr.hStdInput = pipeInfo.hStdInRead
procAttr.hStdOutput = pipeInfo.hStdOutWrite

' start app
If CreateProcess(0&, pathname, securityA, securityA, 1&, _
    NORMAL_PRIORITY_CLASS, 0&, 0&, procAttr, procInfo) <> 1 Then
    'error checking required
    CloseHandle pipeInfo.hStdInRead
    CloseHandle pipeInfo.hStdInWrite
    CloseHandle pipeInfo.hStdOutRead
    CloseHandle pipeInfo.hStdOutWrite
    Exit Function
End If

' set function return to success
ShellPipeApp = True

End Function

Public Function WritePipe(pStringOut As String, _
    hStdInWrite As Long, bytesWritten As Long) As Long

WritePipe = WriteFile(hStdInWrite, pStringOut, _
    Len(pStringOut), bytesWritten, 0&)

End Function

Public Function ReadPipe(pStringIn As String, _
    hStdOutRead As Long, bytesRead As Long) As Long

ReadPipe = ReadFile(hStdOutRead, pStringIn, _
    Len(pStringIn), bytesRead, 0&)

End Function

Public Function ClosePipes(procInfo As PROCESS_INFORMATION, _
    pipeInfo As PIPE_INFORMATION) As Long

'error checking required
CloseHandle procInfo.hProcess
CloseHandle procInfo.hThread

CloseHandle pipeInfo.hStdInRead
CloseHandle pipeInfo.hStdInWrite
CloseHandle pipeInfo.hStdOutRead
CloseHandle pipeInfo.hStdOutWrite

End Function

Sub main()

Dim myProcInfo As PROCESS_INFORMATION
Dim myPipeInfo As PIPE_INFORMATION

Dim myPathName As String
Dim lret As Long

Dim BytesIn As Long
Dim ReadBuffer As String
Dim MoreData As Boolean
Dim OutputString As String

'some more examples listed below
'myPathName = "c:\windows\nbtstat.exe -n"
'myPathName = "c:\windows\netstat.exe -r"
'myPathName = "c:\windows\tracert.exe 127.0.0.1"
'myPathName = "c:\windows\ping.exe 127.0.0.1"

myPathName = "c:\windows\command\mem.exe"

' error checking required
lret = ShellPipeApp(myPathName, myProcInfo, myPipeInfo)

Do

    DoEvents
    ' ReadBuffer Length determines size of data chunk read
    ' ReadBuffer Length must be > 1
    ReadBuffer = Space(256)
    MoreData = False
    lret = ReadPipe(ReadBuffer, myPipeInfo.hStdOutRead, BytesIn)
    If BytesIn = Len(ReadBuffer) Then MoreData = True
    OutputString = OutputString & Left(ReadBuffer, BytesIn)

' exit if shelled app is closed and no more data
Loop Until WaitForSingleObject(myProcInfo.hProcess, 0) = False _
    And MoreData = False

lret = ClosePipes(myProcInfo, myPipeInfo)

MsgBox OutputString

End Sub
' ---------- End of Code ----------



Tue, 25 Jun 2002 03:00:00 GMT  
 HowTo: Capture Text Output (Redirect StdIO)


Fri, 19 Jun 1992 00:00:00 GMT  
 HowTo: Capture Text Output (Redirect StdIO)
Oops left a little bug in!

The line
procAttr.dwFlags = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW
under the ShellPipApp function should read
procAttr.dwFlags = STARTF_USESTDHANDLES

The ammended code is contained below.

Sorry for any inconvenience

Wayne Cornish

Quote:

>Dear All

>Have seen several threads recently on how to capture the text output from
>console apps such as ping, tracert etc. The only solutions ever given
>involve piping the output to a text file, and then reading the text file
>(works with limitations, but can be messy). I have included some source
that
>I have written below, which when pasted into a .bas module will allow you
to
>redirect the Standard Input/Output of an application. The functions will
>work with console and windows apps, but the examples under Sub Main(), only
>cater for console apps. If you wish to run the exsamples, start a new vb
>project, add a module and paste in the code. Then make sure the Startup
>object under project properties is set to 'Sub Main' and the code should
>run. The code should work for VB4-32 and above.

>Any comments/suggestions welcome.

>Wayne Cornish

' ---------- Start of Code ----------
Option Explicit

Private Const NORMAL_PRIORITY_CLASS = &H20
Private Const REALTIME_PRIORITY_CLASS = &H100
Private Const HIGH_PRIORITY_CLASS = &H80
Private Const IDLE_PRIORITY_CLASS = &H40

Private Const STARTF_FORCEOFFFEEDBACK = &H80
Private Const STARTF_FORCEONFEEDBACK = &H40
Private Const STARTF_RUNFULLSCREEN = &H20        '  ignored for non-x86
platforms
Private Const STARTF_USECOUNTCHARS = &H8
Private Const STARTF_USEFILLATTRIBUTE = &H10
Private Const STARTF_USEPOSITION = &H4
Private Const STARTF_USESHOWWINDOW = &H1
Private Const STARTF_USESIZE = &H2
Private Const STARTF_USESTDHANDLES = &H100

Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As Long
    lpDesktop As Long
    lpTitle As Long
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Public Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Public Type PIPE_INFORMATION
    hStdInRead As Long
    hStdInWrite As Long
    hStdOutRead As Long
    hStdOutWrite As Long
End Type

Private Declare Function CreatePipe Lib "kernel32" _
    (phReadPipe As Long, phWritePipe As Long, _
    lpPipeAttributes As Any, ByVal nSize As Long) As Long

Private Declare Function CreateProcess Lib "kernel32" _
    Alias "CreateProcessA" (ByVal lpApplicationName As Long, _
    ByVal lpCommandLine As String, lpProcessAttributes As Any, _
    lpThreadAttributes As Any, ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, lpStartupInfo As Any, _
    lpProcessInformation As Any) As Long

Private Declare Function ReadFile Lib "kernel32" _
    (ByVal hFile As Long, ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToRead As Long, lpNumberOfbytes_read As Long, _
    ByVal lpOverlapped As Any) As Long

Private Declare Function WriteFile Lib "kernel32" _
    (ByVal hFile As Long, ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToWrite As Long, _
    lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long

Public Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hHandle As Long, _
     ByVal dwMilliseconds As Long) As Long

Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Public Function ShellPipeApp(pathname As String, _
    procInfo As PROCESS_INFORMATION, _
    pipeInfo As PIPE_INFORMATION) As Long

Dim securityA As SECURITY_ATTRIBUTES
Dim procAttr As STARTUPINFO

' set return to fail
ShellPipeApp = False

' set security attributes
securityA.nLength = Len(securityA)
securityA.bInheritHandle = 1&
securityA.lpSecurityDescriptor = 0&

' create stdIn pipe
If CreatePipe(pipeInfo.hStdInRead, pipeInfo.hStdInWrite, _
securityA, 0) = 0 Then Exit Function

' create stdOut pipe
If CreatePipe(pipeInfo.hStdOutRead, pipeInfo.hStdOutWrite, _
securityA, 0) = 0 Then
    'error checking required
    CloseHandle pipeInfo.hStdInRead
    CloseHandle pipeInfo.hStdInWrite
    Exit Function
End If

' set process attributes
procAttr.cb = Len(procAttr)
procAttr.dwFlags = STARTF_USESTDHANDLES
procAttr.hStdInput = pipeInfo.hStdInRead
procAttr.hStdOutput = pipeInfo.hStdOutWrite

' start app
If CreateProcess(0&, pathname, securityA, securityA, 1&, _
    NORMAL_PRIORITY_CLASS, 0&, 0&, procAttr, procInfo) <> 1 Then
    'error checking required
    CloseHandle pipeInfo.hStdInRead
    CloseHandle pipeInfo.hStdInWrite
    CloseHandle pipeInfo.hStdOutRead
    CloseHandle pipeInfo.hStdOutWrite
    Exit Function
End If

' set function return to success
ShellPipeApp = True

End Function

Public Function WritePipe(pStringOut As String, _
    hStdInWrite As Long, bytesWritten As Long) As Long

WritePipe = WriteFile(hStdInWrite, pStringOut, _
    Len(pStringOut), bytesWritten, 0&)

End Function

Public Function ReadPipe(pStringIn As String, _
    hStdOutRead As Long, bytesRead As Long) As Long

ReadPipe = ReadFile(hStdOutRead, pStringIn, _
    Len(pStringIn), bytesRead, 0&)

End Function

Public Function ClosePipes(procInfo As PROCESS_INFORMATION, _
    pipeInfo As PIPE_INFORMATION) As Long

'error checking required
CloseHandle procInfo.hProcess
CloseHandle procInfo.hThread

CloseHandle pipeInfo.hStdInRead
CloseHandle pipeInfo.hStdInWrite
CloseHandle pipeInfo.hStdOutRead
CloseHandle pipeInfo.hStdOutWrite

End Function

Sub main()

Dim myProcInfo As PROCESS_INFORMATION
Dim myPipeInfo As PIPE_INFORMATION

Dim myPathName As String
Dim lret As Long

Dim BytesIn As Long
Dim ReadBuffer As String
Dim MoreData As Boolean
Dim OutputString As String

'some more examples listed below
'myPathName = "c:\windows\nbtstat.exe -n"
'myPathName = "c:\windows\netstat.exe -r"
'myPathName = "c:\windows\tracert.exe 127.0.0.1"
'myPathName = "c:\windows\ping.exe 127.0.0.1"

myPathName = "c:\windows\command\mem.exe"

' error checking required
lret = ShellPipeApp(myPathName, myProcInfo, myPipeInfo)

Do

    DoEvents
    ' ReadBuffer Length determines size of data chunk read
    ' ReadBuffer Length must be > 1
    ReadBuffer = Space(256)
    MoreData = False
    lret = ReadPipe(ReadBuffer, myPipeInfo.hStdOutRead, BytesIn)
    If BytesIn = Len(ReadBuffer) Then MoreData = True
    OutputString = OutputString & Left(ReadBuffer, BytesIn)

' exit if shelled app is closed and no more data
Loop Until WaitForSingleObject(myProcInfo.hProcess, 0) = False _
    And MoreData = False

lret = ClosePipes(myProcInfo, myPipeInfo)

MsgBox OutputString

End Sub
' ---------- End of Code ----------



Tue, 25 Jun 2002 03:00:00 GMT  
 HowTo: Capture Text Output (Redirect StdIO)
Dr. Wayne, many  thanks for your examples.



Quote:
> Oops left a little bug in!
> The line
> procAttr.dwFlags = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW
> under the ShellPipApp function should read
> procAttr.dwFlags = STARTF_USESTDHANDLES
> The ammended code is contained below.
> Sorry for any inconvenience

> Wayne Cornish
> . . .



Wed, 26 Jun 2002 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. VB: How do I redirect (capture) a dos-prompt's output

2. Redirect FORM output to local text File

3. Redirect FORM output to local text File

4. VB4 - problem creating text from redirected output of shell command

5. Capture printer output to text file

6. Capture application screen text output

7. Redirecting Print Output

8. redirecting file output

9. Redirecting the output of a DOS application to my .NET application

10. Redirect WshShell.Run Output ?

11. Redirecting Printer Output

12. redirecting program output

 

 
Powered by phpBB® Forum Software