| View previous topic :: View next topic |
| Author |
Message |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Fri May 22, 2026 08:06 Post subject: |
|
|
Orion9
Разобраться-бы с -@ -. Не понятно, почему в вашем примере на ahk нет параметра -stay_open. Думаю болван ошибся. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Fri May 22, 2026 11:38 Post subject: |
|
|
| AkulaBig wrote: | | Разобраться-бы с -@ - |
Это всего лишь один параметр, а вам придется изучать всю документацию, никуда вы от этого не денетесь
| AkulaBig wrote: | | Не понятно, почему в вашем примере на ahk нет параметра -stay_open. Думаю болван ошибся. |
Нет, в этом случае болван не ошибся. Он сделал пример для одиночного запроса через stdin и получения одиночного ответа через stdout, о чем и написал
| Болван wrote: | Критические правила при работе с -@ -Закрытие потока: Метод exec.StdIn.Close() обязателен. Пока поток открыт, ExifTool будет бесконечно ждать продолжения ввода и зависнет.Кавычки не нужны: Внутри строки argsContent пути к файлам и текстовые значения с пробелами нельзя оборачивать в кавычки.Символы перевода строки: Каждая опция и её значение должны разделяться стандартным символом новой строки (``n`).Если вам необходимо развить этот скрипт, уточните:Нужно ли обрабатывать несколько файлов по очереди в одном долгоживущем процессе ExifTool (режим -stay_open)?Требуется ли обрабатывать ошибки, возникающие при работе утилиты (чтение потока StdErr)?Какого формата данные вы хотите извлечь из файла (строки, JSON или XML)?
https://forum.wincmd.ru/viewpost.php?p=141380 |
А так-то да, он может и чушь иногда написать, нужно быть к этому готовым. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Fri May 22, 2026 11:47 Post subject: |
|
|
| Orion9 wrote: | | никуда вы от этого не денетесь |
Почему вы думаете, что я не изучаю документацию? Но одна строчка про -@ - не особо помогла. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Fri May 22, 2026 12:46 Post subject: |
|
|
| AkulaBig wrote: | | Почему вы думаете, что я не изучаю документацию? |
Я прикалываюсь. Но если вы серьезно хотите в этом разбираться, то от изучения именно всей документации exiftool вам не уйти. Нужно знать все теги, форматы, ключи. А это процесс небыстрый, быстрого результата не будет. Поэтому... я бы бросил
| AkulaBig wrote: | | Но одна строчка про -@ - не особо помогла. |
Самый простой вариант: Google -> Поиск -> "exiftool" -> Режим ИИ:
 Запрос | 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")
необходимо развить этот скрипт, уточните:Нужно ли обрабатывать несколько файлов по очереди в одном долгоживущем процессе ExifTool (режим -stay_open) |
 Ответ | Code: | Использование режима -stay_open — это лучший способ оптимизировать скрипт, если вам нужно обработать множество файлов.Запуск exiftool.exe для каждого отдельного файла создает огромную нагрузку на процессор. Процесс запускается медленно, так как каждый раз заново загружает в память сотни модулей Perl [1]. Режим -stay_open позволяет запустить ExifTool один раз на всё время работы скрипта и мгновенно передавать ему команды через stdin [2].Ниже представлен готовый, развитый шаблон скрипта на AutoHotkey v2.0, который реализует этот профессиональный подход.Скрипт AHK v2.0 с поддержкой -stay_openautohotkey#Requires AutoHotkey v2.0
#SingleInstance Force
; ==============================================================================
; 1. ИНИЦИАЛИЗАЦИЯ ДОЛГОЖИВУЩЕГО ПРОЦЕССА EXIFTOOL
; ==============================================================================
exiftoolPath := "C:\Windows\exiftool.exe"
; Флаги запуска:
; -stay_open True : указывает ExifTool не закрываться после выполнения команды
; -@ - : указывает читать аргументы из стандартного ввода (stdin)
shell := ComObject("Wscript.Shell")
exec := shell.Exec('"' exiftoolPath '" -stay_open True -@ -')
; ==============================================================================
; 2. ПРИМЕР ОБРАБОТКИ ФАЙЛОВ ПО ОЧЕРЕДИ
; ==============================================================================
; Массив файлов для демонстрации последовательной обработки
filesToProcess := [
"C:\Photos\photo1.jpg",
"C:\Photos\photo2.jpg",
"C:\Photos\photo3.jpg"
]
; Перебираем файлы в цикле
for index, targetFile in filesToProcess {
; Формируем пакет аргументов для текущего файла.
; Каждая опция и значение должны быть на новой строке.
cmd := "-Artist=Автор " index "`n"
cmd .= "-Copyright=2026 Студия`n"
cmd .= targetFile "`n" ; Путь к файлу передается в конце пакета команд
cmd .= "-execute" ; ОБЯЗАТЕЛЬНО: сообщает ExifTool, что этот пакет команд пора выполнить
; Отправляем команду в поток stdin
exec.StdIn.WriteLine(cmd)
; Считываем ответ конкретно для этого файла
response := ReadResponse(exec.StdOut)
; Выводим промежуточный результат (можно заменить на Лог-файл или GUI)
MsgBox("Файл " index " обработан!`n`nОтвет ExifTool:`n" response, "Статус обработки")
}
; ==============================================================================
; 3. ПРАВИЛЬНОЕ ЗАКРЫТИЕ EXIFTOOL ПРИ ВЫХОДЕ ИЗ СКРИПТА
; ==============================================================================
; Посылаем команду закрытия перед завершением работы скрипта
ExitRoutine(*) {
global exec
if (exec.Status == 0) { ; Если процесс еще запущен
try {
exec.StdIn.WriteLine("-stay_open`nFalse") ; Корректная команда выхода для ExifTool
exec.StdIn.Close()
}
}
}
OnExit(ExitRoutine)
ExitApp()
; ==============================================================================
; ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
; ==============================================================================
; Функция построчного чтения ответа до маркера окончания выполнения ({ready})
ReadResponse(stdOutStream) {
output := ""
while !stdOutStream.AtEndOfStream {
line := stdOutStream.ReadLine()
; ExifTool по умолчанию выводит "{ready}" на новой строке после завершения -execute
if (Trim(line) == "{ready}")
break
output .= line "`n"
}
return Trim(output)
}
Используйте код с осторожностью.Как это работает:Флаг -stay_open True: Программа запускается в фоне и "слушает" поток stdin [2].Маркер -execute: ExifTool не начнет обрабатывать файл, пока не увидит эту строку. Она служит разделителем между командами [2].Маркер {ready}: После выполнения команды -execute программа выводит в stdout текст {ready} [2]. Наша функция ReadResponse ждет это слово, чтобы скрипт не завис на чтении пустого потока.Завершение -stay_open False: Строго обязательная команда при закрытии скрипта, иначе скрытый процесс exiftool.exe останется "висеть" в Диспетчере задач Windows [2].Чтобы мы могли развить этот скрипт под вашу реальную задачу, ответьте:Откуда скрипт будет брать файлы (выбор папки целиком, выделенные файлы в Проводнике или просто Drag-and-Drop на окно скрипта)?Нужно ли делать фильтрацию по расширениям (например, обрабатывать только .jpg и .mp4, игнорируя .txt)?Требуется ли выводить прогресс-бар или общее окно логов вместо назойливых MsgBox? |
И т.д. пока болван не треснет
Быстрее бы уже Loopback или кто-нибудь научил болвана понимать язык Autorun — вот тогда мы заживём  |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Fri May 22, 2026 13:01 Post subject: |
|
|
| Orion9 wrote: | | И т.д. пока болван не треснет |
У меня толком ничего не получается. Составлять правильно запрос тоже надо уметь. Собственно простой поиск тоже не мало инфы выдает. Но с ИИ не сравнить. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Fri May 22, 2026 13:13 Post subject: |
|
|
| AkulaBig wrote: | | Составлять правильно запрос тоже надо уметь. |
Да бросьте вы. Болван заводится с полпинка понимает с полуслова
 Запрос расскажи подробнее об опции -@- в exiftool и об устройстве stdin stdout
 Ответ | Code: | Опция -@ и механизмы stdin/stdout — это фундамент, на котором строится скоростная и автоматизированная работа с ExifTool. Без них обработка тысяч файлов превращается в кошмар для процессора.
