| View previous topic :: View next topic |
| Author |
Message |
Orion9

Joined: 01 Jan 2024 Posts: 1104
|
(Separately) Posted: Thu May 14, 2026 00:08 Post subject: |
|
|
| AkulaBig wrote: | | Попробую, как время выберу |
Я просто подумал, что если такая скорость устроит, то нет смысла заморачиваться с чтением из stdout. Выигрыш все-равно будет минимальный. Болван уже дал решение, как считать данные с чужой консоли, но адаптировать это решение под Autorun лень, да и нет смысла. Прирост в скорости и так очевиден — через временный файл работает быстро.
 Hidden text Если чужой процесс уже вывел текст в окно консоли, этот текст находится в экранном буфере (Screen Buffer). Чтобы прочитать его через API, используется AttachConsole в связке с GetStdHandle и ReadConsoleOutputCharacterW.Ниже представлен рабочий скрипт для AutoHotkey v2, который подключается к консоли чужого процесса по его PID, считывает весь текст из его экранного буфера и отключается.
| Code: | #Requires AutoHotkey v2.0
; --- ТЕСТОВЫЙ ЗАПУСК (для демонстрации) ---
; Запустим скрытый cmd.exe, который сделает вывод, чтобы нам было что читать
DetectHiddenWindows(true)
Run(A_ComSpec " /c dir C:\", , "Hide", &targetPID)
WinWait("ahk_pid " targetPID)
Sleep(500) ; Даем команде dir время отработать и заполнить буфер
; --- ОСНОВНОЙ ВЫЗОВ ФУНКЦИИ ---
textOutput := ReadConsoleBufferByPID(targetPID)
MsgBox(textOutput, "Результат чтения чужой консоли")
; Закрываем тестовый процесс
ProcessClose(targetPID)
ExitApp
; --- ФУНКЦИЯ ДЛЯ ЧТЕНИЯ БУФЕРА ЧУЖОГО ПРОЦЕССА ---
ReadConsoleBufferByPID(pid) {
; 1. Отключаемся от нашей текущей консоли (если она была)
DllCall("FreeConsole")
; 2. Привязываемся к консоли чужого процесса по его PID
if !DllCall("AttachConsole", "UInt", pid) {
err := DllCall("GetLastError")
return "Ошибка: Не удалось вызвать AttachConsole. Код ошибки: " err
}
; 3. Получаем дескриптор буфера вывода (STD_OUTPUT_HANDLE = -11)
hStdOut := DllCall("GetStdHandle", "Int", -11, "Ptr")
if (hStdOut == -1 || hStdOut == 0) {
DllCall("FreeConsole")
return "Ошибка: Не удалось получить GetStdHandle."
}
; 4. Получаем размеры экранного буфера консоли
; Структура CONSOLE_SCREEN_BUFFER_INFO занимает 22 байта
csbi := Buffer(22, 0)
if !DllCall("GetConsoleScreenBufferInfo", "Ptr", hStdOut, "Ptr", csbi) {
err := DllCall("GetLastError")
DllCall("FreeConsole")
return "Ошибка: Не удалось получить инфо о буфере. Код ошибки: " err
}
; Читаем размеры буфера из структуры (размер по оси X и Y)
dwSizeX := NumGet(csbi, 0, "Short")
dwSizeY := NumGet(csbi, 2, "Short")
; Общее количество символов для чтения
totalChars := dwSizeX * dwSizeY
if (totalChars <= 0) {
DllCall("FreeConsole")
return ""
}
; 5. Выделяем буфер под текст (2 байта на символ для UTF-16/Unicode)
textBuffer := Buffer((totalChars + 1) * 2, 0)
; Координаты начала чтения (0, 0) — упакованы в 4 байта (DWORD)
dwReadCoord := 0
; 6. Читаем символы из консоли
bytesRead := 0
if !DllCall("ReadConsoleOutputCharacterW",
"Ptr", hStdOut,
"Ptr", textBuffer,
"UInt", totalChars,
"UInt", dwReadCoord,
"UInt*", &bytesRead := 0)
{
err := DllCall("GetLastError")
DllCall("FreeConsole")
return "Ошибка при чтении буфера ReadConsoleOutputCharacter. Код: " err
}
; 7. Обязательно освобождаем чужую консоль
DllCall("FreeConsole")
; 8. Преобразуем буфер в строку AHK
rawText := StrGet(textBuffer, bytesRead, "UTF-16")
; Форматируем текст: разбиваем сплошную строку обратно на строки по ширине консоли
formattedText := ""
Loop dwSizeY {
offset := ((A_Index - 1) * dwSizeX) + 1
line := SubStr(rawText, offset, dwSizeX)
; Убираем лишние пробелы в конце строки, которые консоль добавляет для заполнения экрана
line := RTrim(line, " `t`r`n")
if (line != "")
formattedText .= line "`n"
}
return RTrim(formattedText, "`n")
}
|
Кстати, в Autohotkey можно попробовать считать данные StdOut через ComObject. Не уверен, что получится с ExifTool, но был такой пример в этом топике. Там, кстати, и перевод из досовской кодировки используется. Я вам, наверное, ерунду написал про
| Code: | buf.SetStr(ansi, 0, nSize, "CP:866")
utf8 = buf.GetStr(0, nSize, "CP:65001") |
|
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 552
|
(Separately) Posted: Thu May 14, 2026 09:03 Post subject: |
|
|
Orion9
Нашел, что плагин ExifToolWDX использует такую командную строку:
| Code: |
C:\PortablePrograms\FileManagers\TotalCommanderPortable\Plugins\wlx\ExifToolView\exiftool.exe -charset FileName=UTF8 -stay_open true -@ - |
Нашел описание параметра -@ -:
| Code: |
Примечание. При записи аргументов в файл на диске после записи «-execute\n» сделана задержка до 0,01 секунды, прежде чем exiftool начнёт обработку команды. Этой задержки можно избежать, отправив сигнал CONT процессу exiftool сразу после записи «-execute\n». (Соответствующая задержка отсутствует при записи аргументов через конвейер с «-@ -», поэтому сигнал не требуется при использовании этого метода.) |
И запутался совсем. Как использовать эту опцию? Почему нет временного файла? Не разбирались с этим?
Интересно, что плагин ExifToolView не запускает ExifTool. Похоже сам обрабатывает ее библиотеки. Не будем тревожить автора для разъяснений. Просто для инфы.
Добавлено спустя 50 минут:
| Orion9 wrote: | | нет смысла заморачиваться с чтением из stdout. |
Не в этом дело. В вашем примере не решается главный вопрос wdx-плагина. Однократный запуск ET и многократное считывание данных.
Но ваш код натолкнул меня на мысль:
| Code: |
2. Привязываемся к консоли чужого процесса по его PID
|
Может быть мне надо такое подключение выполнить.
Сейчас я переписал одноразовый запуск ET в au3. Думал это поможет. Но нет, так и не могу получить данные. Возможно это как-раз из-за того, что консоли вывода разные. Хоть я и использую ПИД одной копии ET. Но похоже это не гарантирует, что я данные из ее консоли получаю. И временный файл данных эту проблему никак не решит.
Добавлено спустя 21 минуту:
А ведь кажется можно просто проверить, запущена ли ET и в wdx. Буду тестить. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1104
|
(Separately) Posted: Thu May 14, 2026 13:33 Post subject: |
|
|
| AkulaBig wrote: | | Как использовать эту опцию? Почему нет временного файла? Не разбирались с этим? |
Читал, но написано там скудно, без примеров и хорошего объяснения. Болван реально лучше в этом плане помогает.
Очевидно опция -@ - предназначена для прямой работы с stdin и stdout, а сигнал CONT процессу, видимо, только для линуха.
Но как я писал выше, я бы не стал с этим заморачиваться. Работа через временный файл дает хороший прирост скорости (20-40 раз, и чем больше файлов для обработки, тем выше).
| AkulaBig wrote: | | В вашем примере не решается главный вопрос wdx-плагина. Однократный запуск ET и многократное считывание данных. |
Так я и не стал дальше мучить болвана по озвученной выше причине. Но все можно сделать при желании. Другое дело, что это не решает проблемы Autorun с отображением набора колонок и связанных с этим глюками. Просто с выделенными файлами работает все хорошо. |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|