是否在不创建子进程(端口句柄继承)的情况下启动Process.Start? [英] Process.Start without creating a child process (port handle inheritance)?

查看:59
本文介绍了是否在不创建子进程(端口句柄继承)的情况下启动Process.Start?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a WCF service in a self hosted application using TCP bindings. If I start an external process "commandLineApp" from the application, that continues even after my application has closed, I run into problems next time the WCF service is started by my application.

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

WCF says that the address/port is already in use. If I close the external application (that isn't using WCF or any sockets at all) before restarting my application, the WCF service starts just fine.

似乎我的应用程序中的套接字句柄以某种方式被新进程"commandLineApp"继承,并且直到该进程退出后才释放.

It looks like that the socket handles from my application is somehow inherited by the new process "commandLineApp", and not released until that process has exited.

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

How do I prevent the other process from inheriting the handles (or becoming a child process?) from my main application? Currently I'm using Process.Start to launch the other process, using UseShellExecute set to False because I need to set both EnvironmentVarables and RedirectStandardOutput/Error.

我认为,如果我将UseShellExecute = true设置,则会阻止子进程的设置,但是这样我将无法获得所需的全部功能.

I think the child process setup is prevented if I set UseShellExecute = true, but then I don't get all features I need.

有没有解决这个问题的办法?请参见下面的示例代码.

Are there any way around this problem? See example code below.

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命令就不再列出该端口.

Edit - Additional information: Doing "netstat -noa" indicates that the port is used with state LISTEN by the previous PID of the main application, but there is no process with that PID anymore. As soon as I close "commandLineApp", the port isn't listed by the netstat command anymore.

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

WCF services are closed like this before the main application exit:

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

推荐答案

在上述注释中我错了:SO_REUSEADDR仅在关闭句柄的情况下适用,但似乎套接字句柄确实是由子进程继承的,并且在那里防止这种情况绝非易事.这似乎是一个非常愚蠢的设计决定,尤其是因为某些地方指出,如果安装了LSP,则不能在子代中使用该句柄.

I was wrong in the above comment: SO_REUSEADDR would only apply if the handle had been closed, but it seems like socket handles truly are inherited by child processes and there is no easy way to prevent this. This seems like a very stupid design decision, particularly since some places noted that the handle can't be used in the child if any LSPs are installed.

如果您可以更好地控制对 WSASocket 的调用,则可以传递 WSA_FLAG_NO_HANDLE_INHERIT 标志,但这在WCF中很难实现.这是另外两个选项:

If you had more control over the call to WSASocket, you might be able to pass the WSA_FLAG_NO_HANDLE_INHERIT flag, but this is going to be hard to accomplish inside WCF. Here's a couple other options:

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

Option #2: Create a helper process before you set up WCF (or any other sockets). Communicate with it via named pipes. Start the child process from this helper instead of from the main process.

这篇关于是否在不创建子进程(端口句柄继承)的情况下启动Process.Start?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