Click to See Complete Forum and Search --> : Capturing DOS Output


Jared
November 16th, 1999, 12:47 AM
Hello,

I am developing an application that needs to "capture" the text that a DOS prompt displays. For example, I am wanting to Shell out to a compiler for assembly language with a command line, and then capture the output to display in my program. I have tried "piping" the output to a file by doing this for example...

"C:\compiler.exe -h" > "C:\test.txt"

This will "pipe" the output to the file "C:\test.txt". This works for some executables, but not for all of them..? I am wanting to find a bullet proof method to doing this so that it will work for all compilers. Is there a way to read a console's output buffers from VB..?

Any examples, thoughts, ideas, or leads to finding this information would be greatly appreciated.

Thanks for your time...


Please visit VB Overdrive at:
http://extreme-vb.net/vboverdrive/

SulSDK
November 16th, 1999, 07:02 AM
Hi
I think in this link you will find somthing to help you

http://www.vb2themax.com/ArticleBank.asp?PageID=ArticleBank

Regards
SulSDK

Jared
November 16th, 1999, 07:36 AM
Thanks that was exactly what I was looking for..!

But now I have another problem. One executable I want to read the output of apparently does not send it's output to stdOut. Is there any other way to do this so that you could read the output to any device..?

Thanks,
Jared Hoylman

Please visit VB Overdrive at:
http://extreme-vb.net/vboverdrive/

Lothar Haensler
November 16th, 1999, 07:51 AM
This looked like an excellent link.
But, then I downloaded it and wanted to use it and found that it sucked in so many parts, that I finally gave up. Did you try it?
did you get it to work?
No matter what DOS program I used, I never got any redirection to work, although all the DOS programs I tried direct their output to stdout or stderr.

Lothar Haensler
November 16th, 1999, 07:52 AM
if you got that sample to work, I'd like to see your source code. I failed miserably.

you can not only redirect output to stdout, but also to stderr.
si.hStdOutput = yourFirstFileOpenedbycreateFile
si.hStdError = yourSecondFile

Lothar Haensler
November 16th, 1999, 10:28 AM
I have just created a sample app in VB 6 and tested it under win NT.
It allows you to capture output to stdout or stderr by a dos app.


option Explicit

public Declare Function WaitForSingleObject Lib "kernel32" (byval hHandle as Long, byval dwMilliseconds as Long) as Long
public Const INFINITE = &HFFFF
public Const STARTF_USESHOWWINDOW = &H1
public Const SW_HIDE = 0

public Const DUPLICATE_SAME_ACCESS = &H2
public Declare Function DuplicateHandle Lib "kernel32" (byval hSourceProcessHandle as Long, byval hSourceHandle as Long, byval hTargetProcessHandle as Long, lpTargetHandle as Long, byval dwDesiredAccess as Long, byval bInheritHandle as Long, byval dwOptions as Long) as Long

public Declare Function GetCurrentProcess Lib "kernel32" () as Long

private Declare Function CreatePipe Lib "kernel32" ( _
phReadPipe as Long, _
phWritePipe as Long, _
lpPipeAttributes as Any, _
byval nSize as Long) as Long

public Type OVERLAPPED
Internal as Long
InternalHigh as Long
offset as Long
OffsetHigh as Long
hEvent as Long
End Type

public 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 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 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

private Const NORMAL_PRIORITY_CLASS = &H20&
private Const STARTF_USESTDHANDLES = &H100&

public Function ExecCmd(byval strcmd as string) as string
Dim proc as PROCESS_INFORMATION, ret as Long, bSuccess as Long
Dim start as STARTUPINFO
Dim sa as SECURITY_ATTRIBUTES, hReadPipe as Long, hWritePipe _
as Long
Dim hReadErrpipe as Long
Dim hWriteErrpipe as Long
Dim bytesread as Long, mybuff as string
Dim i as Integer

mybuff = string(1000, vbNullChar)

sa.nLength = len(sa)
sa.bInheritHandle = 1&
sa.lpSecurityDescriptor = 0&

