Function RunConsoleCallback
console program for testing
Function console2
;/
function# cbFunc cbParam $cl [$curDir] [flags] ;;flags: 1 show window, 0x200 exclude stdError, 0x400 ANSI, 0x800 UTF-8, 0x1000 UTF-16, 0x4000 64-bit System folder
;Runs a console program. Calls a callback function that receives its output in real time. Or displays in QM output.
;Returns the exit code of the process.
;Error if fails or the file does not exist.
;cbFunc, cbParam - callback function, and some value to pass to it. Must begin with:
;;;function# cbParam $s
;;;;cbParam - cbParam of RunConsoleCallback. Can be declared as TYPE&cbParam if you want to pass address of a variable of type TYPE.
;;;;s - console output line text.
;;;;The return value currently is not used.
;;;If cbFunc is 0, displays console output text in QM output panel.
;cl - program name or full path, optionally followed by command line parameters.
;;;Must be exe, not a document.
;;;Example: "$desktop$\folder\program.exe /a ''c:\new folder\file.txt''".
;;;Program path should be enclosed in quotes if contains spaces.
;;;Expands path even if program path is enclosed in quotes. Example: "''$my qm$\an.exe'' /a".
;curDir - current directory for the program.
;flags:
;;;0-255 - console window show state, like with ShowWindow. If 0 (default), it is hidden.
;;;0x200 - don't get standard error output.
;;;0x400 - console text encoding is current user's defaul ANSI encoding, not OEM.
;;;0x800 - console text encoding is UTF-8, not OEM.
;;;0x1000 - console text encoding is UTF-16, not OEM.
;;;0x4000 - temporarily disable file system redirection from 64-bit system folder (System32) to 32-bit system folder (SysWOW64). Without this flag, starting from QM 2.4.8, this function retries with disabled redirection if file not found.
;REMARKS
;Unlike <help>RunConsole2</help>, allows to capture console output lines immediately, in real time, not when the process ends.
;Expands special folder string in program's path and in curDir, but not in command line arguments.
;While waiting, this thread cannot receive window/dialog messages, COM events, hooks. If need, call this function from separate thread (mac).
;EXAMPLE
;out
;int ec=RunConsoleCallback(&sub.OnConsoleOutput 0 "$my qm$\console2.exe /ab cd")
;out ec
;
;#sub OnConsoleOutput
;function# cbParam $s
;out F"<{s}>"
;create pipe
__Handle hProcess hOutRead hOutWrite
SECURITY_ATTRIBUTES sa.nLength=sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle=1
if(!CreatePipe(&hOutRead &hOutWrite &sa 0)) end "" 16
SetHandleInformation(hOutRead HANDLE_FLAG_INHERIT 0)
;create process
PROCESS_INFORMATION pi
STARTUPINFOW si.cb=sizeof(STARTUPINFOW)
si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW
si.hStdOutput=hOutWrite
if(flags&0x200=0) si.hStdError=hOutWrite
si.wShowWindow=flags&255
str s1 s2 s3
if(cl and cl[0]=34) s1.expandpath(cl+1); s1-"''"; else s1.expandpath(cl)
if(!empty(curDir)) s2.expandpath(curDir)
;g1
__DisableFsRedirection dfsr; if(flags&0x4000) dfsr.Disable
if(!CreateProcessW(0 @s1 0 0 1 CREATE_NEW_CONSOLE 0 @s2 &si &pi))
,if(flags&0x4000=0 and GetLastError=ERROR_FILE_NOT_FOUND and _win64) flags|0x4000; goto g1
,end "" 16
hOutWrite.Close
CloseHandle(pi.hThread)
hProcess=pi.hProcess
;read pipe
int n=100000
s1.all(n)
int r
rep
,if(!PeekNamedPipe(hOutRead 0 0 0 &r 0)) break ;;makes easier to end thread etc
,if(r<n) 0.01
,if(!r) continue
,if(!ReadFile(hOutRead s1 n &r 0)) break
,s2.get(s1.lpstr 0 r)
,if s2.len
,,if flags&0x400 ;;ANSI
,,,if(_unicode) s2.ConvertEncoding(0 -1)
,,else if flags&0x800 ;;UTF-8
,,,if(!_unicode) s2.ConvertEncoding(CP_UTF8 0)
,,else if flags&0x1000 ;;UTF-16
,,,s2.ansi
,,else ;;OEM
,,,s2.ConvertEncoding(GetOEMCP -1)
,
,foreach s3 s2
,,if(cbFunc) call(cbFunc cbParam s3)
,,else out s3
int ec
if(!GetExitCodeProcess(hProcess &ec)) ec=-1000
ret ecconsole program for testing
Function console2
