3

У меня есть программа, которая запускает другие экземпляры себя. Каждый экземпляр перенаправляет стандартный поток вывода в другой файл. У меня проблема со следующей цепочкой событий:

  1. Выполняется BAT-файл, содержащий команду my_program.exe > output_launcher.txt
  2. my_program.exe запускает больше своих экземпляров, используя команды my_program.exe > output_1.txt и my_program.exe > output_2.txt
  3. Исходный экземпляр (my_program.exe > output_launcher.txt) завершается, пока два запущенных экземпляра (my_program.exe > output_1.txt и my_program.exe > output_2.txt) продолжают выполняться.
  4. Тот же BAT-файл из # 1 выполняется снова.
  5. Новый экземпляр my_program.exe > output_launcher.txt завершается с ошибкой «Процесс не может получить доступ к файлу, поскольку он используется другим процессом».

Я не получаю сообщение об ошибке, если файл BAT из # 1 не перенаправляет вывод, и я не получаю сообщение об ошибке, если два запущенных экземпляра завершают работу до повторного выполнения файла BAT.

Итак, я предполагаю, что CMD.EXE обладает исключительными правами на файл output_launcher.txt, пока все подпроцессы не будут завершены.

Прежде всего, это хорошее предположение?

Я хотел бы, чтобы CMD.EXE отказался от своих прав на файл output_launcher.txt, когда исходный экземпляр существует в # 3, поскольку каждый подпроцесс перенаправляется в свой собственный файл.

Возможно ли это при перенаправлении стандартного вывода? Лучшая альтернатива, которую я могу придумать, - это взять местоположение файла журнала в качестве аргумента командной строки и записать файл непосредственно из моей программы, а не перенаправлять стандартный вывод. Это потребует от меня гораздо больше работы, поэтому я бы хотел избежать этого пути, если это возможно.

Спасибо!

РЕДАКТИРОВАТЬ: фактическая командная строка, которую первый экземпляр использует для запуска дополнительных экземпляров, выглядит как start cmd /C "call my_program.exe > output_1.txt" . Затем я передаю эту команду в функцию "system()" (my_program.exe написан на MSDN C).

Может быть, я мог бы запустить дополнительные экземпляры другим способом, который мог бы помочь?

2 ответа2

1

После небольшого тестирования я бы сказал, что ваше предположение кажется верным. Если вы хотите это проверить, я рекомендую Process Hacker. (В верхней части есть кнопка "Загрузки"; будьте осторожны, поскольку в объявлениях появляются плохие ссылки для загрузки.) Перейти к хакеру, найти дескрипторы или библиотеки DLL ... (Ctrl-F)

Используя это, вы можете легко проверить, что использует файл, и, повторно выполнив поиск, можно проверить, когда файл будет выпущен.

Я ожидаю, что Process Explorer также может сделать это похоже.

Обратите внимание, что вам может быть лучше записать в уникальное имя файла ... учтите это: вместо output_1.txt первый дополнительный вызов и output_2.txt второй дополнительный вызов, проверьте, какие файлы уже существуют. Затем поднимитесь выше, чтобы не перезаписывать файл и не сталкиваться с проблемами, потому что вы не можете добавить, потому что файл используется. Операционные системы и языки программирования часто предоставляют функциональность для генерации уникального имени файла.

Возможно, вы захотите записать много временных файлов, а затем объединить их в меньшее количество файлов. Будет ли эта идея иметь много смысла, или вообще не иметь смысла, может зависеть от вашего проекта и от того, как вы подходите к вещам.

Если у вас есть исходный код для program.exe, вместо запуска «program.exe> filename» просто используйте «program.exe filename». Поместите код в вашу программу для быстрой записи в файл, а затем закройте файл, чтобы он больше не задерживался, когда нет активной записи. (Более тщательный процесс может даже выполнить некоторую "блокировку" ..., так как вы запускаете несколько копий программы, в это, возможно, стоит инвестировать.) Вместо вызова printf () используйте пользовательскую функцию, которая вызывает printf () только в том случае, если не указан выходной файл, в противном случае выполняется запись в файл. Тогда вместо того, чтобы менять все вызовы printf () каждый раз, когда вы изменяете выходной файл, вам просто нужно изменить значение одной переменной, которая передается в вашу пользовательскую функцию вывода. Я знаю, что вы сказали, что это не может быть предпочтительным из-за необходимости уделять больше времени. Тем не менее, я дам вам знать, что я лично сэкономил много времени и сил после того, как пришел к такому подходу. Я считаю это хорошим долгосрочным решением.

Или рассмотрите возможность использования функции ведения журнала операционной системы. Это можно сделать, запустив команду из командной строки: в Unix запустите "logger"; в MS Windows запустите EventCreate. Должны быть способы, с помощью которых вы можете сделать это прямо из выбора языка программирования (MSDN C, как вы заметили). Это может быть неидеально, если ваш вывод длинный, или если вы беспокоитесь о загромождении журналов вашей ОС. (Я знаю, что в некоторых местах ведется активный мониторинг журналов ОС.)

0

Это разумное предположение.

1) Убедитесь, что файл не открыт ни в одном другом приложении. Разумный способ сделать это - попытаться переименовать файлы, когда приложение .bat не запущено. Если это не удается, другое приложение удерживает файл открытым.

2) Можете ли вы попробовать использовать Оператор добавления >> вместо > и скажите мне, что происходит?

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .