This example illustrates a Visual Basic application starting another process with the purpose of redirecting that process's standard IO handles. The Visual Basic application redirects the created process's standard output handle to an anonymous pipe, then proceeds to read the output through the pipe. This sample just redirects STDOUT of the new process. To redirect other handles (STDIN and STDERR), create a pipe for each handle for which redirection is desired. The Visual Basic application would read from the read ends of the pipes for the redirected STDOUT and STDERR. If STDIN redirection was desired, the Visual Basic application would write to the write end of the appropriate pipe. An example follows: |
Click here to copy the following block | CreatePipe(hReadPipe1, hWritePipe1, sa, 0)
CreatePipe(hReadPipe2, hWritePipe2, sa, 0)
CreatePipe(hReadPipe3, hWritePipe3, sa, 0)
start.hStdOutput = hWritePipe1 start.hStdError = hWritePipe2 start.hStdInput = hReadPipe3
ReadFile(hReadPipe1, mybuff1, 100, bytesread, ByVal 0&)
ReadFile(hReadPipe2, mybuff2, 100, bytesread, ByVal 0&)
WriteFile(hWritePipe3, mybuff3, 100, byteswritten, ByVal 0&) |
Step-By-Step Example
- Create a standard exe project - Add 2 textbox controls and one command button control - Set Multiline=True and Scrollbar=Verticle for Text2 - Add the following code in form1 |
Click here to copy the following block | Option Explicit Private Declare Function CreatePipe Lib "kernel32" ( _ phReadPipe As Long, _ phWritePipe As Long, _ lpPipeAttributes As SECURITY_ATTRIBUTES, _ ByVal nSize As Long) As Long
Private Declare Sub GetStartupInfo Lib "kernel32" Alias "GetStartupInfoA" ( _ lpStartupInfo As STARTUPINFO)
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" ( _ ByVal lpApplicationName As String, _ ByVal lpCommandLine As String, _ lpProcessAttributes As Any, _ lpThreadAttributes As Any, _ ByVal bInheritHandles As Long, _ ByVal dwCreationFlags As Long, _ lpEnvironment As Any, _ ByVal lpCurrentDriectory As String, _ lpStartupInfo As STARTUPINFO, _ lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" ( _ ByVal hwnd As Long, _ ByVal lpString As String) As Long
Private Declare Function ReadFile Lib "kernel32" ( _ ByVal hFile As Long, _ lpBuffer As Any, _ ByVal nNumberOfBytesToRead As Long, _ lpNumberOfBytesRead As Long, _ lpOverlapped As Any) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _ ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Long) As Long
Private Type SECURITY_ATTRIBUTES nLength As Long lpSecurityDescriptor As Long bInheritHandle As Long End Type
Private Type PROCESS_INFORMATION hProcess As Long hThread As Long dwProcessId As Long dwThreadId 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 Byte hStdInput As Long hStdOutput As Long hStdError As Long End Type
Private Type OVERLAPPED ternal As Long ternalHigh As Long offset As Long OffsetHigh As Long hEvent As Long End Type
Private Const STARTF_USESHOWWINDOW = &H1 Private Const STARTF_USESTDHANDLES = &H100 Private Const SW_HIDE = 0 Private Const EM_SETSEL = &HB1 Private Const EM_REPLACESEL = &HC2
Private Sub Command1_Click() Command1.Enabled = False Redirect Text1.Text, Text2 Command1.Enabled = True End Sub Private Sub Form_Load() Command1.Caption = "Run Command" Text1.Text = "cmd /C " & "dir /b c:\" Text2.Font.Name = "Terminal" End Sub Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer) If Command1.Enabled = False Then Cancel = True End Sub
Sub Redirect(cmdLine As String, objTarget As Object) Dim i%, t$ Dim pa As SECURITY_ATTRIBUTES Dim pra As SECURITY_ATTRIBUTES Dim tra As SECURITY_ATTRIBUTES Dim pi As PROCESS_INFORMATION Dim sui As STARTUPINFO Dim hRead As Long Dim hWrite As Long Dim bRead As Long Dim lpBuffer(1024) As Byte pa.nLength = Len(pa) pa.lpSecurityDescriptor = 0 pa.bInheritHandle = True
pra.nLength = Len(pra) tra.nLength = Len(tra)
If CreatePipe(hRead, hWrite, pa, 0) <> 0 Then sui.cb = Len(sui) GetStartupInfo sui sui.hStdOutput = hWrite sui.hStdError = hWrite sui.dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES sui.wShowWindow = SW_HIDE
If CreateProcess(vbNullString, cmdLine, pra, tra, True, 0, Null, vbNullString, sui, pi) <> 0 Then SetWindowText objTarget.hwnd, "" Do Erase lpBuffer() If ReadFile(hRead, lpBuffer(0), 1023, bRead, ByVal 0&) Then SendMessage objTarget.hwnd, EM_SETSEL, -1, 0 SendMessage objTarget.hwnd, EM_REPLACESEL, False, lpBuffer(0) DoEvents Else Exit Do End If CloseHandle hWrite Loop CloseHandle hRead End If End If End Sub |
|