Может ли CMD.EXE освободить перенаправленный выходной файл до завершения всех подпроцессов?

Может ли CMD.EXE освободить перенаправленный выходной файл до завершения всех подпроцессов?

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

  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, поскольку каждый подпроцесс перенаправляется в свой собственный файл.

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

Спасибо!

EDIT: Фактическая командная строка, которую первый экземпляр использует для запуска дополнительных экземпляров, выглядит так start cmd /C "call my_program.exe > output_1.txt". Затем я передаю эту команду функции "system()" (my_program.exe написана на MSDN C).

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

решение1

После некоторых кратких тестов я бы сказал, что ваше предположение, похоже, верно. Если вы хотите это проверить, я рекомендуюПроцесс Хакер. (Вверху есть кнопка «Загрузки»; будьте осторожны, так как реклама показывает плохие ссылки для загрузки.) Перейдите в раздел «Хакер», найдите дескрипторы или библиотеки 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 запуститеСобытиеСоздать. Должны быть способы сделать это напрямую из выбранного вами языка программирования (MSDN C, как вы отметили). Это может быть неидеально, если ваш вывод длинный или если вы обеспокоены загромождением журналов ОС. (Я знаю, что в некоторых местах есть активный мониторинг журналов ОС.)

решение2

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

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

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

Связанный контент