我有一個程式可以啟動其自身的其他實例。每個實例將標準輸出流重定向到不同的檔案。我遇到以下一系列事件的問題:
- 執行包含指令的 BAT 文件
my_program.exe > output_launcher.txt
- my_program.exe 使用以下命令啟動更多自身
my_program.exe > output_1.txt
實例my_program.exe > output_2.txt
- 原始實例 (
my_program.exe > output_launcher.txt
) 退出,而兩個啟動的實例 (my_program.exe > output_1.txt
和my_program.exe > output_2.txt
) 繼續執行。 - 再次執行 #1 中的相同 BAT 檔案。
- 新實例
my_program.exe > output_launcher.txt
失敗並顯示錯誤“該進程無法存取該文件,因為該文件正在被另一個進程使用。”
如果 #1 中的 BAT 檔案不重定向輸出,我不會收到錯誤;如果兩個啟動的實例在第二次執行 BAT 檔案之前退出,我也不會收到錯誤。
因此,我假設 CMD.EXE 擁有對 output_launcher.txt 檔案的獨佔權限,直到所有子進程完成為止。
首先,這是一個好的假設嗎?
我希望發生的是,當原始實例存在於 #3 中時,CMD.EXE 放棄對 output_launcher.txt 的權利,因為每個子程序都會重新導向到自己的檔案。
重定向標準輸出時可以這樣做嗎?我能想到的最好的替代方案是實際將日誌文件位置作為命令列參數,並直接從我的程式寫入文件,而不是重定向標準輸出。不過,這對我來說會涉及更多的工作,所以如果可能的話,我想避免走這條路。
謝謝!
編輯:第一個實例用於啟動其他實例的實際命令列如下所示start cmd /C "call my_program.exe > output_1.txt"
。然後我將該指令傳遞給「system()」函數(my_program.exe 是用 MSDN C 寫的)。
也許我可以以不同的方式啟動額外的實例,這會有所幫助?
答案1
經過一些簡短的測試後,我想說你的假設似乎是正確的。如果您想驗證這一點,我建議行程駭客。 (頂部有一個「下載」按鈕;要小心,因為廣告顯示的是錯誤的下載連結。)前往 Hacker,尋找句柄或 DLL... (Ctrl-F)
使用它,您可以輕鬆驗證正在使用該文件的內容,並透過重新執行查找,可以驗證文件何時被釋放。
我希望 Process Explorer 也可以做類似的事情。
請注意,您可能最好寫入唯一的文件名...考慮一下:檢查預先存在的文件,而不是第一個子呼叫的output_1.txt和第二個子呼叫的output_2.txt。然後走得更高,這樣您就不會最終覆蓋文件或遇到問題,因為文件正在使用中而無法追加。作業系統和程式語言經常提供產生唯一檔案名稱的功能。
您可能想要寫入許多臨時文件,然後將它們組合成更少的文件。這個想法是否有意義,或者根本沒有意義,可能取決於你的專案以及你處理事情的方式。
如果您有program.exe 的源代碼,則不必執行“program.exe > 檔名”,只需使用“program.exe 檔名”。將程式碼放入程式中以快速寫入文件,然後關閉文件,以便在沒有活動寫入時不再被封鎖。 (更徹底的過程甚至可能執行一些「鎖定」...因為您正在運行程式的多個副本,這實際上可能值得投資。)不要呼叫printf(),而是使用僅呼叫printf 的自定義函數() 如果沒有指定輸出文件,否則寫入文件。然後,您無需每次更改輸出檔案時都更改所有 printf() 調用,而只需更改傳遞給自訂輸出函數的一個變數的值。我知道您說過這可能不是更好的選擇,因為需要花費更多時間。然而,我會讓你知道,在我想出這種方法後,我個人節省了很多時間和精力。我認為這是一個很好的長期解決方案。
或者,考慮使用作業系統的記錄功能。這可以透過從命令列運行命令來完成:在 Unix 中,運行「logger」;在 MS Windows 中,執行事件創建。應該有一些方法可以直接從您選擇的程式語言(MSDN C,正如您所指出的)中做到這一點。如果您的輸出很長,或者您擔心作業系統日誌混亂,這可能不理想。 (我知道有些地方會主動監控作業系統日誌。)
答案2
這是一個合理的假設。
1) 請確認該文件未在任何其他應用程式中開啟。執行此操作的合理方法是在 .bat 應用程式未執行時嘗試重新命名檔案。如果失敗,則表示其他應用程式正在使檔案保持開啟狀態。
2)你能嘗試使用追加操作符>>來代替>並告訴我會發生什麼嗎?