2011-09-12 77 views
1

第一標準輸出的閱讀,讓我說,我不是一個Visual Basic 6的專家...Shell程序在Visual Basic 6

我需要的是:

  • 推出從VB6客戶端代碼exeternal.exe文件
  • 等待該過程完成並在執行過程中讀取來自其「標準輸出」的消息(以便我可以將其打印在文本小部件或類似文件上)。

我想知道如果它甚至有可能做到這一點在VB6 ......互聯網我沒有拿出任何東西在漫長的尋找之後。發現了很多關於如何使用Shell函數的例子,但它似乎迫使我在進程執行結束時一次性讀取標準輸出,但我希望在進程「輪迴」時查詢「新鮮」消息。

真的很感激任何代碼片段/建議/參考。

在此先感謝!

+1

您正在爲此作業使用錯誤的工具。現在需要更新到VB.NET,以便使用Process.BeginOutputReadLine()。 –

+0

我知道......(我真的很喜歡用Java或Python來做到這一點)但是我現在被迫用VB6來做到這一點。 – csparpa

+2

@Hans and claudio你可以在VB.Net中編寫一個DLL,並通過COM interop從VB6調用它。假設外部約束允許這樣做。 – MarkJ

回答

6

使用CreatePipe()創建一個匿名管道,您可以傳遞給CreateProcess()。 你可以從這個管道的要求(使用輪詢或重疊/異步I/O,然後閱讀。

這應該給你足夠的信息來找到一個很好的例子。

+1

是的,人們整天都在VB6中做這個。我在http://www.vbforums.com/showthread.php?t=660014上發佈了一些可重複使用的代碼來幫助說明。 – Bob77

+0

@deanna:你能提供一些代碼嗎,我在鏈接中找到的代碼不起作用 – Smith

2

您還可以創建一個批處理文件,有你需要運行的所有命令,然後從VB6調用批處理文件執行

Shell "C:\YourPath\BatchFileName.bat > OutputFileName.txt" 'Overwrites OutputFilename.txt everytime 

一旦您執行,然後打開OutputFileName.txt,你會發現所有的一切在生成的消息和輸出批處理。然後,您可以在VB6中以簡單的方式讀取它open "filename" for input as #1

您還應該注意,如果您使用雙倍GreaterThan符號,則輸出文件在每次批處理運行時都不會被覆蓋。相反,它會附加新的輸出行。

Shell "C:\YourPath\BatchFileName.bat >> OutputFileName.txt" 'This will append to OutputFileName.txt 
1

這裏是你想要的功能。讀取器會執行聲明API(CreatePipe,CreateProcessA,CloseHandle等),類型(PROCESS_INFORMATION,STARTUPINFO,SECURITY_ATTRIBUTES)常量(STARTF_USESTDHANDLES,STARF_USESHOWWINDOW等)的練習。

Public Function ExecuteCommand(ByVal CommandLine As String, Optional bShowWindow As Boolean = False, Optional sCurrentDir As String) As String 
     Dim proc As PROCESS_INFORMATION  'Process info filled by CreateProcessA 
     Dim ret As Long      'long variable for get the return value of the 
     'API functions 
     Dim start As STARTUPINFO   'StartUp Info passed to the CreateProceeeA 
     'function 
     Dim sa As SECURITY_ATTRIBUTES  'Security Attributes passeed to the 
     'CreateProcessA function 
     Dim hReadPipe As Long    'Read Pipe handle created by CreatePipe 
     Dim hWritePipe As Long    'Write Pite handle created by CreatePipe 
     Dim lngBytesRead As Long   'Amount of byte read from the Read Pipe handle 
     Dim strBuff As String * 256   'String buffer reading the Pipe 


     'if the parameter is not empty update the CommandLine property 


      If Len(CommandLine) > 0 Then 
       mCommand = CommandLine 
      End If 

     'if the command line is empty then exit whit a error message 
      If Len(mCommand) = 0 Then 
       ApplicationEventLogError "Command Line empty in procedure ExecuteCommand of module modPipedOutput." 
       Exit Function 
      End If 

     'Create the Pipe 
      sa.nLength = Len(sa) 
      sa.bInheritHandle = 1& 
      sa.lpSecurityDescriptor = 0& 
      ret = CreatePipe(hReadPipe, hWritePipe, sa, 0) 

      If ret = 0 Then 
      'If an error occur during the Pipe creation exit 
       Debug.Print "CreatePipe failed. Error: " & Err.LastDllError & " (" & ReturnError(Err.LastDllError) 
       Exit Function 
      End If 


     'Launch the command line application 
      start.cb = Len(start) 
      start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW 

     'set the StdOutput and the StdError output to the same Write Pipe handle 
      start.hStdOutput = hWritePipe 
      start.hStdError = hWritePipe 
     ' start.hStdInput = hInReadPipe 
      If bShowWindow Then 
       start.wShowWindow = SW_SHOWNORMAL 
      Else 
       start.wShowWindow = SW_HIDE 
      End If 

     'Execute the command 
      If Len(sCurrentDir) = 0 Then 
       ret& = CreateProcessA(0&, mCommand, sa, sa, 1&, _ 
        NORMAL_PRIORITY_CLASS, 0&, vbNullString, start, proc) 
      Else 
       ret& = CreateProcessA(0&, mCommand, sa, sa, 1&, _ 
        NORMAL_PRIORITY_CLASS, 0&, sCurrentDir, start, proc) 
      End If 

      If ret <> 1 Then 
      'if the command is not found .... 
       Debug.Print "File or command not found in procedure ExecuteCommand" 
       Exit Function 
      End If 

     'Now We can ... must close the hWritePipe 
      ret = CloseHandle(hWritePipe) 
     ' ret = CloseHandle(hInReadPipe) 
      mOutputs = vbNullString 

     'Read the ReadPipe handle 
      Do 
       ret = ReadFile(hReadPipe, strBuff, 256, lngBytesRead, 0&) 

       mOutputs = mOutputs & Left$(strBuff, lngBytesRead) 
      'Send data to the object via ReceiveOutputs event 

      Loop While ret <> 0 

     'Close the opened handles 
      Call CloseHandle(proc.hProcess) 
      Call CloseHandle(proc.hThread) 
      Call CloseHandle(hReadPipe) 

     'Return the Outputs property with the entire DOS output 
      ExecuteCommand = mOutputs 

End Function 
+0

你認爲你可以重新訪問這個答案並讓它工作嗎?我很難找到一個類似的代碼片段。 –

3

您可以隨時使用Exec method of WshShell做的工作。

我更喜歡使用一個土生土長的基於API的解決方案比cExec.cls鮑勃Riemersma的用戶控制更簡單(但不是通用的)。

+0

最簡單,最乾淨!順便說一句,您可以通過添加對「Windows腳本宿主對象模型」庫(wshom.ocx)的引用輕鬆訪問WScript對象, – gbr