使用 Autohotkey 读取 StdErr 和 StdOut
Reading StdErr and StdOut with Autohotkey
我正在尝试编写一个在后台执行控制台命令并侦听 StdOut 和 StdErr 的函数。如果出现错误,它会抛出 StdErr 和 StdOut。我正在尝试在 Autohotkey 中执行此操作。首先我尝试使用 WScript.Shell COM 对象,但 StdErr 和 StdOut 总是空的,尽管 StdOut 绝对应该是非空的。 WScript.Shell COM 对象的信息不多,所有 Microsoft 文档都在技术档案中。
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:\Users6B~1\AppData\Local\Temp\~temp5812406.res"" -action compile")
} catch e {
MsgBox % e
}
然后我尝试用 GetStdHandle 来做。在 SciTe4Autohotkeys(或任何控制台)中,句柄已成功创建,但在尝试写入 StdInn 或读取 StdOut/StdErr 时,我得到 ERROR_ACCESS_DENIED (5)。然而,写信给 StdOut/StdErr 或阅读 StdInn 工作正常但对我没用。然后我尝试在没有控制台的情况下启动它,但我无法创建错误 ERROR_SEM_NOT_FOUND (187) 的句柄。在脚本的开头,它以蚂蚁附加到它的隐藏模式启动 cmd。如何通过适当的 read/write 访问权限获取附加控制台的句柄?
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:\Users6B~1\AppData\Local\Temp\~temp5812406.res"" -action compile\n")
} catch e {
MsgBox % e
}
可以做到,但我不确定你想要完成什么。
您使用 WScript.Shell
然后在 .Exec(ComSpec " /C cscript " command)
方法和 return 中传递命令 exec.StdOut.ReadAll()
我有一个工作示例如下,也许对你有帮助:
;// The following runs a command (add.vbs)
;// and retrieves its output via StdOut:
InputBox, x,,"Enter two numbers"
MsgBox % """" RunWaitOne("add.vbs " x) """" ;// result in quotes
ExitApp
RunWaitOne(command)
{
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec(ComSpec " /C cscript /nologo " command)
return exec.StdOut.ReadAll()
}
/* This is the external "add.vbs" command:
a=3
b=4
if WScript.Arguments.Count > 0 Then
a=cint(WScript.Arguments.Item(0))
b=cint(WScript.Arguments.Item(1))
End If
Dim StdOut : Set StdOut = CreateObject("Scripting.FileSystemObject").GetStandardStream(1)
x=a+b
StdOut.Write x
*/
Hth,
我正在尝试编写一个在后台执行控制台命令并侦听 StdOut 和 StdErr 的函数。如果出现错误,它会抛出 StdErr 和 StdOut。我正在尝试在 Autohotkey 中执行此操作。首先我尝试使用 WScript.Shell COM 对象,但 StdErr 和 StdOut 总是空的,尽管 StdOut 绝对应该是非空的。 WScript.Shell COM 对象的信息不多,所有 Microsoft 文档都在技术档案中。
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:\Users6B~1\AppData\Local\Temp\~temp5812406.res"" -action compile")
} catch e {
MsgBox % e
}
然后我尝试用 GetStdHandle 来做。在 SciTe4Autohotkeys(或任何控制台)中,句柄已成功创建,但在尝试写入 StdInn 或读取 StdOut/StdErr 时,我得到 ERROR_ACCESS_DENIED (5)。然而,写信给 StdOut/StdErr 或阅读 StdInn 工作正常但对我没用。然后我尝试在没有控制台的情况下启动它,但我无法创建错误 ERROR_SEM_NOT_FOUND (187) 的句柄。在脚本的开头,它以蚂蚁附加到它的隐藏模式启动 cmd。如何通过适当的 read/write 访问权限获取附加控制台的句柄?
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:\Users6B~1\AppData\Local\Temp\~temp5812406.res"" -action compile\n")
} catch e {
MsgBox % e
}
可以做到,但我不确定你想要完成什么。
您使用 WScript.Shell
然后在 .Exec(ComSpec " /C cscript " command)
方法和 return 中传递命令 exec.StdOut.ReadAll()
我有一个工作示例如下,也许对你有帮助:
;// The following runs a command (add.vbs)
;// and retrieves its output via StdOut:
InputBox, x,,"Enter two numbers"
MsgBox % """" RunWaitOne("add.vbs " x) """" ;// result in quotes
ExitApp
RunWaitOne(command)
{
shell := ComObjCreate("WScript.Shell")
exec := shell.Exec(ComSpec " /C cscript /nologo " command)
return exec.StdOut.ReadAll()
}
/* This is the external "add.vbs" command:
a=3
b=4
if WScript.Arguments.Count > 0 Then
a=cint(WScript.Arguments.Item(0))
b=cint(WScript.Arguments.Item(1))
End If
Dim StdOut : Set StdOut = CreateObject("Scripting.FileSystemObject").GetStandardStream(1)
x=a+b
StdOut.Write x
*/
Hth,