Process.Start没有创建子进程(端口句柄inheritance)?

我在使用TCP绑定的自托管应用程序中有一个WCF服务。 如果我从应用程序启动外部进程“commandLineApp”,即使在我的应用程序关闭后仍然继续,我的应用程序下次启动WCF服务时会遇到问题。

WCF说地址/端口已经在使用中。 如果在重新启动应用程序之前关闭外部应用程序(根本不使用WCF或任何套接字),WCF服务就可以正常启动。

看起来我的应用程序中的套接字句柄以某种方式由新进程“commandLineApp”inheritance,并且在该进程退出之前不会被释放。

如何阻止其他进程从我的主应用程序inheritance句柄(或成为子进程?)? 目前我正在使用Process.Start启动其他进程,使用UseShellExecute设置为False,因为我需要设置EnvironmentVarables和RedirectStandardOutput / Error。

我认为如果我设置UseShellExecute = true,则会阻止子进程设置,但是我没有得到我需要的所有function。

有没有解决这个问题的方法? 请参阅下面的示例代码

ProcessStartInfo psi = new ProcessStartInfo(); psi.FileName = "commandLineApp.exe"; psi.Arguments = "/someParameter"; psi.EnvironmentVariables.Add("...", "..."); psi.RedirectStandardOutput = true; psi.RedirectStandardError = true; psi.UseShellExecute = false; Process process = new Process(); process.StartInfo = psi; process.Start(); // Monitor if process with PID = process.Id is running // ... 

编辑 – 附加信息:执行“netstat -noa”表示该端口与主应用程序的先前PID一起使用状态LISTEN,但不再有该PID的进程。 一旦我关闭“commandLineApp”,netstat命令就不再列出该端口了。

在主应用程序退出之前,WCF服务将像这样关闭:

 try { serviceHost.Close(TimeSpan.FromSeconds(4)); } catch (Exception) { serviceHost.Abort(); } 

我在上面的评论中错了:SO_REUSEADDR仅在句柄被关闭时才适用,但看起来套接字句柄确实是由子进程inheritance的,并且没有简单的方法可以防止这种情况。 这似乎是一个非常愚蠢的设计决定,特别是因为有些地方指出,如果安装了任何LSP,则不能在子代中使用句柄。

如果您可以更好地控制对WSASocket的调用,那么您可以传递WSA_FLAG_NO_HANDLE_INHERIT标志,但这在WCF内部很难实现。 这里有几个其他选择:

选项#1: 自己调用CreateProcess并为bInheritHandles传递FALSE

选项#2:在设置WCF(或任何其他套接字)之前创建一个帮助程序进程。 通过命名管道与它通信 。 从此帮助程序而不是从主进程启动子进程。