当前位置: 首页 > 知识库问答 >
问题:

使用Autohotkey读取StdErr和StdOut

凤伟泽
2023-03-14

我正在尝试编写一个在后台执行控制台命令并侦听StdOut和StdErr的函数。如果出现错误,它会抛出StdErr和StdOut。我正在尝试使用Autohotkey。首先,我尝试使用WScript。Shell COM Object,但StdErr和StdOut始终为空,尽管StdOut绝对应该为非空。关于WScript的信息不多。Shell COM Object和所有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:\Users\486B~1\AppData\Local\Temp\~temp5812406.res"" -action compile")
} catch e {
    MsgBox % e
}

然后我试着用GetStdHandle来做。在SciTe4Autohotkeys(或任何控制台)中,成功创建了句柄,但当尝试写入StdInn或读取StdOut/StdErr时,我得到了ERROR\u ACCESS\u DENIED(5)。然而,写信给StdOut/StdErr或阅读StdInn对我来说很好,但没用。然后我试着在没有控制台的情况下启动它,我无法创建带有错误error\u SEM\u NOT\u FOUND(187)的句柄。在脚本开始时,它以隐藏模式启动cmd,ant附加到它。如何获得具有正确读/写访问权限的连接控制台的句柄?

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
}

共有1个答案

白永昌
2023-03-14

这是可以做到的,但我不确定你想要实现什么。

您可以使用WScript。Shell,然后在中传递命令。Exec(ComSpec”/C cscript“命令)方法并返回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,

 类似资料:
  • AutoHotkey是一个windows上的开源软件,用于做自动化的处理 将所有用键盘操作和鼠标点击的事件自动化。可以编辑或者录制自己的脚本 为键盘,手柄和鼠标创建快捷键 自动扩展简写。如,键入"btw" 会自动变成 "by the way". 可以创建为自动化脚本创建交互式UI  改变键盘,手柄,鼠标的默认功能 通过 WinLIRC client script.对外部设备的信号进行回应 可以运行

  • 我试图让两个连字符触发短破折号,三个连字符触发长破折号;喜欢 除了工作。以下是我的收获: 这部作品(11部产生2111部产生3部) 这是同一个脚本,但“1”已被替换为“-”,“2”已被替换为“-”,而“3”已被替换为“-“--”-“应该生成”-“和“--”应该生成”-”,但它不起作用,因为我使用的版本中不完全支持Unicode(AutoHotKey.com上的AutoHotKey_L v1.1.0

  • 我对java比较陌生,对如何使用缓冲读取器读取文件很好奇。这是因为我正在上一门课,被分配做一个简单的ceaser密码,我应该解密一个文本文件,创建一个新文件,并将解密的文本放入该文件。我可以用扫描仪和一个10KB的小文件来完成,但是当我要测试的100MB的大文本文件的时候,它是非常慢的。这是我的代码,它应该是读取文件内容。 如果有人能给我指明正确的方向,那就太好了。 提前致谢

  • 问题内容: 我想通过python从目录中调用脚本(它们是可执行的shell脚本)。 到现在为止还挺好: 现在我想要的是:假设我有一个具有启动功能的bash脚本。我从那里打电话 回声“某事” 现在,我想看看sys.stdout和退出代码上的回显。我相信您可以使用.communicate()执行此操作,但是我的操作不符合我的预期。 我究竟做错了什么? 任何帮助深表感谢 问题答案: 授予http://d

  • 问题内容: 我知道有很多关于阅读python文件的文章和回答的问题。但是我仍然想知道是什么使python具有多种方法来完成相同的任务。我只想知道,使用这两种方法对性能有何影响? 问题答案: using语句不是为了提高性能,只要您执行与using语句将自动执行的相同的清除活动,我认为与using语句不存在任何性能提升或损失。 当您将带有功能的语句一起使用时,不需要最后关闭文件,因为它将自动为您关闭文

  • 问题内容: HTTP服务器向我发送JSON响应(字符串),如下所示: 我想将此“远程文件夹的树”与本地文件夹树(例如,包含本地文件位置的字符串向量)进行比较,因此我想在(string,vector(map(string ,string)))(我不知道是否可行)。 我正在开发一种工具来在本地文件夹和远程文件夹之间同步文件,因此我正在使用boost列出本地文件夹,并且我想将本地列表与远程列表(JSON