Instead of a batch file you can just pass the DOS commands directly. Then output the results to a file.
Its not that hard.
This example will pass the DIR command, enter C:\, and output the directory listing to the file C:\Dir.txt
The /K switch is to keep the DOS window open but you can change it to the /C to close it. Also, SW_HIDE to make
it totally transparent to the user.
VB Code:
Option Explicit
Private Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, _
ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
you would want to use the GetSystemDirectory API to dynamically get the directory where the CMD.EXE program is located.
Well that would require that cmd.exe actually is in that directory, and on a Win9x/ME box cmd.exe doesn't even exist. What you can use instead is Environ("COMSPEC").
Well that would require that cmd.exe actually is in that directory, and on a Win9x/ME box cmd.exe doesn't even exist. What you can use instead is Environ("COMSPEC").
At the end of my post I added a Note that you can get the CMD.exe location dynamically using the GetSystemDirectory API.
I dont like to rely on the environ variable since it can be changed or deleted by the user.
Originally Posted by dgleinna
How do you append command output to the same file, though?
You simple use the append mode of file output instead of the output mode.
Output: >
Append: >>
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
Read the outputted file into your program using basic file i/o and set the .Text property of your textbox to the
contents (assuming mult-line textbox).
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
At the end of my post I added a Note that you can get the CMD.exe location dynamically using the GetSystemDirectory API.
I dont like to rely on the environ variable since it can be changed or deleted by the user.
Yes I know, but that requires that cmd.exe is in the system folder. Besides the ComSpec environment variable is safe to use, Win9x doesn't even work properly if you change that to an invalid command interpretor. And on an NT based system the ComSpec environment variable is a system variable which you need admin rights to change.
Anyhow... I've attached a module that uses a different approach (and a tiny bit more advanced) to this. It contains a function called GetCommandOutput that will shell any command and return the output written to StdOut and StdErr as a string. You can then do whatever you want with that string, such as write it to a file, display it in a text box or whatever...
One of the (optional) arguments to this function is called fOEMConvert which would convert the OEM characters use by a command line to the Ansi characters used by Windows. This is especially importent if your command line program will display international characters (like Å or ü for example) since they are different in Ansi compared to OEM.
'Visit Jernejs site at [url]http://www2.arnes.si/~sopjsimo/[/url]
'
'Note: don't run plain DOS programs with this example
'under Windows 95,98 and ME, as the program freezes when
'execution of program is finnished.
Option Explicit
Private Declare Function CreatePipe Lib "kernel32" (phReadPipe As Long, phWritePipe As Long, lpPipeAttributes As SECURITY_ATTRIBUTES, ByVal nSize As Long) As Long
Private Declare Sub GetStartupInfo Lib "kernel32" Alias "GetStartupInfoA" (lpStartupInfo As STARTUPINFO)
Private Declare Function CreateProcess Lib "kernel32" Alias "CreateProcessA" (ByVal lpApplicationName As String, ByVal lpCommandLine As String, lpProcessAttributes As Any, lpThreadAttributes As Any, ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, lpEnvironment As Any, ByVal lpCurrentDriectory As String, lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Long
Private Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Private 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 Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Private Type PROCESS_INFORMATION
hProcess As Long
hThread As Long
dwProcessId As Long
dwThreadId 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 Byte
hStdInput As Long
hStdOutput As Long
hStdError As Long
End Type
Private Type OVERLAPPED
ternal As Long
ternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type
Private Const STARTF_USESHOWWINDOW = &H1
Private Const STARTF_USESTDHANDLES = &H100
Private Const SW_HIDE = 0
Private Const EM_SETSEL = &HB1
Private Const EM_REPLACESEL = &HC2
Private Sub Command1_Click()
Command1.Enabled = False
Redirect Text1.Text, Text2
Command1.Enabled = True
End Sub
Private Sub Form_Load()
Text1.Text = "ping"
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If Command1.Enabled = False Then Cancel = True
End Sub
Sub Redirect(cmdLine As String, objTarget As Object)
Dim i%, t$
Dim pa As SECURITY_ATTRIBUTES
Dim pra As SECURITY_ATTRIBUTES
Dim tra As SECURITY_ATTRIBUTES
Dim pi As PROCESS_INFORMATION
Dim sui As STARTUPINFO
Dim hRead As Long
Dim hWrite As Long
Dim bRead As Long
Dim lpBuffer(1024) As Byte
pa.nLength = Len(pa)
pa.lpSecurityDescriptor = 0
pa.bInheritHandle = True
pra.nLength = Len(pra)
tra.nLength = Len(tra)
If CreatePipe(hRead, hWrite, pa, 0) <> 0 Then
sui.cb = Len(sui)
GetStartupInfo sui
sui.hStdOutput = hWrite
sui.hStdError = hWrite
sui.dwFlags = STARTF_USESHOWWINDOW Or STARTF_USESTDHANDLES
sui.wShowWindow = SW_HIDE
If CreateProcess(vbNullString, cmdLine, pra, tra, True, 0, Null, vbNullString, sui, pi) <> 0 Then
SetWindowText objTarget.hwnd, ""
Do
Erase lpBuffer()
If ReadFile(hRead, lpBuffer(0), 1023, bRead, ByVal 0&) Then
Yea thanks got it sorry i asked i figured that part on my own stupid question -.- Oh and this thread was like instant messageing we all must be really bored
Just imaging ThaRubby, all this attention and great code just for the asking.
I highly doubt any other forum is like ours
Its like this almost ALL the time.
VB/Office Guru™ (AKA: Gangsta Yoda™ ®)
I dont answer coding questions via PM. Please post a thread in the appropriate forum.
So the meat of both examples is the CreatePipe API correct?
Yes, the main difference between my and manavo11's code is that my also use the DuplicateHandle API function so that it can (optionally) read from both StdOut as well as StdErr. My code also is in a function that returns the string instead of writing it directly to a textbox. But basically it's the same idea.
Does your code have the same problem of freezing or crashing under 95, and 98 systems Joacim?
And on another curious note how hard would it be to port code like that over to VB .NET, I'm trying to learn .Net and migrate over to it, but I could see code like this being handy in some situations.