Разберем детально обе составляющие.
------------------------------
## 1. Что такое stdin и stdout простыми словами
В операционных системах (Windows, Linux, macOS) каждый запускаемый консольный процесс по умолчанию получает три стандартных потока данных (или «трубы»):
1. stdin (Standard Input / Стандартный ввод) — поток, через который программа принимает текстовые данные. Обычно туда попадает то, что пользователь печатает на клавиатуре в консоли. В автоматизации мы программно «вталкиваем» туда текст из AutoHotkey.
2. stdout (Standard Output / Стандартный вывод) — поток, куда программа выводит результаты своей успешной работы. В консоли этот текст печатается на экране. Скрипт AHK перехватывает этот поток и сохраняет в переменную для анализа.
3. stderr (Standard Error / Стандартная ошибка) — отдельный поток для сообщений об ошибках. Разделение нужно, чтобы ошибки не смешивались с полезными данными (например, при сохранении вывода в файл).
## Почему это важно для ExifTool?
Каждое создание нового процесса exiftool.exe в Windows занимает от 50 до 200 миллисекунд. Если у вас 10 000 фотографий, запуск процесса на каждый файл займет до получаса только на инициализацию.
Используя stdin и stdout, мы запускаем ExifTool один раз, а затем общаемся с ним со скоростью оперативной памяти, передавая команды текстом.
------------------------------
## 2. Опция -@ (Файл аргументов)
Официально опция -@ (читается как «at-знак» или «собака») указывает ExifTool прочитать аргументы командной строки из файла, а не из самой командной строки.
## Классическое использование (с физическим файлом):
Представьте, что у вас есть текстовый файл commands.txt с таким содержимым:
-S
-Artist=Иван Иванов
-Copyright=2026
C:\Photos\image.jpg
Если вы выполните команду exiftool -@ commands.txt, программа откроет этот файл, построчно прочитает параметры и выполнит их точно так же, как если бы вы написали длинную команду вручную.
## Правила синтаксиса внутри файла аргументов:
1. Строго один аргумент на строку. Вы не можете написать -Artist=Иван -Copyright=2026 на одной строчке.
2. Никаких кавычек для экранирования пробелов. В обычной консоли вы обязаны писать -Artist="Иван Иванов", иначе пробел разобьет команду. Внутри файла аргументов кавычки не нужны (и даже вредны), так как разделителем служит сам перенос строки. Пишется просто: -Artist=Иван Иванов.
------------------------------
## 3. Магия связки -@ -
Когда вы пишете дефис после опции: -@ -, вы даете команду:
«ExifTool, читай аргументы не из физического файла на диске, а прямо из потока stdin!»
Программа замирает и начинает ждать, пока ваш скрипт (например, на AutoHotkey) не запишет текстовые строки в её поток ввода.
## Как это работает пошагово на примере вашего скрипта:
graph TD
A[AHK Скрипт] -- WriteLine --> B(Поток stdin)
B --> C[Запущенный ExifTool]
C -- Обработка файла --> C
C -- WriteLine --> D(Поток stdout)
D --> E[AHK Скрипт: ReadLine]
1. Запуск: shell.Exec('exiftool -stay_open True -@ -')
ExifTool запускается, видит -stay_open True (не закрываться после первой задачи) и -@ - (слушать поток). Он уходит в режим ожидания.
2. Передача команды: Скрипт отправляет в stdin строки:
-Artist=Новый Автор
C:\Photos\image.jpg
-execute
3. Триггер -execute: Для ExifTool строка -execute — это сигнал: «Пакет аргументов закончился, выполняй!». Он считывает метаданные или записывает их в файл.
4. Ответ: Выполнив задачу, ExifTool отправляет текстовый результат работы в свой поток stdout. В самом конце ответа он всегда дописывает строку {ready} (это зашито в его логику работы с ключом -stay_open).
5. Ожидание в AHK: Наш скрипт в цикле while читает stdout строка за строкой. Как только скрипт видит строку {ready}, он понимает, что ExifTool закончил текущую задачу и вернулся в режим ожидания. Цикл чтения завершается, и скрипт может отправлять команды для следующего файла.
------------------------------
## Главные подводные камни при работе со stdin/stdout
1. Буферизация потоков (Зависание): Если вы забудете отправить команду -execute или не добавите символ переноса строки (\n) в самом конце, ExifTool будет бесконечно ждать продолжения ввода, а ваш скрипт зависнет на попытке прочитать ответ.
2. Кодировка текста: По умолчанию Windows использует кодировку CP1251 или OEM-866 для консоли, а ExifTool ожидает UTF-8 для сохранения интернациональных символов (например, русских букв в именах авторов). При работе через COM-объект Wscript.Shell может потребоваться отправлять текст в правильной кодировке или использовать опцию ExifTool -charset filename=utf8.
Если вы хотите оптимизировать скрипт для обработки папок с файлами, дайте знать — мы можем добавить в него автоматическую кодировку UTF-8, чтобы русские теги (вроде копирайта или авторов) не превращались в "кракозябры".
|
|
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Sat May 23, 2026 10:43 Post subject: |
|
|
Orion9
Забил запрос в Гугл, нажал Режим ИИ. Ничего похожего на ваш ответ. Напишите подробней, как вы ищите. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Sat May 23, 2026 12:08 Post subject: |
|
|
| AkulaBig wrote: | | Ничего похожего на ваш ответ. |
Ответ может быть непохожим, т.к. он зависит от контекcта чата, но в общих чертах должен совпадать.
| AkulaBig wrote: | | Напишите подробней, как вы ищите. |
Так я и написал подробно, куда же еще подробнее. Не знаю, что у вас не получается. Ну попробуйте других болванов, их там сейчас вагон с телегой. Из самых простых и доступных:
https://duck.ai/
https://search.brave.com/ask |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Sat May 23, 2026 12:22 Post subject: |
|
|
Orion9
Вы вроде про Гугл ИИ писали. Я в нем и попробовал. А до этого и в Алисе ИИ пробовал и еще в каком-то. Ладно, спасибо за консультацию. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Sat May 23, 2026 14:10 Post subject: |
|
|
| AkulaBig wrote: | | в Алисе ИИ пробовал |
Loopback + Алиса? Нет...)) Салтычиха такого не выдержит. Она и так себе места в сарайчике не находит, весь сельхозпродукт перевела так скучает по топикстартеру )) |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Sat May 23, 2026 15:38 Post subject: |
|
|
Orion9
Однака, пропал сансей  |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Mon May 25, 2026 06:48 Post subject: |
|
|
Orion9
Наконец-то я разобрался с опцией -@ - и вообще с обработкой потоков. Есть еще проблема с определением наполненности потока. Но пока это не важно. Решил через временную задержку.
А теперь серьезная проблема. Оказывается с потоками можно работать, только если обработку завершать строкой:
| Code: | StdinWrite($iPID, "-stay_open" & @LF & "False" & @LF) |
Собственно как и показано в примерах. Но для wdx-плагина это означает, что exiftool надо запускать каждый раз. ПИД процесса каждый раз новый. Но при этом не требуется завершение процесса функцией ProcessWaitClose. Соответственно скорость становится такая-же, как при запуске каждый раз exiftool.
Может у вас есть какая-нибудь идея, как решить эту проблему? То-есть не выполнять:
| Code: | StdinWrite($iPID, "-stay_open" & @LF & "False" & @LF) |
(Конечно без помощи двух промежуточных файлов, это и сейчас у меня в сборке сделано). |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Mon May 25, 2026 10:13 Post subject: |
|
|
Уф, ну вот и все. Тестирование разных вариантов ExifTool закончено. Все работает с любыми опциями. Вот сводная табличка скорости:
Сравнение скорости работы ExifTool:
| Code: |
1. ExifTool -stay_open $sArgFile $sOutFile - 10 c
2. ExifTool -stay_open -@ - - 20 c
3. ExifTool -stay_open $sArgFile Std - 30 c
4. ExifTool Std - 20 c |
Таким образом самый быстрый вариант через временные файлы. Его и оставляю в сборке. |
|
| Back to top |
|
 |
