Usage: Text1.Text = RunCommand("ipconfig")
VB Code:
  1. Option Explicit
  2. Option Base 0
  3. 'Code written by JoshT.  Use at your own risk :)
  4.  
  5. Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" _
  6.    (ByVal lpApplicationName As String, _
  7.     ByVal lpCommandLine As String, _
  8.     lpProcessAttributes As SECURITY_ATTRIBUTES, _
  9.     lpThreadAttributes As SECURITY_ATTRIBUTES, _
  10.     ByVal bInheritHandles As Long, _
  11.     ByVal dwCreationFlags As Long, _
  12.     lpEnvironment As Any, _
  13.     ByVal lpCurrentDirectory As String, _
  14.     lpStartupInfo As STARTUPINFO, _
  15.     lpProcessInformation As PROCESS_INFORMATION) As Long
  16.  
  17. Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
  18.  
  19. Private Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, _
  20.     lpBuffer As Any, ByVal nNumberOfBytesToRead As Long, lpNumberOfBytesRead As Long, _
  21.     lpOverlapped As Long) As Long
  22.  
  23. Private Declare Function WaitForSingleObject Lib "kernel32" _
  24.     (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
  25.  
  26. Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, _
  27.     phWritePipe As Long, lpPipeAttributes As SECURITY_ATTRIBUTES, _
  28.     ByVal nSize As Long) As Long
  29.  
  30. Private Type STARTUPINFO
  31.         cb As Long
  32.         lpReserved As String
  33.         lpDesktop As String
  34.         lpTitle As String
  35.         dwX As Long
  36.         dwY As Long
  37.         dwXSize As Long
  38.         dwYSize As Long
  39.         dwXCountChars As Long
  40.         dwYCountChars As Long
  41.         dwFillAttribute As Long
  42.         dwFlags As Long
  43.         wShowWindow As Integer
  44.         cbReserved2 As Integer
  45.         lpReserved2 As Long
  46.         hStdInput As Long
  47.         hStdOutput As Long
  48.         hStdError As Long
  49. End Type
  50.  
  51. Private Type PROCESS_INFORMATION
  52.         hProcess As Long
  53.         hThread As Long
  54.         dwProcessId As Long
  55.         dwThreadId As Long
  56. End Type
  57.  
  58. Private Type SECURITY_ATTRIBUTES
  59.         nLength As Long
  60.         lpSecurityDescriptor As Long
  61.         bInheritHandle As Long
  62. End Type
  63.  
  64. Private Const NORMAL_PRIORITY_CLASS As Long = &H20&
  65.  
  66. Private Const STARTF_USESTDHANDLES As Long = &H100&
  67. Private Const STARTF_USESHOWWINDOW As Long = &H1&
  68. Private Const SW_HIDE As Long = 0&
  69.  
  70. Private Const INFINITE As Long = &HFFFF&
  71.  
  72. Public Function RunCommand(CommandLine As String) As String
  73.     Dim si As STARTUPINFO 'used to send info the CreateProcess
  74.     Dim pi As PROCESS_INFORMATION 'used to receive info about the created process
  75.     Dim retval As Long 'return value
  76.     Dim hRead As Long 'the handle to the read end of the pipe
  77.     Dim hWrite As Long 'the handle to the write end of the pipe
  78.     Dim sBuffer(0 To 63) As Byte 'the buffer to store data as we read it from the pipe
  79.     Dim lgSize As Long 'returned number of bytes read by readfile
  80.     Dim sa As SECURITY_ATTRIBUTES
  81.     Dim strResult As String 'returned results of the command line
  82.    
  83.     'set up security attributes structure
  84.     With sa
  85.         .nLength = Len(sa)
  86.         .bInheritHandle = 1& 'inherit, needed for this to work
  87.         .lpSecurityDescriptor = 0&
  88.     End With
  89.    
  90.     'create our anonymous pipe an check for success
  91.     '   note we use the default buffer size
  92.     '   this could cause problems if the process tries to write more than this buffer size
  93.     retval = CreatePipe(hRead, hWrite, sa, 0&)
  94.     If retval = 0 Then
  95.         Debug.Print "CreatePipe Failed"
  96.         RunCommand = ""
  97.         Exit Function
  98.     End If
  99.    
  100.     'set up startup info
  101.     With si
  102.         .cb = Len(si)
  103.         .dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW 'tell it to use (not ignore) the values below
  104.         .wShowWindow = SW_HIDE
  105. '        .hStdInput = GetStdHandle(STD_INPUT_HANDLE)
  106.         .hStdOutput = hWrite 'pass the write end of the pipe as the processes standard output
  107. '        .hStdError = GetStdHandle(STD_ERROR_HANDLE)
  108.     End With
  109.    
  110.     'run the command line and check for success
  111.     retval = CreateProcess(vbNullString, _
  112.                             CommandLine & vbNullChar, _
  113.                             sa, _
  114.                             sa, _
  115.                             1&, _
  116.                             NORMAL_PRIORITY_CLASS, _
  117.                             ByVal 0&, _
  118.                             vbNullString, _
  119.                             si, _
  120.                             pi)
  121.     If retval Then
  122.         'wait until the command line finishes
  123.         '   trouble if the app doesn't end, or waits for user input, etc
  124.         WaitForSingleObject pi.hProcess, INFINITE
  125.        
  126.         'read from the pipe until there's no more (bytes actually read is less than what we told it to)
  127.         Do While ReadFile(hRead, sBuffer(0), 64, lgSize, ByVal 0&)
  128.             'convert byte array to string and append to our result
  129.             strResult = strResult & StrConv(sBuffer(), vbUnicode)
  130.             'TODO = what's in the tail end of the byte array when lgSize is less than 64???
  131.             Erase sBuffer()
  132.             If lgSize <> 64 Then Exit Do
  133.         Loop
  134.        
  135.         'close the handles of the process
  136.         CloseHandle pi.hProcess
  137.         CloseHandle pi.hThread
  138.     Else
  139.         Debug.Print "CreateProcess Failed" & vbCrLf
  140.     End If
  141.    
  142.     'close pipe handles
  143.     CloseHandle hRead
  144.     CloseHandle hWrite
  145.    
  146.     'return the command line output
  147.     RunCommand = Replace(strResult, vbNullChar, "")
  148. End Function