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

tpe*_*tpe 4 .net c# sockets wcf process

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

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

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

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

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

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

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
// ...
Run Code Online (Sandbox Code Playgroud)

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

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

try
{
    serviceHost.Close(TimeSpan.FromSeconds(4));
}
catch (Exception)
{
    serviceHost.Abort();
}
Run Code Online (Sandbox Code Playgroud)

Dar*_*con 5

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

如果您对调用有更多控制权WSASocket,则可以传递该WSA_FLAG_NO_HANDLE_INHERIT标志,但这在WCF内部很难实现.这里有几个其他选择:

选项#1:自己调用CreateProcess并传递FALSEbInheritHandles.

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