Потестировал.
Практически все консольные утилиты отпадают, так как
-- некоторые из них не могу быть созданы в "скрытом" (не знаю как сказать точно) состоянии, то есть при их создании мелькает консольное окно. Перенаправление STDOUT?STDERR не помогают. Пример: PING
-- некоторые консольные утилиты можно создать без мелькания окна, но они создаются так быстро, что происходит коллизия. Пример: HOSTNAME
Графические тоже. Так как практически нет ни одной графической утилиты, которая не рисовала бы интерфейс. HH - исключение, но при ее использовании все-таки возникают коллизии. MSHTA - остается в памяти: надо выгружать вручную.
Остались 2 более-менее подходящие:
SVCHOST - но как посмотрят антивирусы на ее запуск (%windir%\System32\svchost.exe)
WSCRIPT //B - пока единственная более-менее надежная команда, которую можно запустить и которая пока ни разу не привела к коллизиям. Хотя коллизии теоретически возможны и с нею.
Следующий скрипт - z.bat использовался во всех тестах. Менялся только запускаемый процесс (строка set "proc=...").
Скрипт создает временный файл вида tmp.HHMMSS,CC_UID.tmp (HH - часы, MM - минуты, SS - секунды, CC - сотые секунды, UID - номер процесса). Содержимое файла - имя самого файла и первый аргумент, если он передан скрипту.
@echo off
set "proc=wscript.exe //b>nul"
:again
for /f "tokens=1,2 delims==; " %%a in (
'%windir%\System32\Wbem\wmic.exe Process call create "%windir%\System32\%proc%" 2^>nul ^| %windir%\System32\find.exe "ProcessId"'
) do (
set UID=%%b
)
set UTIME=%TIME%
set UTIME=%UTIME: =0%
set UTIME=%UTIME::=%
set tmpfile=tmp.%UTIME%_%UID%.tmp
if exist tmpfile goto again
echo.%1: %tmpfile%>>"%tmpfile%"
Этот скрипт запускает предыдущий многократно. Для упрощения теста использовались утилиты из пакета UnxUtils. Тестовый скрипт вызывается в конвейере z 1 | z 2, 200 раз for /l %%l in ( 1, 1, 200 ). В результате должно быть создано 400 файлов.
@echo off
del tmp*
if not "%~1" == "" goto :EOF
echo.ERRORS
(
for /l %%l in ( 1, 1, 200 ) do @( z 1 | z 2 )
) 2>&1 | sort | uniq -c
echo.SUMMARY
ls -l tmp* | gawk "{ print $5 }" | sort | uniq -c | tee con | gawk "BEGIN { N = 0 } { N += $1 } END { print N }"
А вот тестовые результаты:
hostname.exe>nul
Из 400 файлов вида tmp.HHMMSS,CC_UID.tmp было создано только 353. Из них, 319 файлов размером 27 байт содержат по одной строке (как и должно быть). 34 файла содержат по две строки (54 байта), что значит два процесса писали в один файл. 13 раз конвейер был вызван с ошибкой.
ERRORS
13 The process cannot access the file because it is being used by another p
rocess.
SUMMARY
319 27
34 54
353
wscript.exe //b
Было создано 11, 371 и 18 файлов, соответственно, длиной 26, 27 и 28 байт, содержащие ровно по одной строке. Всего 400 файлов. Различие в размерах связана с длиной строки, обозначающей номер процесса (3, 4 или 5 цифр), которая суммируется с количеством остальных символов.
ERRORS
SUMMARY
11 26
371 27
18 28
400
( 2 * b ) || ! ( 2 * b )