RunCMD() is a rewrite and renamed version of my old StdOutToVar() which was adapted from Sean's StdoutToVar
RunCMD( CmdLine, WorkingDir, Codepage, Fn )
RunCMD() runs a console utility in windowless mode and captures its output one line at a time, concatenates them and returns the complete text.
The lines that are read maybe redirected to a helper function for pre-process. Within the helper functions individual lines they maybe omitted or reformatted.
Unlike previous versions, the current RunCMD() v0.93 reads from a non-blocking pipe enabled via PIPE_NOWAIT flag passed to SetNamedPipeHandleState()
During the lifetime of the created process, a global array element A_Args.RunCMD.PID will contain the PID and assigning a 0 (false) to this element will cancel RunCMD().
The created process will inherit the Priority of the script. Therefore Process, Priority,, High maybe used in scripts to see some marginal improvement.
Parameters:
- CmdLine : The command line to be executed.
- WorkingDir : Use this parameter to specify Working Directory. If omitted the launched process will default to A_WorkingDir.
- Codepage : Default is Cp0. Use UTF-8 or UTF-16 when dealing with unicode.
- Fn : Helper function name. When a helper function is available, RunCMD() will call it with two parameters Line, LineNum.
You may control the output within the helper function.
Powershell examples: viewtopic.php?p=341237#p341237
The function:
Code: Select all
RunCMD(CmdLine, WorkingDir:="", Codepage:="CP0", Fn:="RunCMD_Output", Slow:=1) { ; RunCMD v0.97
Local ; RunCMD v0.97 by SKAN on D34E/D67E @ autohotkey.com/boards/viewtopic.php?t=74647
Global A_Args ; Based on StdOutToVar.ahk by Sean @ autohotkey.com/board/topic/15455-stdouttovar
Slow := !! Slow
, Fn := IsFunc(Fn) ? Func(Fn) : 0
, DllCall("CreatePipe", "PtrP",hPipeR:=0, "PtrP",hPipeW:=0, "Ptr",0, "Int",0)
, DllCall("SetHandleInformation", "Ptr",hPipeW, "Int",1, "Int",1)
, DllCall("SetNamedPipeHandleState","Ptr",hPipeR, "UIntP",PIPE_NOWAIT:=1, "Ptr",0, "Ptr",0)
, P8 := (A_PtrSize=8)
, VarSetCapacity(SI, P8 ? 104 : 68, 0) ; STARTUPINFO structure
, NumPut(P8 ? 104 : 68, SI) ; size of STARTUPINFO
, NumPut(STARTF_USESTDHANDLES:=0x100, SI, P8 ? 60 : 44,"UInt") ; dwFlags
, NumPut(hPipeW, SI, P8 ? 88 : 60) ; hStdOutput
, NumPut(hPipeW, SI, P8 ? 96 : 64) ; hStdError
, VarSetCapacity(PI, P8 ? 24 : 16) ; PROCESS_INFORMATION structure
If not DllCall("CreateProcess", "Ptr",0, "Str",CmdLine, "Ptr",0, "Int",0, "Int",True
,"Int",0x08000000 | DllCall("GetPriorityClass", "Ptr",-1, "UInt"), "Int",0
,"Ptr",WorkingDir ? &WorkingDir : 0, "Ptr",&SI, "Ptr",&PI)
Return Format("{1:}", "", ErrorLevel := -1
,DllCall("CloseHandle", "Ptr",hPipeW), DllCall("CloseHandle", "Ptr",hPipeR))
DllCall("CloseHandle", "Ptr",hPipeW)
, A_Args.RunCMD := { "PID": NumGet(PI, P8? 16 : 8, "UInt") }
, File := FileOpen(hPipeR, "h", Codepage)
, LineNum := 1, sOutput := ""
While ( A_Args.RunCMD.PID | DllCall("Sleep", "Int",Slow) )
and DllCall("PeekNamedPipe", "Ptr",hPipeR, "Ptr",0, "Int",0, "Ptr",0, "Ptr",0, "Ptr",0)
While A_Args.RunCMD.PID and StrLen(Line := File.ReadLine())
sOutput .= Fn ? Fn.Call(Line, LineNum++) : Line
A_Args.RunCMD.PID := 0
, hProcess := NumGet(PI, 0)
, hThread := NumGet(PI, A_PtrSize)
, DllCall("GetExitCodeProcess", "Ptr",hProcess, "PtrP",ExitCode:=0)
, DllCall("CloseHandle", "Ptr",hProcess)
, DllCall("CloseHandle", "Ptr",hThread)
, DllCall("CloseHandle", "Ptr",hPipeR)
, ErrorLevel := ExitCode
Return sOutput
}