1 (изменено: equipment66, 2025-04-12 14:16:48)

Тема: AHK v2: захват текста из окна cmd.

Здравствуйте,
Имеется окно командной строки (В данном случае речь идет про консоль управления плеером VLC), из которого надо бы извлечь информацию.
Пробовал при помощи ReadConsoleOutputCharacter, но так и не смог настроить под АНК v2:

#Requires AutoHotkey v2.0
dwProcessId := WinGetID("A")
bResult := DllCall("AttachConsole", "uint", dwProcessId, "int")
hConsole := DllCall("GetStdHandle", "uint", -11, "ptr")
VarSetStrCapacity(&Out, 2000)

bResult := DllCall("ReadConsoleOutputCharacter", "ptr", hConsole, "str", &Out, "uint", 1000, "ptr", 0, "uint*", 0)

ToolTip "ProcessID: " dwProcessId "`nHandle: " hConsole "`nReturn: " bResult "`nOut: " Out "`nErr: " A_LastError, 1300, 30, 5


/*
BOOL WINAPI ReadConsoleOutputCharacter(
  _In_  HANDLE  hConsoleOutput,
  _Out_ LPTSTR  lpCharacter,
  _In_  DWORD   nLength,
  _In_  COORD   dwReadCoord,
  _Out_ LPDWORD lpNumberOfCharsRead
)

Parameters
hConsoleOutput [in]
A handle to the console screen buffer. The handle must have the GENERIC_READ access right. For more information, see Console Buffer Security and Access Rights.

lpCharacter [out]
A pointer to a buffer that receives the characters read from the console screen buffer.

nLength [in]
The number of screen buffer character cells from which to read. The size of the buffer pointed to by the lpCharacter parameter should be nLength * sizeof(TCHAR).

dwReadCoord [in]
The coordinates of the first cell in the console screen buffer from which to read, in characters. The X member of the COORD structure is the column, and the Y member is the row.

lpNumberOfCharsRead [out]
A pointer to a variable that receives the number of characters actually read.

Что я делаю не так, как делать правильно? Есть подозрение, что дело в координатах, но как их задать правильно?
Может есть альтернативные решения?

2

Re: AHK v2: захват текста из окна cmd.

equipment66
Ваша ссылка нерабочая.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK v2: захват текста из окна cmd.

teadrinker

Да, вы правы. Если скопировать в браузер, открывает. Если трансформировать в ссылку - нет.
Переделал в текст.

4

Re: AHK v2: захват текста из окна cmd.

В смысле, не умеете ссылки оформлять?
А что за адрес www.script-coding.com? У нас forum.script-coding.com.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

5

Re: AHK v2: захват текста из окна cmd.

teadrinker

Обижаете. Что имеем, то копируем. Желаете убедится - скриншот прицепил.

Post's attachments

Скриншот 11-04-2025 20.49.14.png 51.01 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

6

Re: AHK v2: захват текста из окна cmd.

А в чём убедиться-то? Что вы адрес неверно указали, видно:
https://i.imgur.com/QRbIjNy.png
Нажмите там кнопку "Войти", и увидите правильный домен.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

7

Re: AHK v2: захват текста из окна cmd.

teadrinker
Ссылки на вход или регистрацию на той странице не активны.
Так понимаю, гугл нагуглил какой-то архив. Да и черт с ним, я ее просто удалю.

8

Re: AHK v2: захват текста из окна cmd.

Да, задача, конечно, неразрешимая.

equipment66 пишет:

консоль управления плеером VLC

Там какая-то особая консоль, или из обычной можно запустить?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

9

Re: AHK v2: захват текста из окна cmd.

teadrinker
Так понимаю, обычная.
Запускается обычной консолью из папки с плеером.
Winspector Spy ее определяет как ConsoleWindowClass, как и вызывающую.

Post's attachments

Скриншот 11-04-2025 22.07.41.png 215.01 kb, file has never been downloaded. 

You don't have the permssions to download the attachments of this post.

10

Re: AHK v2: захват текста из окна cmd.

У меня код из этого поста работает. Немного подправил его:

characterCount := 1000 ; сколько символов всего нужно прочитать

#IfWinActive ahk_class ConsoleWindowClass
1:: MsgBox % ReadConsoleOutput(characterCount)

ReadConsoleOutput(characterCount) {
    WinGet, dwProcessId, PID, A ;окно консоли должно быть активно.
    bResult := DllCall("AttachConsole", "uint", dwProcessId, "int")
    if(!bResult)
    {
        msgbox не удалось подключиться к консоли
        return
    }
    hConsole := DllCall("GetStdHandle", "uint", -11, "ptr")
    if(hConsole==-1)
    {
        msgbox не удалось получить хендл консоли
        return
    }
    VarSetCapacity(Buffer, characterCount * 2, 0) ;консоль должна быть юникодной
    bResult := DllCall("ReadConsoleOutputCharacter", "ptr", hConsole, "ptr", &Buffer, "uint", characterCount, "ptr", 0, "uint*", x, "int")
    if(!bResult)
    {
        msgbox не удалось получить данные
        return
    }
    DllCall("FreeConsole")
    Return StrGet(&Buffer, "UTF-16")
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

11 (изменено: equipment66, 2025-04-12 12:26:22)

Re: AHK v2: захват текста из окна cmd.

teadrinker

Ну, в АНК v2 он не работает:
1:

VarSetStrCapacity(&Buffer, characterCount*2)

   - функция требует референции, а ее к Buffer нельзя применить. Ну, в мануале пишут, что применение этой функции не обязательно.

2: В строке

DllCall("ReadConsoleOutputCharacter", "ptr", hConsole, "ptr", &Buffer, "uint", characterCount, "ptr", 0, "uint*", x, "int")

какая-то путаница с аргументами:

2.1: Вот здесь

"ptr", &Buffer

насколько я понимаю, требуется использовать "str", так как функция возвращает LPTSTR  :
https://learn.microsoft.com/en-us/windo … tcharacter
https://script-coding.com/AutoHotkey/DllCall.html
при смене жалуется на "Error: Expected a String but got a Class."

2.2: для чего используется переменная "x"?  При попытке исполнения получаем  "Error: This global variable has not been assigned a value." То есть, интерпретатор полагает, что х является вводной? Но по документации, так понимаю, в ее должно выводится количество считанных символов?

12

Re: AHK v2: захват текста из окна cmd.

equipment66 пишет:

в АНК v2 он не работает:

А, я не понял, что под v2 нужно. Позже подправлю. Измените язык в заголовке на AHK v2.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

13 (изменено: equipment66, 2025-04-13 12:19:31)

Re: AHK v2: захват текста из окна cmd.

teadrinker

Поправил.

14

Re: AHK v2: захват текста из окна cmd.

На v2 так:

#Requires AutoHotkey v2

characterCount := 1000 ; сколько символов всего нужно прочитать

#HotIf WinActive('ahk_class ConsoleWindowClass')
1:: MsgBox ReadConsoleOutput(characterCount)
#HotIf

ReadConsoleOutput(charCount) {
    static STD_OUTPUT_HANDLE := -11, INVALID_HANDLE_VALUE := -1
    if !DllCall('AttachConsole', 'UInt', WinGetPID('A')) {
        throw OSError()
    }
    hConsole := DllCall('GetStdHandle', 'UInt', STD_OUTPUT_HANDLE, 'Ptr')
    if hConsole == INVALID_HANDLE_VALUE {
        throw OSError()
    }
    VarSetStrCapacity(&text, charCount * 2)
    if !DllCall('ReadConsoleOutputCharacter', 'Ptr', hConsole, 'Str', text,
                                              'UInt', charCount, 'Ptr', 0, 'UInt*', &read := 0) {
        throw OSError()
    }
    DllCall('FreeConsole')
    return text
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

15 (изменено: equipment66, 2025-04-13 13:04:09)

Re: AHK v2: захват текста из окна cmd.

teadrinker
Спасибо.
На Win11 так работает.
А вот на Win10 - нет, при попытке извлечь текст выдает "Error: (6) The handle is invalid".
К стати, обратил внимание, что у меня и Winspector Spy консоли среди процессов не видит.

16

Re: AHK v2: захват текста из окна cmd.

А код на v1 работает?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

17

Re: AHK v2: захват текста из окна cmd.

teadrinker
Вечерком гляну.

18

Re: AHK v2: захват текста из окна cmd.

Если эта ошибка случилась на функции AttachConsole, то это бывает тогда, когда функция не видит консоль у процесса.

learn.microsoft пишет:

If the specified process does not have a console, the error code returned is ERROR_INVALID_HANDLE

Но у меня на Windows 10 работает.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

19 (изменено: equipment66, 2025-04-13 20:08:15)

Re: AHK v2: захват текста из окна cmd.

teadrinker
Проверил обе версии скрипта на 4 машинках:
....................................AHK v1...............AHK v2
WinXP SP3.................не работает..............n/a
Win10.......................не работает...............n/a
Win10 (основной).........работает...........не работает
Win11..........................работает.............работает

Похоже, на разных машинах тот же код может вести себя по разному.

Если эта ошибка случилась на функции AttachConsole, то это бывает тогда, когда функция не видит консоль у процесса.

Но при попытке подключения консоли к процессу ошибок не было.
К тому же, у меня на той же машинке, один работает, другой - нет.
Надо будет попробовать в более развернутом виде потом переписать, авось отловлю что-то.

20

Re: AHK v2: захват текста из окна cmd.

equipment66 пишет:

Но при попытке подключения консоли к процессу ошибок не было.

Так а на какой строке ошибка?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

21 (изменено: equipment66, 2025-04-13 21:58:14)

Re: AHK v2: захват текста из окна cmd.

teadrinker пишет:

Так а на какой строке ошибка?

В этих, в обоих случаях:

 if !DllCall('ReadConsoleOutputCharacter', 'Ptr', hConsole, 'Str', text, 'UInt', charCount, 'Ptr', 0, 'UInt*', &read := 0),
bResult := DllCall("ReadConsoleOutputCharacter", "ptr", hConsole, "ptr", &Buffer, "uint", characterCount, "ptr", 0, "uint*", x, "int")

22

Re: AHK v2: захват текста из окна cmd.

Не особо понятно, в чём может быть проблема, если v1 работает, а v2 нет. Принцип работы не отличается.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23

Re: AHK v2: захват текста из окна cmd.

Понял, в чём косяк второй версии. Если вы установили вторую версию поверх первой, то скрипты запускаются не сами по себе, а их запускает лаунчер, дополнительный скрипт (чтобы выбрать нужный интерпретатор), и там путаница с консолями выходит. Можно прописать в начале перезагрузку, тогда всё будет ок:

if !(DllCall('GetCommandLine', 'Str') ~= ' /restart(?!\S)') {
    Reload
}

Ну, или создать ярлык, где будет прописан путь к интерпретатору.
Вот такой вариант лучше:

#Requires AutoHotkey v2

if !(DllCall('GetCommandLine', 'Str') ~= ' /restart(?!\S)') {
    Reload
}

#HotIf WinActive('ahk_class ConsoleWindowClass')
1:: MsgBox A_Clipboard := ReadConsoleOutput(WinGetPID('A'))
#HotIf

ReadConsoleOutput(PID) {
    static STD_OUTPUT_HANDLE := -11, INVALID_HANDLE_VALUE := -1
    if !DllCall('AttachConsole', 'UInt', PID) {
        throw OSError()
    }
    hConsole := DllCall('GetStdHandle', 'UInt', STD_OUTPUT_HANDLE, 'Ptr')
    if hConsole == INVALID_HANDLE_VALUE {
        throw OSError()
    }
    CONSOLE_SCREEN_BUFFER_INFO := Buffer(24, 0)
    if !DllCall('GetConsoleScreenBufferInfo', 'Ptr', hConsole, 'Ptr', CONSOLE_SCREEN_BUFFER_INFO) {
        throw OSError()
    }
    bufferSize := NumGet(CONSOLE_SCREEN_BUFFER_INFO, 'UInt')
    bufferWidth := bufferSize & 0xFF
    bufferHeight := bufferSize >> 16
    outBuf := Buffer(bufferWidth * bufferHeight * 4, 0)
    NumPut('UInt', bufferSize, readRegion := Buffer(8, 0), 4)
    if !DllCall('ReadConsoleOutput', 'Ptr', hConsole, 'Ptr', outBuf, 'UInt', bufferSize, 'UInt', 0, 'Ptr', readRegion) {
        throw OSError()
    }
    emptyCounter := 0
    Loop bufferHeight {
        lineNum := A_Index - 1
        line := ''
        Loop bufferWidth {
            line .= Chr(NumGet(outBuf, 4 * (A_Index - 1) + lineNum * bufferWidth * 4, 'UShort'))
        }
        text .= RegExReplace(line, '\s+$', '`r`n')
        emptyCounter := (line ~= '^\s*$') ? emptyCounter + 1 : 0
    } until emptyCounter == 5
    DllCall('FreeConsole')
    return RegExReplace(text, '\s*$')
}

Я запускал скрипт не двойным кликом, а из редактора, поэтому у меня проблемы не возникало.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

24 (изменено: equipment66, 2025-04-14 13:35:29)

Re: AHK v2: захват текста из окна cmd.

teadrinker пишет:

Я запускал скрипт не двойным кликом, а из редактора, поэтому у меня проблемы не возникало.

Мать его за ногу, так и есть.
Только у меня на оборот.
На десятке, при запуске двойным кликом, всё работает. Из Sci-Te - только v1.
Вот и разобрались. Надо бы тему поднять. Тем более, у меня Sci-Te на одиннадцатую криво встала, из редактора ни запуск, ни дебаг не работает, а ещё ассоциации работают через раз.

Спасибо!