的过程.开始时不创建子进程(端口句柄继承)

本文关键字:句柄 继承 子进程 过程 开始时 创建 | 更新日期: 2023-09-27 18:12:30

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

WCF提示地址/端口已被使用。如果我在重新启动应用程序之前关闭外部应用程序(不使用WCF或任何套接字),WCF服务就会正常启动。

看起来我的应用程序的套接字句柄以某种方式被新进程"commandLineApp"继承,直到该进程退出才释放。

如何防止其他进程从我的主应用程序继承句柄(或成为子进程?)?目前我使用的是Process。开始启动另一个进程,使用UseShellExecute设置为False,因为我需要设置environmentvariables和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();
}

的过程.开始时不创建子进程(端口句柄继承)

我在上面的评论中是错误的:SO_REUSEADDR只会在句柄被关闭时应用,但似乎套接字句柄确实被子进程继承,并且没有简单的方法来防止这种情况。这似乎是一个非常愚蠢的设计决策,特别是因为有些地方注意到,如果安装了任何lsp,则不能在子进程中使用句柄。

如果你对WSASocket的调用有更多的控制,你可能能够传递WSA_FLAG_NO_HANDLE_INHERIT标志,但这将很难在WCF中完成。以下是其他几个选项:

选项#1:自己调用CreateProcess,将FALSE传递给bInheritHandles

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