Orion9

Joined: 01 Jan 2024 Posts: 1155
|
(Separately) Posted: Mon May 25, 2026 13:02 Post subject: |
|
|
| AkulaBig wrote: | | Может у вас есть какая-нибудь идея, как решить эту проблему? |
Не всегда на костылях можно решить проблему, а WinScriptAdv это и есть костыль. | AkulaBig wrote: | | Таким образом самый быстрый вариант через временные файлы |
Это хороший вариант, но не самый быстрый. Через stdin/stdout должно быть быстрее, но через WinScriptAdv это проверить не получится
 Hidden text Почему нельзя просто "перехватить" дескриптор STDIN по PID? В ОС Windows дескрипторы таблиц STDIN / STDOUT формируются строго внутри структуры STARTUPINFO в момент рождения процесса. Windows не позволяет чужому изолированному процессу "на лету" внедриться и подменить системные дескрипторы ввода-вывода стандартными WinAPI вызовами. Из-за этого использование Named Pipes или файлов-аргументов — единственный стабильный способ работать без генерации процесса
Если верить болвану, придется использовать AttachConsole (подключение к чужой консоли) или Named Pipes (именованные каналы), но эти методы тоже приведут к задержкам.
На Autorun можно было попробовать, но лень. Как-то не тянет переводить DllCall для CreateProcess
 Hidden text | Code: | #Requires AutoHotkey v2.0
