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

时间:2014-07-10 12:03:43

标签: c# .net wcf sockets 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
// ...

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

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

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

1 个答案:

答案 0 :(得分:5)

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

如果您可以更好地控制对WSASocket的调用,则可能会传递WSA_FLAG_NO_HANDLE_INHERIT标志,但这在WCF内部很难实现。以下是其他几个选项:

选项#1:Call CreateProcess yourself并为FALSE传递bInheritHandles

选项#2:在设置WCF(或任何其他套接字)之前创建一个帮助程序进程。 Communicate with it via named pipes。从此帮助程序而不是从主进程启动子进程。