4

我正在尝试使用 AutoHotkey 读取 Windows CMD 的标准输出。例如,我想将setAHK 中的控制台命令的输出存储在一个变量中。我已经在不久前实现了它,这让我更加困惑为什么它现在不起作用。在 AHK 论坛中,有一个关于CMDret
的相当的帖子,这是一个基于 DLL 的功能,可以完全按照我的意愿行事。第一个问题是为它找到一个有效的下载,因为帖子中的所有链接都已失效。Google 给了我另一个站点,托管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 看起来很简单)
4

6 回答 6

2

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

所以你可以在你的运行命令中做到这一点(只是一个常规的 cmd 参数):

ipconfig > myoutput.txt
exit

现在您有了一个包含 ipconfig 输出的文本文件。

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

ipconfig | clip

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

于 2013-06-24T20:57:09.760 回答
2

截至 2019 年 11 月,新推荐的 2 种做法 - 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() 方法,如 Run 命令示例中所示。

运行命令示例 - 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")
于 2019-11-14T22:37:59.220 回答
1

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

于 2013-06-29T02:16:25.607 回答
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")

由于每次都在更新同一个字段,您显然需要在每个字段之间做一些事情以使这个示例有用!

试试看,让我知道你的进展如何

问候,杰夫

于 2014-02-21T15:41:36.343 回答
0

我在以下位置找到了适用于 AutoHotKey L 64bit 的仅脚本解决方案: http ://www.autohotkey.com/board/topic/67687-ahkahk-lusing-wsh-to-interact-with-command-line-progs/

在玩了一会儿之后,我能够捕获我使用 DOS 类型命令列出的 40k 文本文件的整个输出。有一个演示展示了如何与 time 命令交互,如果您需要与 dos 命令或批处理脚本进行有限的双向交互,这很好。

于 2013-06-21T12:40:52.040 回答
0

只是对@amynbe 答案的更新。

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 命令时。

您可以在下面执行此操作以隐藏 cmd 并避免闪烁。

MsgBox % RunWaitOne("dir " A_ScriptDir)


RunWaitOne(command) {
  DetectHiddenWindows On
  Run %ComSpec%,, Hide, pid
  WinWait ahk_pid %pid%
  DllCall("AttachConsole", "UInt", pid)

  shell := ComObjCreate("WScript.Shell")
  exec := shell.Exec(ComSpec " /C " command)

  DllCall( "FreeConsole" )
    return exec.StdOut.ReadAll()
}
于 2021-09-27T19:12:43.970 回答