class ExifToolPipe {
__New(exiftoolPath) {
this.hChildStdInWr := 0
this.hChildStdOutRd := 0
this.hProcess := 0
this.hThread := 0
this.StartProcess(exiftoolPath)
}
StartProcess(exiftoolPath) {
; Настройка атрибутов безопасности для наследования дескрипторов
SA := Buffer(24, 0)
NumPut("UInt", 24, SA, 0) ; nLength
NumPut("Ptr", 0, SA, 8) ; lpSecurityDescriptor
NumPut("Int", 1, SA, 16) ; bInheritHandle
; Создаем Pipe для STDIN (Запись из AHK -> Чтение в ExifTool)
if !DllCall("CreatePipe", "Ptr*", &hChildStdInRd := 0, "Ptr*", &hChildStdInWr := 0, "Ptr", SA, "UInt", 0)
throw OSError()
; Создаем Pipe для STDOUT (Запись из ExifTool -> Чтение в AHK)
if !DllCall("CreatePipe", "Ptr*", &hChildStdOutRd := 0, "Ptr*", &hChildStdOutWr := 0, "Ptr", SA, "UInt", 0) {
DllCall("CloseHandle", "Ptr", hChildStdInRd)
DllCall("CloseHandle", "Ptr", hChildStdInWr)
throw OSError()
}
; Запрещаем наследование нашей (записывающей/читающей) стороны каналов
DllCall("SetHandleInformation", "Ptr", hChildStdInWr, "UInt", 1, "UInt", 0)
DllCall("SetHandleInformation", "Ptr", hChildStdOutRd, "UInt", 1, "UInt", 0)
; Настройка STARTUPINFO
SI := Buffer(A_PtrSize == 8 ? 104 : 68, 0)
NumPut("UInt", SI.Size, SI, 0)
NumPut("UInt", 0x00000100 | 0x00000001, SI, A_PtrSize == 8 ? 60 : 44) ; STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
NumPut("UShort", 0, SI, A_PtrSize == 8 ? 64 : 48) ; SW_HIDE (скрывает окно консоли)
NumPut("Ptr", hChildStdInRd, SI, SI.Size - 3 * A_PtrSize)
NumPut("Ptr", hChildStdOutWr, SI, SI.Size - 2 * A_PtrSize)
NumPut("Ptr", hChildStdOutWr, SI, SI.Size - A_PtrSize) ; Дублируем stdout в stderr
; Настройка PROCESS_INFORMATION
PI := Buffer(A_PtrSize == 8 ? 24 : 16, 0)
; Командная строка запуска
cmdLine := '"' exiftoolPath '" -stay_open True -@ -'
; Флаг CREATE_NO_WINDOW (0x08000000) полностью блокирует создание консольного окна
if !DllCall("CreateProcessW", "Ptr", 0, "Str", cmdLine, "Ptr", 0, "Ptr", 0, "Int", 1, "UInt", 0x08000000, "Ptr", 0, "Ptr", 0, "Ptr", SI, "Ptr", PI) {
; Закрываем все открытые дескрипторы при ошибке
DllCall("CloseHandle", "Ptr", hChildStdInRd), DllCall("CloseHandle", "Ptr", hChildStdInWr)
DllCall("CloseHandle", "Ptr", hChildStdOutRd), DllCall("CloseHandle", "Ptr", hChildStdOutWr)
throw OSError()
}
; Сохраняем нужные дескрипторы в свойствах класса
this.hChildStdInWr := hChildStdInWr
this.hChildStdOutRd := hChildStdOutRd
this.hProcess := NumGet(PI, 0, "Ptr")
this.hThread := NumGet(PI, A_PtrSize, "Ptr")
; Закрываем дескрипторы, которые больше не нужны родительскому процессу
DllCall("CloseHandle", "Ptr", hChildStdInRd)
DllCall("CloseHandle", "Ptr", hChildStdOutWr)
}
; Метод отправки команды (аналог exec.StdIn.WriteLine)
WriteLine(text) {
rawString := text "`r`n"
; ExifTool ожидает UTF-8 или системную кодировку (зависит от настроек, UTF-8 наиболее универсален)
bufLen := StrPut(rawString, "UTF-8")
buf := Buffer(bufLen, 0)
StrPut(rawString, buf, "UTF-8")
; Запись через WinAPI WriteFile
DllCall("WriteFile", "Ptr", this.hChildStdInWr, "Ptr", buf, "UInt", bufLen - 1, "UInt*", &bytesWritten := 0, "Ptr", 0)
}
; Метод чтения ответа (ваш ReadResponse переписанный под WinAPI)
ReadResponse() {
output := ""
lineBuffer := ""
; Буфер для побайтового/посимвольного чтения из пайпа
readBuf := Buffer(1, 0)
while DllCall("ReadFile", "Ptr", this.hChildStdOutRd, "Ptr", readBuf, "UInt", 1, "UInt*", &bytesRead := 0, "Ptr", 0) && bytesRead > 0 {
char := StrGet(readBuf, 1, "CP0") ; Читаем посимвольно в системной кодировке (или UTF-8 при побайтовой сборке)
if (char == "`n") {
line := Trim(lineBuffer, "`r`n")
if (line == "{ready}")
break
output .= line "`n"
lineBuffer := ""
} else {
lineBuffer .= char
}
}
return Trim(output, "`r`n")
}
; Корректное завершение работы процесса
Close() {
if this.hChildStdInWr {
this.WriteLine("-stay_open")
this.WriteLine("False")
DllCall("CloseHandle", "Ptr", this.hChildStdInWr)
this.hChildStdInWr := 0
}
if this.hChildStdOutRd
DllCall("CloseHandle", "Ptr", this.hChildStdOutRd), this.hChildStdOutRd := 0
if this.hProcess
DllCall("CloseHandle", "Ptr", this.hProcess), this.hProcess := 0
if this.hThread
DllCall("CloseHandle", "Ptr", this.hThread), this.hThread := 0
}
__Delete() {
this.Close()
}
}
|
А потом еще избавляться от однобайтового буфера
 Hidden text | Code: | ReadResponse() {
output := ""
remainder := ""
foundReady := false
; Размер буфера 4 КБ (вместо 1 байта)
bufferSize := 4096
readBuf := Buffer(bufferSize, 0)
; Читаем из пайпа блоками по 4096 байт
while DllCall("ReadFile", "Ptr", this.hChildStdOutRd, "Ptr", readBuf, "UInt", bufferSize, "UInt*", &bytesRead := 0, "Ptr", 0) && bytesRead > 0 {
; Преобразуем СРАЗУ ВЕСЬ БЛОК байтов в строку (UTF-8 или CP0 в зависимости от настроек ExifTool)
chunk := StrGet(readBuf, bytesRead, "UTF-8")
; Дописываем остаток строки с прошлого шага и очищаем его
fullText := remainder chunk
remainder := ""
; Разбиваем блок текста на массив строк по символу переноса
lines := StrSplit(fullText, "`n")
; Если блок прервался посередине строки (не заканчивается на `\n`),
; забираем последний кусок в remainder, чтобы склеить его при следующем чтении
if (SubStr(fullText, -1) != "`n") {
remainder := lines.Pop()
}
; Быстро перебираем строки в памяти AHK
for index, line in lines {
cleanLine := Trim(line, "`r")
; Если встретили маркер окончания ответа — фиксируем и выходим
if (cleanLine == "{ready}") {
foundReady := true
break
}
output .= cleanLine "`n"
}
; Если маркер {ready} найден, прекращаем чтение из пайпа
if foundReady
break
}
return Trim(output, "`n")
} |
В общем, нее... Ну его на фиг. Вот если бы Loopback сделал объект ComObject, как в Autohotkey, тогда можно было попробовать, всё свелось бы к нескольким строкам )
| AkulaBig wrote: | | Сравнение скорости работы ExifTool: |
Не совсем понятное сравнение. При разрешении 1920х1080 на панели помещается около 50 файлов. Прирост скорости от опции -stay_open с использованием временных файлов составляет где-то 2000%. Т.е. если без этой опции exitool обрабатывает 50 файлов за 20 сек., то с этой опцией у неё уйдёт на это всего 1 сек.
 Hidden text Win+[ запуск exiftool для каждого файла. Win+] держит процесс открытым и взаимодействует с ним через файл аргументов.
