使用AutoHotkey捕获CMD输出

时间:2013-04-04 19:40:50

标签: cmd autohotkey

我正在尝试使用AutoHotkey阅读Windows CMD的标准输出。例如,我想让AHK中的set控制台命令的输出存储在一个变量中。我已经在不久前实现了它,这使我更加困惑为什么它现在不起作用 在AHK论坛中,有一个相当old thread关于 CMDret ,这是一个基于DLL的功能,可以完全按照我的意愿行事。第一个问题是为它找到一个有效的下载,因为帖子中的所有链接都已经死了。 Google给了我another site,托管 v3.1.2 。尽管似乎有一个较新的( v3.2.1 分别 4d Beta ),我检查了它并测试了一个简单的例子:

msgbox % CMDret(COMSPEC " /C set")
CMDret(CMD) 
{ 
  VarSetCapacity(StrOut, 10000) 
  RetVal := DllCall("cmdret.dll\RunReturn", "str", CMD, "str", StrOut)
  Return, %StrOut%
}

不幸的是,MsgBox什么都没包含。然后我检查了RetVal,其值 0 ;附上的自述文件说:

  

如果函数失败,则返回值为零。

进一步向下,它说:

  

注意:仅32位控制台应用程序目前可以使用   这个DLL版本的CMDret(v3.1.2或更低版本)。需要的电话   command.com可能不会产生任何输出并可能崩溃。避免   这个我已经包含了一个名为“cmdstub.exe”的文件和下载(在   Win9x文件夹)。调用 16位时应使用此文件   控制台应用程序以启用返回输出。

总之,我不确定问题是什么。我的机器运行在64位。但自述文件中的相应条款是否应该单独排除16位系统,还是只包含32位? 如果计算架构可能不是问题,那么可能是什么?

我正在寻找的是以下任何一种:

  1. 我可以解决问题并继续使用v3.1.2吗?
  2. 是否有人可以查看我可以查看的较新版本的工作源(甚至是本地副本)?
  3. 我可以使用另一种方法[库,.ahk代码等]吗? (最好是类似的,因为CMDret看起来很简单)

5 个答案:

答案 0 :(得分:1)

如果您不需要实时输出,可以使用cmd框本身保存自身的文本文件,然后您可以在控制台的PID完成时使用autohotkey检测(使用返回的runwait结果并将输出的文件读入内存。

所以你可以在你的运行命令(只是常规cmd参数)中执行此操作:

ipconfig > myoutput.txt
exit

现在你有一个带有ipconfig输出的文本文件。

OR 你可以做同样的事情,但不是输出到文本文件,你可以输出到剪贴板,如下所示:

ipconfig | clip

然后,由于输出在剪贴板上,您可以轻松地将其抓取到autohotkey。

答案 1 :(得分:1)

这一直困扰着我一段时间 - 最后这种方法有效!

唯一的先决条件是MS sqlcmd.exe,一个名为AHK_Dev的数据库 当然,当您希望使用它时,AHK_DBA会读取该值。

PS。确保用自己的值替换{yourDir}和{yourServer}!

USE AHK_DEV
CREATE TABLE [dbo].[AHK_DOS]([dos_out] [varchar](max) NULL) ON [PRIMARY];
insert into ahk_dos select 'empty'

创建以下脚本...将其命名为dos_out.bat

@echo off
if "%1" == "" ( 
    set v_cmd=""
) else (
    set v_cmd=%1
)
set v_cmd=%v_cmd:~1,-1%
SETLOCAL ENABLEDELAYEDEXPANSION
if "!v_cmd!" == "" (
    set v_cmd="echo ... %COMPUTERNAME% %USERNAME% %DATE% %TIME%"
    set v_cmd=!v_cmd:~1,-1!
)
set v_data=""
FOR /F "usebackq delims=¬" %%i in (`!v_cmd!`) do (
    set v_data="!v_data:~1,-1!%%i~"
)
set q_cmd="set nocount on;update ahk_dos set dos_out=N'!v_data:~1,-1!'"
"{yourDir}\Microsoft SQL Server\90\Tools\Binn\sqlcmd.exe" -S {yourServer} -E -d ahk_dev -Q !q_cmd! -W 
set q_cmd="set nocount on;select len(dos_out) as out_len, dos_out from ahk_dos"
"{yourDir}\Microsoft SQL Server\90\Tools\Binn\sqlcmd.exe" -S {yourServer} -E -d ahk_dev -Q !q_cmd! -W -w 8000
pause

您可以使用...

从AHK运行它
dosCmd2db(c) {
runwait, {yourDir\}dos_out.bat "%c%", , , dospid
msgbox %dospid% closed
}
dosCmd2db("")
dosCmd2db("echo This is a test")
dosCmd2db("dir")

由于每次更新相同的字段,您显然需要在每个字段之间执行某些操作以使此示例有用!

尝试一下,让我知道你是怎么做到的

此致,杰夫

答案 2 :(得分:0)

我发现了一个仅适用于AutoHotKey L 64bit的脚本解决方案:  http://www.autohotkey.com/board/topic/67687-ahkahk-lusing-wsh-to-interact-with-command-line-progs/

稍微玩了一下后,我能够使用DOS Type命令列出我列出的40k文本文件的整个输出。有一个演示,展示了如何与time命令进行交互,如果你需要与dos命令或批处理脚本进行有限的双向交互,那就很好。

答案 3 :(得分:0)

这个脚本StdoutToVar怎么样? 它支持64位控制台。 http://www.autohotkey.com/board/topic/15455-stdouttovar/page-7

答案 4 :(得分:0)

从2019年11月开始,新的推荐的两种操作方式-https://www.autohotkey.com/docs/FAQ.htm#output

  

如何检索命令行操作的输出?

     

测试表明,由于文件缓存,对于较小的输出,临时文件可能会非常快。实际上,如果文件在使用后立即删除,则通常实际上并不会写入磁盘。例如:

RunWait %ComSpec% /c dir > C:\My Temp File.txt
FileRead, VarToContainContents, C:\My Temp File.txt
FileDelete, C:\My Temp File.txt
     

为避免使用临时文件(尤其是在输出较大的情况下),请考虑使用   Shell.Exec()方法,如运行命令示例中所示。

“运行”命令的示例-https://www.autohotkey.com/docs/commands/Run.htm#StdOut

MsgBox % RunWaitOne("dir " A_ScriptDir)


RunWaitOne(command) {
    shell := ComObjCreate("WScript.Shell")
    exec := shell.Exec(ComSpec " /C " command)
    return exec.StdOut.ReadAll()
}

注意:后一种方法(shell.Exec)将导致cmd窗口的快速显示。 您可以通过将这些行放在脚本的顶部来减少其显示的时间,这也将导致闪烁仅在第一次调用cmd命令时发生一次。来自https://autohotkey.com/board/topic/92032-how-to-hide-a-wscript-comspec-window/

;Following 2 lines : the cmd window will flash only once and quickly
DllCall("AllocConsole")
WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr")