Run a batch program(.bat) through a Visual Basic 6.0

一世执手 提交于 2019-12-25 01:09:00

问题


I want to run a batch program(.bat) through a Visual Basic 6.0 application and also want to print the output of the batch program(.bat) in the Visual Basic 6.0 application. I want to execute the dir command in the batch file so that VB6.0 application can print the output in a text box.

VB6.0 code:

Dim com As String
Dim wshThisShell
Dim lngRet As Long
Dim strShellCommand As String
Dim strBatchPath As String

Sub C0ding()
    Set wshThisShell = CreateObject("WScript.Shell")
    strBatchPath = "C:\first.bat"
    strShellCommand = """" & strBatchPath & """"
    lngRet = wshThisShell.Run(strShellCommand, vbNormalFocus, vbTrue)
End Sub

Private Sub Command1_Click()
    C0ding
End Sub

first.bat:

dir c:\

In the above example 'first.bat' is batch file and containing the 'dir c:\' command. Now VB6.0 app will run the first.bat and show the output of the 'dir c:\' command in a text box.

Please also tell me that I can achieve this requirement means can VB6.0 application regain the control from batch program(.bat)?

Please help me with this.


回答1:


Your example is not a batch file, but if all you want to do is display the results of a command prompt's dir c:\ command in a textbox, then the following should work:

Disclaimer: The following is "Air Code" and not tested for syntax

Private Sub Command1_Click()
    Dim sCommand As String
    sCommand = "dir c:\ > C:\tempFile.txt"
    Shell "%COMSPEC% /c " & sCommand
    Dim inCh As Integer
    inCh = Freefile
    Open "C:\tempFile.txt" For Input As inCh
    Text1.Text = Input$(Lof(inCh), inCh)
    Close inCh
End Sub

There are several variations and alternative ways to accomplish this, this is just a quick-and-dirty solution example.




回答2:


Lots of simple ways to skin this cat, for example:

Option Explicit

'Reference to: Windows Script Host Object Model

Private WshExec As IWshRuntimeLibrary.WshExec

Private Sub Form_Load()
    With New IWshRuntimeLibrary.WshShell
        Set WshExec = .Exec("cmd.exe /c dir c:\")
    End With
    Timer1.Interval = 100
End Sub

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        Text1.Move 0, 0, ScaleWidth, ScaleHeight
    End If
End Sub

Private Sub Timer1_Timer()
    With WshExec
        Select Case .Status
            Case WshFinished, WshFailed
                Text1.Text = .StdOut.ReadAll()
                Timer1.Interval = 0
        End Select
    End With
End Sub



回答3:


Following is solution which worked for me:

Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As Any, ByVal nSize As Long) As Long
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
Private Declare Function GetNamedPipeInfo Lib "kernel32" (ByVal hNamedPipe As Long, lType As Long, lLenOutBuf As Long, lLenInBuf As Long, lMaxInstances As Long) As Long

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

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

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
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
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long


'Purpose     :  Synchronously runs a DOS command line and returns the captured screen output.
'Inputs      :  sCommandLine                The DOS command line to run.
'               [bShowWindow]               If True displays the DOS output window.
'Outputs     :  Returns the screen output
'Notes       :  This routine will work only with those program that send their output to
'               the standard output device (stdout).
'               Windows NT ONLY.
'Revisions   :

Function ShellExecuteCapture(sCommandLine As String, Optional bShowWindow As Boolean = False) As String
    Const clReadBytes As Long = 256, INFINITE As Long = &HFFFFFFFF
    Const STARTF_USESHOWWINDOW = &H1, STARTF_USESTDHANDLES = &H100&
    Const SW_HIDE = 0, SW_NORMAL = 1
    Const NORMAL_PRIORITY_CLASS = &H20&

    Const PIPE_CLIENT_END = &H0     'The handle refers to the client end of a named pipe instance. This is the default.
    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.
    Const PIPE_TYPE_BYTE = &H0      'The named pipe is a byte pipe. This is the default.
    Const PIPE_TYPE_MESSAGE = &H4   'The named pipe is a message pipe. If this value is not specified, the pipe is a byte pipe


    Dim tProcInfo As PROCESS_INFORMATION, lRetVal As Long, lSuccess As Long
    Dim tStartupInf As STARTUPINFO
    Dim tSecurAttrib As SECURITY_ATTRIBUTES, lhwndReadPipe As Long, lhwndWritePipe As Long
    Dim lBytesRead As Long, sBuffer As String
    Dim lPipeOutLen As Long, lPipeInLen As Long, lMaxInst As Long

    tSecurAttrib.nLength = Len(tSecurAttrib)
    tSecurAttrib.bInheritHandle = 1&
    tSecurAttrib.lpSecurityDescriptor = 0&

    lRetVal = CreatePipe(lhwndReadPipe, lhwndWritePipe, tSecurAttrib, 0)
    If lRetVal = 0 Then
        'CreatePipe failed
        Exit Function
    End If

    tStartupInf.cb = Len(tStartupInf)
    tStartupInf.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    tStartupInf.hStdOutput = lhwndWritePipe
    If bShowWindow Then
        'Show the DOS window
        tStartupInf.wShowWindow = SW_NORMAL
    Else
        'Hide the DOS window
        tStartupInf.wShowWindow = SW_HIDE
    End If

    lRetVal = CreateProcessA(0&, sCommandLine, tSecurAttrib, tSecurAttrib, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, tStartupInf, tProcInfo)
    If lRetVal <> 1 Then
        'CreateProcess failed
        Exit Function
    End If

    'Process created, wait for completion. Note, this will cause your application
    'to hang indefinately until this process completes.
    WaitForSingleObject tProcInfo.hProcess, INFINITE

    'Determine pipes contents
    lSuccess = GetNamedPipeInfo(lhwndReadPipe, PIPE_TYPE_BYTE, lPipeOutLen, lPipeInLen, lMaxInst)
    If lSuccess Then
        'Got pipe info, create buffer
        sBuffer = String(lPipeOutLen, 0)
        'Read Output Pipe
        lSuccess = ReadFile(lhwndReadPipe, sBuffer, lPipeOutLen, lBytesRead, 0&)
        If lSuccess = 1 Then
            'Pipe read successfully
            ShellExecuteCapture = Left$(sBuffer, lBytesRead)
        End If
    End If

    'Close handles
    Call CloseHandle(tProcInfo.hProcess)
    Call CloseHandle(tProcInfo.hThread)
    Call CloseHandle(lhwndReadPipe)
    Call CloseHandle(lhwndWritePipe)
End Function

Sub Test()
    'Debug.Print ShellExecuteCapture("C:\first.bat", False)
    Text1.Text = ShellExecuteCapture("C:\first.bat", False)
End Sub

Private Sub Command1_Click()
    Call Test
End Sub

I got this solution from the following link: Solution Link



来源:https://stackoverflow.com/questions/50879063/run-a-batch-program-bat-through-a-visual-basic-6-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!