Results 1 to 4 of 4

Thread: Getting information from external programs

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Mar 2006
    Posts
    18

    Getting information from external programs

    I am trying to gather information from a command line program that is running in the background to use in my VB program. The command line program basically continuously displays values and I want to be able to capture these and store them to use in my program.

    Is this possible and if so how do I do it?

  2. #2
    Frenzied Member Jmacp's Avatar
    Join Date
    Jul 2003
    Location
    UK
    Posts
    1,959

    Re: Getting information from external programs

    VB Code:
    1. CreatePipe

    VB Code:
    1. Capture DOS screen output from a command line
    2.  
    3. This code is extremely useful if you ever need to capture output from a DOS screen/console. The simple demonstration below, shows how to capture the output from a batch file.
    4.  
    5. Note, to redirect other handles (STDIN and STDERR), create a pipe for each handle for which redirection is desired. The code should read from the read ends of the pipes for the redirected STDOUT and STDERR. If STDIN redirection was desired, the could should write to the write end of the appropriate pipe.
    6.  
    7. Option Explicit
    8.  
    9. Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As Any, ByVal nSize As Long) As Long
    10. Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
    11. Private Declare Function GetNamedPipeInfo Lib "kernel32" (ByVal hNamedPipe As Long, lType As Long, lLenOutBuf As Long, lLenInBuf As Long, lMaxInstances As Long) As Long
    12.    
    13. Private Type SECURITY_ATTRIBUTES
    14.     nLength As Long
    15.     lpSecurityDescriptor As Long
    16.     bInheritHandle As Long
    17. End Type
    18.  
    19. Private Type STARTUPINFO
    20.     cb As Long
    21.     lpReserved As Long
    22.     lpDesktop As Long
    23.     lpTitle As Long
    24.     dwX As Long
    25.     dwY As Long
    26.     dwXSize As Long
    27.     dwYSize As Long
    28.     dwXCountChars As Long
    29.     dwYCountChars As Long
    30.     dwFillAttribute As Long
    31.     dwFlags As Long
    32.     wShowWindow As Integer
    33.     cbReserved2 As Integer
    34.     lpReserved2 As Long
    35.     hStdInput As Long
    36.     hStdOutput As Long
    37.     hStdError As Long
    38. End Type
    39.  
    40. Private Type PROCESS_INFORMATION
    41.     hProcess As Long
    42.     hThread As Long
    43.     dwProcessID As Long
    44.     dwThreadID As Long
    45. End Type
    46.  
    47. Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
    48. Private Declare Function CreateProcessA Lib "kernel32" (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
    49. Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
    50.  
    51.  
    52. 'Purpose     :  Synchronously runs a DOS command line and returns the captured screen output.
    53. 'Inputs      :  sCommandLine                The DOS command line to run.
    54. '               [bShowWindow]               If True displays the DOS output window.
    55. 'Outputs     :  Returns the screen output
    56. 'Notes       :  This routine will work only with those program that send their output to
    57. '               the standard output device (stdout).
    58. '               Windows NT ONLY.
    59. 'Revisions   :
    60.  
    61. Function ShellExecuteCapture(sCommandLine As String, Optional bShowWindow As Boolean = False) As String
    62.     Const clReadBytes As Long = 256, INFINITE As Long = &HFFFFFFFF
    63.     Const STARTF_USESHOWWINDOW = &H1, STARTF_USESTDHANDLES = &H100&
    64.     Const SW_HIDE = 0, SW_NORMAL = 1
    65.     Const NORMAL_PRIORITY_CLASS = &H20&
    66.    
    67.     Const PIPE_CLIENT_END = &H0     'The handle refers to the client end of a named pipe instance. This is the default.
    68.     Const PIPE_SERVER_END = &H1     'The handle refers to the server end of a named pipe instance. If this value is not specified, the handle refers to the client end of a named pipe instance.
    69.     Const PIPE_TYPE_BYTE = &H0      'The named pipe is a byte pipe. This is the default.
    70.     Const PIPE_TYPE_MESSAGE = &H4   'The named pipe is a message pipe. If this value is not specified, the pipe is a byte pipe
    71.    
    72.    
    73.     Dim tProcInfo As PROCESS_INFORMATION, lRetVal As Long, lSuccess As Long
    74.     Dim tStartupInf As STARTUPINFO
    75.     Dim tSecurAttrib As SECURITY_ATTRIBUTES, lhwndReadPipe As Long, lhwndWritePipe As Long
    76.     Dim lBytesRead As Long, sBuffer As String
    77.     Dim lPipeOutLen As Long, lPipeInLen As Long, lMaxInst As Long
    78.    
    79.     tSecurAttrib.nLength = Len(tSecurAttrib)
    80.     tSecurAttrib.bInheritHandle = 1&
    81.     tSecurAttrib.lpSecurityDescriptor = 0&
    82.  
    83.     lRetVal = CreatePipe(lhwndReadPipe, lhwndWritePipe, tSecurAttrib, 0)
    84.     If lRetVal = 0 Then
    85.         'CreatePipe failed
    86.         Exit Function
    87.     End If
    88.  
    89.     tStartupInf.cb = Len(tStartupInf)
    90.     tStartupInf.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    91.     tStartupInf.hStdOutput = lhwndWritePipe
    92.     If bShowWindow Then
    93.         'Show the DOS window
    94.         tStartupInf.wShowWindow = SW_NORMAL
    95.     Else
    96.         'Hide the DOS window
    97.         tStartupInf.wShowWindow = SW_HIDE
    98.     End If
    99.  
    100.     lRetVal = CreateProcessA(0&, sCommandLine, tSecurAttrib, tSecurAttrib, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, tStartupInf, tProcInfo)
    101.     If lRetVal <> 1 Then
    102.         'CreateProcess failed
    103.         Exit Function
    104.     End If
    105.    
    106.     'Process created, wait for completion. Note, this will cause your application
    107.     'to hang indefinately until this process completes.
    108.     WaitForSingleObject tProcInfo.hProcess, INFINITE
    109.    
    110.     'Determine pipes contents
    111.     lSuccess = GetNamedPipeInfo(lhwndReadPipe, PIPE_TYPE_BYTE, lPipeOutLen, lPipeInLen, lMaxInst)
    112.     If lSuccess Then
    113.         'Got pipe info, create buffer
    114.         sBuffer = String(lPipeOutLen, 0)
    115.         'Read Output Pipe
    116.         lSuccess = ReadFile(lhwndReadPipe, sBuffer, lPipeOutLen, lBytesRead, 0&)
    117.         If lSuccess = 1 Then
    118.             'Pipe read successfully
    119.             ShellExecuteCapture = Left$(sBuffer, lBytesRead)
    120.         End If
    121.     End If
    122.    
    123.     'Close handles
    124.     Call CloseHandle(tProcInfo.hProcess)
    125.     Call CloseHandle(tProcInfo.hThread)
    126.     Call CloseHandle(lhwndReadPipe)
    127.     Call CloseHandle(lhwndWritePipe)
    128. End Function
    129.  
    130.  
    131. 'Demonstration routine
    132. 'NOTE: Create a file called "C:\test.bat" containing a single line:
    133. '   dir *.*
    134. Sub Test()
    135.     Debug.Print ShellExecuteCapture("C:\test.bat", False)
    136. End Sub

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Mar 2006
    Posts
    18

    Re: Getting information from external programs

    Will that code work if the program continually outputs values instead of just one output? I basically am making a progress bar to represent the percentage done of a task that is output from the program. Will this code continually send back new values?

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Mar 2006
    Posts
    18

    Re: Getting information from external programs

    I have found this bit of code that works well for me if I am just capturing one output from a DOS command. It doesn't work for my purpose though. I want to be able to capture continual output. Anyone know how to do this?


    VB Code:
    1. Option Explicit
    2.  
    3. 'The CreatePipe function creates an anonymous pipe,
    4. 'and returns handles to the read and write ends of the pipe.
    5. Private Declare Function CreatePipe Lib "kernel32" ( _
    6.     phReadPipe As Long, _
    7.     phWritePipe As Long, _
    8.     lpPipeAttributes As Any, _
    9.     ByVal nSize As Long) As Long
    10.  
    11. 'Used to read the the pipe filled by the process create
    12. 'with the CretaProcessA function
    13. Private Declare Function ReadFile Lib "kernel32" ( _
    14.     ByVal hFile As Long, _
    15.     ByVal lpBuffer As String, _
    16.     ByVal nNumberOfBytesToRead As Long, _
    17.     lpNumberOfBytesRead As Long, _
    18.     ByVal lpOverlapped As Any) As Long
    19.  
    20. 'Structure used by the CreateProcessA function
    21. Private Type SECURITY_ATTRIBUTES
    22.     nLength As Long
    23.     lpSecurityDescriptor As Long
    24.     bInheritHandle As Long
    25. End Type
    26.  
    27. 'Structure used by the CreateProcessA function
    28. Private Type STARTUPINFO
    29.     cb As Long
    30.     lpReserved As Long
    31.     lpDesktop As Long
    32.     lpTitle As Long
    33.     dwX As Long
    34.     dwY As Long
    35.     dwXSize As Long
    36.     dwYSize As Long
    37.     dwXCountChars As Long
    38.     dwYCountChars As Long
    39.     dwFillAttribute As Long
    40.     dwFlags As Long
    41.     wShowWindow As Integer
    42.     cbReserved2 As Integer
    43.     lpReserved2 As Long
    44.     hStdInput As Long
    45.     hStdOutput As Long
    46.     hStdError As Long
    47. End Type
    48.  
    49. 'Structure used by the CreateProcessA function
    50. Private Type PROCESS_INFORMATION
    51.     hProcess As Long
    52.     hThread As Long
    53.     dwProcessID As Long
    54.     dwThreadID As Long
    55. End Type
    56.  
    57. 'This function launch the the commend and return the relative process
    58. 'into the PRECESS_INFORMATION structure
    59. Private Declare Function CreateProcessA Lib "kernel32" ( _
    60.     ByVal lpApplicationName As Long, _
    61.     ByVal lpCommandLine As String, _
    62.     lpProcessAttributes As SECURITY_ATTRIBUTES, _
    63.     lpThreadAttributes As SECURITY_ATTRIBUTES, _
    64.     ByVal bInheritHandles As Long, _
    65.     ByVal dwCreationFlags As Long, _
    66.     ByVal lpEnvironment As Long, _
    67.     ByVal lpCurrentDirectory As Long, _
    68.     lpStartupInfo As STARTUPINFO, _
    69.     lpProcessInformation As PROCESS_INFORMATION) As Long
    70.  
    71. 'Close opened handle
    72. Private Declare Function CloseHandle Lib "kernel32" ( _
    73.     ByVal hHandle As Long) As Long
    74.  
    75. 'Consts for the above functions
    76. Private Const NORMAL_PRIORITY_CLASS = &H20&
    77. Private Const STARTF_USESTDHANDLES = &H100&
    78. Private Const STARTF_USESHOWWINDOW = &H1
    79.  
    80.  
    81. Private mCommand As String          'Private variable for the CommandLine property
    82. Private mOutputs As String          'Private variable for the ReadOnly Outputs property
    83.  
    84. 'Event that notify the temporary buffer to the object
    85. Public Event ReceiveOutputs(CommandOutputs As String)
    86.  
    87. 'This property set and get the DOS command line
    88. 'It's possible to set this property directly from the
    89. 'parameter of the ExecuteCommand method
    90. Public Property Let CommandLine(DOSCommand As String)
    91.     mCommand = DOSCommand
    92. End Property
    93.  
    94. Public Property Get CommandLine() As String
    95.     CommandLine = mCommand
    96. End Property
    97.  
    98. 'This property ReadOnly get the complete output after
    99. 'a command execution
    100. Public Property Get Outputs()
    101.     Outputs = mOutputs
    102. End Property
    103.  
    104. Public Function ExecuteCommand(Optional CommandLine As String) As String
    105.     Dim proc As PROCESS_INFORMATION     'Process info filled by CreateProcessA
    106.     Dim ret As Long                     'long variable for get the return value of the
    107.                                         'API functions
    108.     Dim start As STARTUPINFO            'StartUp Info passed to the CreateProceeeA
    109.                                         'function
    110.     Dim sa As SECURITY_ATTRIBUTES       'Security Attributes passeed to the
    111.                                         'CreateProcessA function
    112.     Dim hReadPipe As Long               'Read Pipe handle created by CreatePipe
    113.     Dim hWritePipe As Long              'Write Pite handle created by CreatePipe
    114.     Dim lngBytesread As Long            'Amount of byte read from the Read Pipe handle
    115.     Dim strBuff As String * 256         'String buffer reading the Pipe
    116.  
    117.     'if the parameter is not empty update the CommandLine property
    118.     If Len(CommandLine) > 0 Then
    119.         mCommand = CommandLine
    120.     End If
    121.    
    122.     'if the command line is empty then exit whit a error message
    123.     If Len(mCommand) = 0 Then
    124.         MsgBox "Command Line empty", vbCritical
    125.         Exit Function
    126.     End If
    127.    
    128.     'Create the Pipe
    129.     sa.nLength = Len(sa)
    130.     sa.bInheritHandle = 1&
    131.     sa.lpSecurityDescriptor = 0&
    132.     ret = CreatePipe(hReadPipe, hWritePipe, sa, 0)
    133.    
    134.     If ret = 0 Then
    135.         'If an error occur during the Pipe creation exit
    136.         MsgBox "CreatePipe failed. Error: " & Err.LastDllError, vbCritical
    137.         Exit Function
    138.     End If
    139.    
    140.     'Launch the command line application
    141.     start.cb = Len(start)
    142.     start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    143.     'set the StdOutput and the StdError output to the same Write Pipe handle
    144.     start.hStdOutput = hWritePipe
    145.     start.hStdError = hWritePipe
    146.     'Execute the command
    147.     ret& = CreateProcessA(0&, mCommand, sa, sa, 1&, _
    148.         NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
    149.        
    150.     If ret <> 1 Then
    151.         'if the command is not found ....
    152.         MsgBox "File or command not found", vbCritical
    153.         Exit Function
    154.     End If
    155.    
    156.     'Now We can ... must close the hWritePipe
    157.     ret = CloseHandle(hWritePipe)
    158.     mOutputs = ""
    159.    
    160.     'Read the ReadPipe handle
    161.     Do
    162.         ret = ReadFile(hReadPipe, strBuff, 256, lngBytesread, 0&)
    163.         mOutputs = mOutputs & Left(strBuff, lngBytesread)
    164.         'Send data to the object via ReceiveOutputs event
    165.         RaiseEvent ReceiveOutputs(Left(strBuff, lngBytesread))
    166.     Loop While ret <> 0
    167.    
    168.     'Close the opened handles
    169.     ret = CloseHandle(proc.hProcess)
    170.     ret = CloseHandle(proc.hThread)
    171.     ret = CloseHandle(hReadPipe)
    172.    
    173.     'Return the Outputs property with the entire DOS output
    174.     ExecuteCommand = mOutputs
    175. End Function

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width