| Code: | SetHotkeyAction /K:W /V:219 TestExiftoolSpeed 0
SetHotkeyAction /K:W /V:221 TestExiftoolSpeed 1
Static sExif = COMMANDER_PATH & "\Plugins\wlx\ExifToolView\exiftool.exe"
Static sExifOut = TEMP & "\exiftool_out.txt", sExifArgs = TEMP & "\exiftool_args.txt"
Func TestExiftoolSpeed(StayOpen)
Local aSel = List(), sFile
Local sPath = RequestCopyDataInfo("SP"), j, files = 0, str
aSel.Text = GetSelectedItems(3, 0)
If StayOpen = 1 And Not ProcessExist("exiftool.exe") Then
FileWrite(sExifArgs, "", "UTF-8 NOBOM")
ShellExec /TT /SW_HIDE %sExif% "-stay_open True -@ ""%sExifArgs%"""
Sleep 100
Local nPID = ProcessGetId("exiftool.exe")
If nPID = 0 Then Return MsgBox("Процесс ExifTool не запущен")
EndIf
T1 = GetUptime()
ShowHint("Обработка выделенного Exiftool.exe")
For j = 0 To aSel.Count - 1
sFile = sPath & aSel[j]
If FileExist(sFile) And Not StrPos(FileGetAttr(sFile), "D") Then
files += 1
str &= ExiftoolInfo(sFile, StayOpen)
EndIf
Next
T2 = Round(GetUptime() - T1, 0) / 1000
ShowHint("Выбрано: " & aSel.Count & auCRLF & _
"Обработано: " & files & auCRLF & _
"-stay_open: " & (StayOpen ? "Да" : "Нет") & auCRLF & _
"Объем данных: " & SizeFormat(StrLen(str), 0, 'B', 2) & auCRLF & _
"Время операции: " & StrFormat("%.3f", T2) & " sec")
Free(aSel)
ClipPut(str)
EndFunc
Func ExiftoolInfo(FileName, StayOpen)
If Not StayOpen Then
ProcessExecGetOutput /C:65001 out %sExif% '-charset filename=Russian -lang ru -G -S "%FileName%"'
Else
If FileExist(sExifOut) Then
DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)
EndIf
Local sArgs = "-G" & auCRLF & _
"-S" & auCRLF & _
"-lang" & auCRLF & _
"ru" & auCRLF & _
"-W+!" & auCRLF & sExifOut & auCRLF & FileName & auCRLF & "-execute" & auCRLF
Static obj = BinaryFile(sExifArgs, "a")
obj.WriteStr(sArgs, "", "UTF-8")
out = "<time-out>"
For i = 1 To 50
If FileExist(sExifOut) Then
out = FileRead(sExifOut, 0, "UTF-8")
DllCall("kernel32.dll\DeleteFileW", "Wstr", sExifOut)
Break
EndIf
Sleep(10)
Next
EndIf
Return out
EndFunc |
И файловые операции не самое слабое здесь звено, их точно бояться не стоит
 Hidden text Testing shows that due to file caching, a temporary file can be very fast for relatively small outputs. In fact, if the file is deleted immediately after use, it often does not actually get written to disk. For example:
