我使用Process.Start来启动批处理文件.批处理文件使用"START"命令并行启动多个程序然后退出.
批处理文件完成后,Process.HasExited变为true,Process.ExitCode包含正确的退出代码.
但是当我调用Process.WaitForExit()时,它会挂起/永不返回.
下面的代码演示了这个问题.它创建一个批处理文件,启动它然后打印:
Process is still running...
Batch file is done!
Process has exited. Exit code: 123
Calling WaitForExit()...
Run Code Online (Sandbox Code Playgroud)
然后它应该打印:
WaitForExit returned.
Run Code Online (Sandbox Code Playgroud)
...但它永远不会(尽管HasExited是真的,我们已经有了一个ExitCode).
open System.IO
open System.Diagnostics
open System.Threading
let foobat = """
START ping -t localhost
START ping -t google.com
ECHO Batch file is done!
EXIT /B 123
"""
File.WriteAllText("foo.bat", foobat)
use p = new Process(StartInfo = ProcessStartInfo("foo.bat",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true))
let onOutput = DataReceivedEventHandler(fun _ args -> printfn "%s" args.Data)
p.OutputDataReceived.AddHandler …Run Code Online (Sandbox Code Playgroud) 我有一个脚本a.cmd调用另一个脚本b.cmd,并重定向其输出.被调用的脚本,启动永不终止的可执行文件.可执行文件的输出重定向到其自己的日志文件.简化代码:
a.cmd:
[1] @ECHO OFF
[2] SET LOG_FILE_NAME="log.txt"
[3] REM Start the b.cmd redirecting all output
[4] CALL b.cmd >> %LOG_FILE_NAME% 2>&1
[5] ECHO returned to a.cmd >> %LOG_FILE_NAME% 2>&1
[6] EXIT /B 0
Run Code Online (Sandbox Code Playgroud)
b.cmd:
[1] @ECHO OFF
[2] SET ANOTHER_LOG_FILE_NAME="log2.txt"
[4] ECHO RunForEver.exe redirecting all output
[5] START CMD /C "RunForEver.exe >> %ANOTHER_LOG_FILE_NAME% 2>&1"
[6] ECHO b.cmd execution complete
[7] EXIT /B 0
Run Code Online (Sandbox Code Playgroud)
(为方便起见,添加了行号)
我遇到的问题是b.cmd中的第4行似乎抓住了初始日志文件(LOG_FILE_NAME)上的句柄,因为所有b.cmd输出都被重定向到它,并且在可执行文件(和启动它的cmd正在运行.我没有这个行为,因为我认为只有start命令本身的输出将被重定向到LOG_FILE_NAME日志文件,而实际运行RunForEver.exe可执行文件的另一个进程的输出将被写入ANOTHER_LOG_FILE_NAME.因此,a.cmd中的第5行错误输出,拒绝访问LOG_FILE_NAME.
有人可以解释发生了什么吗?有办法避免这种情况吗?
我尝试从b.cmd中对LOG_FILE_NAME执行输出重定向,但后来我在b.cmd的第2行中得到了拒绝访问错误.
提前致谢!