ret = CreatePipe(hReadPipe, hWritePipe, sa, 0)
If ret = 0 then
MsgBox "CreatePipe failed. error: " & Err.LastDllError
Exit Function
End If
ret = CreatePipe(hReadErrpipe, hWriteErrpipe, sa, 0)
If ret = 0 then
MsgBox "CreatePipe failed for stderr. error: " & Err.LastDllError
Exit Function
End If


Dim hReadpipedup as Long
bSuccess = DuplicateHandle(GetCurrentProcess(), hReadPipe, GetCurrentProcess(), _
hReadpipedup, 0&, 0&, DUPLICATE_SAME_ACCESS)
If bSuccess = 0 then
MsgBox "failed to dup"
End If
CloseHandle hReadPipe

Dim hReaderrpipedup as Long
bSuccess = DuplicateHandle(GetCurrentProcess(), hReadErrpipe, GetCurrentProcess(), _
hReaderrpipedup, 0&, 0&, DUPLICATE_SAME_ACCESS)
If bSuccess = 0 then
MsgBox "failed to dup"
End If
CloseHandle hReadErrpipe

start.cb = len(start)
start.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
start.wShowWindow = SW_HIDE
start.hStdOutput = hWritePipe
start.hStdError = hWriteErrpipe
' start app
ret& = CreateProcessA(0&, strcmd, sa, sa, 1&, _
NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)
If ret <> 0 then
WaitForSingleObject proc.hProcess, INFINITE
else
MsgBox "CreateProcess failed. error: " & Err.LastDllError
End If

CloseHandle hWritePipe
CloseHandle hWriteErrpipe
Dim strText as string
bSuccess = ReadFile(hReadpipedup, byval mybuff, 1000, bytesread, byval 0&)
If bSuccess = 1 then
strText = Left(mybuff, bytesread)
End If
bSuccess = ReadFile(hReaderrpipedup, byval mybuff, 1000, bytesread, byval 0&)
If bSuccess = 1 then
strText = strText & Left(mybuff, bytesread)
End If

CloseHandle proc.hProcess
CloseHandle proc.hThread
CloseHandle hReadPipe
CloseHandle hReadErrpipe
CloseHandle hReadpipedup
CloseHandle hReaderrpipedup
ExecCmd = strText
End Function




call the function like this:
msgbox execcmd("link.exe")
or
msgbox execcmd("dumpbin /?")
or
msgbox execcmd("mc.exe")

it will return a concatenation of the output of the program to stdout and stderr.

Is it bulletproof?
no, because some DOS apps might still decide to write directly to the screen buffer.
But, it will probably work for most apps.

The ExecCMd function will restrict the output to 1000 bytes. Feel free to modify it.

e-yan
February 3rd, 2001, 10:29 PM
Hi There!
I tried this code exactly as it is. I placed a module and pasted everything there. Next I had a command button on a form with a code:

command1_click()
msgbox execcmd("c:\TASM\compile.bat")
end sub

but the program hangs everytime. Please Help me.
Thanks alot!

(im using VB6 on Windows98)

Cimperiali
February 6th, 2001, 08:08 AM
It is great to read from you again, even at distant time.

Special thanks to Lothar "the Great" Haensler. Come back soon, you Guru.

clarghi
April 4th, 2001, 07:09 AM
Hallo,
I execute a my VB6 program from Dos prompt.
The program write some word in the Dos prompt but, when I write chr(13), I see (obviously) "Comando o nome di file non valido".
So, I want to capture this sentence so it doesn't appear in the Dos box.
Your example is great, but it create the process while the process is already active in my program (is the batch who execute my program!).
For example, if you go in Dos prompt and type "dir /?" you see the correct syntax; I want to optain an output like this; instead, when I write chr(13) from my program to the Dos Box I see the message above.

How can I do this?

Looking forward for prompt replay.

b.r.

Cristiano Larghi

Cimperiali
April 4th, 2001, 08:48 AM
Ciao, Cristiano. E' un peccato che il grande Lothar non frequnti più questo sito - senza dubbio ti avrebbe suggerito la dritta giusta!-
Ti consiglio di riscrivere una nuova domanda, così il popolo di codeguru la leggerà più facilmente.
Ciao,
Cesare

Special thanks to Lothar "the Great" Haensler. Come back soon, you Guru.