| Code: | RunWait A_ComSpec ' /c dir > C:\My Temp File.txt'
VarToContainContents := FileRead("C:\My Temp File.txt")
FileDelete "C:\My Temp File.txt" |
To avoid using a temporary file (especially if the output is large), consider using the Shell.Exec() method as shown in the examples for the Run function.
https://www.autohotkey.com/docs/v2/FAQ.htm#output
А вот от Sleep никуда не деться, он-то как раз и задерживает. 50 файлов по Sleep(10) это целые полсекунды. Взаимодейстие через stdin могло бы теоретически ускорить этот процесс. |
|
| Back to top |
|
 |
AkulaBig
Joined: 03 Dec 2008 Posts: 582
|
(Separately) Posted: Mon May 25, 2026 13:38 Post subject: |
|
|
| Orion9 wrote: | | Не совсем понятное сравнение. |
Потому что мы с вами не можем прийти к общему знаменателю. У вас теоретические выкладки. А у меня практическое применение для пользовательских колонок. Где файлы обрабатываются по одному, а не кучей. И файлы разные, а не подогнанные для тестирования. Вот возьмите конкретный файл и протестируйте, за сколько по нему выведется инфа:
https://www.dropbox.com/scl/fi/yhfooga76m8m880pb4ixw/mwt-2021-proceedings.pdf?rlkey=o1hfz5x65svzr9e2mh0q40c98&st=3vnpc0nb&dl=1
| Orion9 wrote: | | Взаимодейстие через stdin могло бы теоретически ускорить этот процесс. |
А в действительности работает медленнее, чем с временными файлами. И без слип тоже не обойтись. Еще и маркер конца данных требуется ввести. | Orion9 wrote: | | И файловые операции не самое слабое здесь звено, их точно бояться не стоит |
А чего их бояться, если они работаю быстрей потока.
| Orion9 wrote: | | Через stdin/stdout должно быть быстрее, но через WinScriptAdv это проверить не получится |
Почему не получится, если у меня получилось и результаты теста я привел?
| Orion9 wrote: | | #Requires AutoHotkey v2.0 |
ahk для меня как ру-борда для вас. Ни одного скрипта мне запустить не удалось. Даже просто ET запустить не удалось. А вот алгоритмы скриптов на ahk помогли понять некоторые тонкости. |
|
| 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
|