I am trying to write a function that executes console commands in the background and listens StdOut and StdErr. In case of an error, it throws StdErr and StdOut. I am trying to do it in Autohotkey. First I tried using WScript.Shell COM Object, but StdErr and StdOut always empty, although StdOut definitely should be non-empty. There isn't much information on WScript.Shell COM Object and all Microsoft docs are in tech archive.
Util_Command(command) {
dhw := A_DetectHiddenWindows
DetectHiddenWindows On
Run "%ComSpec%" /k,, Hide, pid
while !(hConsole := WinExist("ahk_pid" pid))
Sleep 10
DllCall("AttachConsole", "UInt", pid)
DetectHiddenWindows %dhw%
objShell := ComObjCreate("WScript.Shell")
objExec := objShell.Exec(command)
While (!objExec.Status) {
Sleep 100
}
err := objExec.ExitCode
StdErr := objExec.StdErr.ReadAll()
StdOut := objExec.StdOut.ReadAll()
DllCall("FreeConsole")
Process Exist, %pid%
if (ErrorLevel == pid) {
Process Close, %pid%
}
if (err) {
if (!StdErr) {
throw StdOut
}
throw StdErr
}
}
try {
Util_Command("""C:\Program Files (x86)\Resource Hacker\ResourceHacker.exe"" -open ""non/existent/dir"" -save ""C:\Users\486B~1\AppData\Local\Temp\~temp5812406.res"" -action compile")
} catch e {
MsgBox % e
}
Then I tried doing it with GetStdHandle. In SciTe4Autohotkeys (or in any console) handle gets created successfully, but when trying to write to StdInn or read StdOut/StdErr I get ERROR_ACCESS_DENIED (5). However, writing to StdOut/StdErr or reading StdInn works fine but useless to me. Then I tried launching it without a console and I can't create a handle with error ERROR_SEM_NOT_FOUND (187). At the beginning of the script, it launches cmd in hidden mode ant attaches to it. How can I get handles of the attached console with proper read/write access?
Util_Command(lpCommand) {
dhw := A_DetectHiddenWindows
DetectHiddenWindows On
Run "%ComSpec%" /k,, Hide, pid
while !(hConsole := WinExist("ahk_pid" pid))
Sleep 10
DllCall("AttachConsole", "UInt", pid)
DetectHiddenWindows %dhw%
hStdIn := DllCall("GetStdHandle", "Int", -10)
hStdOut := DllCall("GetStdHandle", "Int", -11)
hStdErr := DllCall("GetStdHandle", "Int", -12)
StrPut(lpCommand, "UTF-8")
VarSetCapacity(lpCommand, 1024)
VarSetCapacity(lpStdErrBuffer, 2048)
a := DllCall("WriteFile"
, "Ptr", hStdIn
, "Ptr", &lpCommand
, "UInt", 1024
, "UInt", 0
, "UInt", 0)
a := DllCall("ReadFile"
, "Ptr", hStdOut
, "Ptr", &lpStdOutBuffer
, "UInt", 2048
, "UInt", 0
, "UInt", 0)
a := DllCall("ReadFile"
, "Ptr", hStdErr
, "Ptr", &lpStdErrBuffer
, "UInt", 2048
, "UInt", 0
, "UInt", 0)
FileAppend, stdErr - %lpStdErrBuffer%`nstdOut - %lpStdOutBuffer%`n, *
DllCall("FreeConsole")
Process Exist, %pid%
if (ErrorLevel == pid) {
Process Close, %pid%
}
if (err) {
if (!StdErr) {
throw StdOut
}
throw StdErr
}
}
try {
Util_Command("""C:\Program Files (x86)\Resource Hacker\ResourceHacker.exe"" -open ""non/existent/dir"" -save ""C:\Users\486B~1\AppData\Local\Temp\~temp5812406.res"" -action compile\n")
} catch e {
MsgBox % e
}