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

Joined: 01 Jan 2024 Posts: 1110
|
(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: 555
|
(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: 1110
|
(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 |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1110
|
(Separately) Posted: Thu May 14, 2026 18:16 Post subject: |
|
|
Пришлось поставить charset filename=Russian для решения проблемы с русскими именами файлов. Это не решает проблемы юникодных файловых имен при передаче их в качестве параметров Exiftool (там вообще с этим довольно шняжно все), но хоть так.
Это касается только вызова через ProcessExecGetOutput, через -@ arg_file работает все нормально (еще один плюс использования опции -stay_open).
Можно еще ускорить работу через временный файл, заменив Sleep(20) на Sleep(10), это дает эффект. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 555
|
(Separately) Posted: Thu May 14, 2026 21:01 Post subject: |
|
|
| Orion9 wrote: | | Можно еще ускорить работу через временный файл |
В общем я закончил тестирование. Как выше и писал, опция -stay_open совершенно не пригодна для работы в wdx-плагине, так как ET приходится запускать для каждого файла. По крайней мере с файлом аргументов. А про опцию -@ - мы ничего не знаем. Хотя и так понятно, что и она работу не ускоряет, судя по существующему wdx-плагину. Она действует только в пределах текущего файла.
Добавлено спустя 35 минут:
Забыл написать. Для каждого файла требуется новый запуск ET, потому что ПИД у них разный. Так что обращение к одному экземпляру ET не происходит. Конечно можно попытаться обрабатывать список файлов. Ведь в файле аргументов находятся данные о всех файлах в директории. Но не понятно, можно ли так сделать и как обрабатывать это в wdx-плагине. Вот тогда скорость конечно-бы повысилась. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 555
|
(Separately) Posted: Fri May 15, 2026 08:07 Post subject: |
|
|
Orion9
Провел тестирование на скорость. Мой набор файлов, в котором присутствуют запароленные pdf и другие тяжелые файлы, мой алгоритм обрабатывает за 21,5 с. Плагин ExifToolWDX за 3 мин 30 с. Вот что значит обрабатывать с заданным временным интервалом, что требует -stay-open. Один запароленный pdf плагин обрабатывал минуты 2.
Единственное, что поля, которые можно прочитать (даты), плагин вывел, а у меня не выводятся. То-есть просто сразу пропустились. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1110
|
(Separately) Posted: Fri May 15, 2026 12:29 Post subject: |
|
|
| AkulaBig wrote: | | опция -stay_open совершенно не пригодна для работы в wdx-плагине, так как ET приходится запускать для каждого файла. |
Почему? Ничто вроде не мешает запустить exiftool.exe один раз и далее взаимодействовать с ним через файл аргументов.
| AkulaBig wrote: | | А про опцию -@ - мы ничего не знаем. |
Болван тоже не знает?
| AkulaBig wrote: | | Хотя и так понятно, что и она работу не ускоряет, судя по существующему wdx-плагину. Она действует только в пределах текущего файла. |
Это сейчас так. Но плагин не обновлялся 10 лет. Скорее всего автор использовал опцию -stay_open для ускорения, но с последними версиями exiftool.exe она не работает. Для правильной проверки нужно найти версию 10-летней давности. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 555
|
(Separately) Posted: Fri May 15, 2026 12:47 Post subject: |
|
|
Я написал выше. При чтении данных используется ИД процесса. А он разный для каждого запуска в wdx-файле. Запускаем ET, читаем его ИД в коде получения данных. И для каждого обрабатываемого файла в wdx-плагине он разный.
| Orion9 wrote: | | Болван тоже не знает? |
А вы каким пользуетесь? Я каким-то попробовал, сроду столько инфы, сколько выкладываете вы, не получаю.
Ну и я вам данные тестирования скорости плагинов выложил. При использовании -stay_open необходимо задать временной интервал. И это выливается в дичайшее замедление скорости на реальных файлах. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1110
|
(Separately) Posted: Fri May 15, 2026 13:08 Post subject: |
|
|
| AkulaBig wrote: | | Я написал выше. При чтении данных используется ИД процесса. |
Зачем PID, когда взаимодействие с процессом происходит через файл. Один файл для ввода, другой для вывода.
| AkulaBig wrote: | | А вы каким пользуетесь? |
Там сейчас этих болванов развелось, как ... Выбирайте любой — не прогадаете. Я обычный Google AI юзаю. Простой поиск забыл, как кошмарный сон.
 Hidden text Использование значения -@ - (с дефисом в конце) приказывает ExifTool читать список аргументов прямо из стандартного потока ввода (stdin), а не из физического файла на диске.Для реализации этого в AutoHotkey v2 необходимо использовать объект WshShell через COM-интерфейс, так как стандартная функция Run в AHK не умеет напрямую перенаправлять потоки stdin/stdout.🤖 Скрипт AHK v2 с передачей аргументов через StdinЭтот скрипт передает команды в ExifTool в режиме реального времени через оперативную память и сразу возвращает текстовый ответ программы в переменную AHK.
| Code: | #Requires AutoHotkey v2.0
; 1. Конфигурация путей
exiftoolPath := "C:\Windows\exiftool.exe"
targetFile := "C:\Photos\image.jpg"
; 2. Формируем список аргументов (строго по одному на строку)
; Опция -S делает вывод компактным (Тег: Значение)
argsContent :=
(
"-S"
"-Artist=Новый Автор"
"-Copyright=2026 Студия"
)
; Добавляем путь к файлу в конец списка команд
argsContent .= "`n" targetFile
; 3. Запускаем процесс ExifTool с флагами чтения из stdin (-@ -)
shell := ComObject("Wscript.Shell")
exec := shell.Exec('"' exiftoolPath '" -@ -')
; 4. Отправляем команды в поток stdin программы
exec.StdIn.WriteLine(argsContent)
exec.StdIn.Close() ; Закрываем поток, чтобы ExifTool понял, что передача команд окончена, и начал выполнение
; 5. Считываем результат работы (stdout) из ExifTool в переменную
output := exec.StdOut.ReadAll()
; 6. Показываем результат
MsgBox(output, "Результат ExifTool")
|
⚠️ Критические правила при работе с -@ -Закрытие потока: Метод exec.StdIn.Close() обязателен. Пока поток открыт, ExifTool будет бесконечно ждать продолжения ввода и зависнет.Кавычки не нужны: Внутри строки argsContent пути к файлам и текстовые значения с пробелами нельзя оборачивать в кавычки.Символы перевода строки: Каждая опция и её значение должны разделяться стандартным символом новой строки (``n`).Если вам необходимо развить этот скрипт, уточните:Нужно ли обрабатывать несколько файлов по очереди в одном долгоживущем процессе ExifTool (режим -stay_open)?Требуется ли обрабатывать ошибки, возникающие при работе утилиты (чтение потока StdErr)?Какого формата данные вы хотите извлечь из файла (строки, JSON или XML)?
|
|
| 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
|