System.Diagnostics.Process存在的问题

一、Process.Start()调用了Win32的CreateProcess()函数,并且参数bInheritHandles设置为了true,这就导致了子进程继承了父进程的Handle。

 

二、由于上述原因导致的问题

     如果父进程用Process.Start()启动了子进程,并使用ChannelServices.RegisterChannel(channel);注册了channel后父进程结束而子进程不结束,接下来再次运行父进程并使用ChannelServices.RegisterChannel(channel);注册了channel时就会出错:

 

      System.Net.Sockets.SocketException: 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。


三、解决方法

     通过P/Invoking直接调用Win32的CreateProcess()函数,并设置bInheritHandles为false。

 

四、例子参见

     http://forums.msdn.microsoft.com/en-US/netfxremoting/thread/6343e5ea-b39e-4a59-aafa-371f042698f6/

 

     我把这个页面中的几个关键帖子拷贝到下面:

 

     帖子1:

 

The problem is that my .NET 1.1 remoted server application will not restart if it has spawned another process that is inherited (startInfo.UseShellExecute = false).  The error when it is started the second time is"Only one usage of each socket address (protocol/network address/port) is normally permitted".  Once the inherited process is stopped the server will restart with not problem.  I cannot seem to find a way to get the remoting server to really let go of the port. 

 

I have created a small application to demostate the problem.  This is not a practical application but it does demostrate the problem. 

1.  Run the application once.  No problem.  The application spawns an command window.

2.  Run the application again.  It crashes.

3.  Close the command window from the previous execution.

4.  Run the application again.  No problems.  New command window is started.

 

Here is the source:

 


using  System;
using  System.Collections;
using  System.Diagnostics;
using  System.Runtime.Remoting;
using  System.Runtime.Remoting.Channels;
using  System.Runtime.Remoting.Channels.Tcp;
using  System.Runtime.Remoting.Lifetime;

 

namespace  ConsoleApplication2
{
   
class  Class1 : MarshalByRefObject
   {
      
public   override   object  InitializeLifetimeService()
      {
         
return   base .InitializeLifetimeService ();
      }

      
public   int  GetVersion()
      {
         
return   5 ;
      }

      [STAThread]
      
static   void  Main( string [] args)
      {
         
//  Create the channel
         BinaryServerFormatterSinkProvider serverProv  =   new  BinaryServerFormatterSinkProvider();
         serverProv.TypeFilterLevel 
=  System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
         BinaryClientFormatterSinkProvider clientProv 
=   new  BinaryClientFormatterSinkProvider();
         IDictionary props 
=   new  Hashtable();
         props[
" name " =   " TCP1 " ;
         props[
" timeout " =   5000 ;
         props[
" port " =   4100 ;
         props[
" exclusiveAddressUse " =   false ;
         TcpChannel channel 
=   new  TcpChannel(props, clientProv, serverProv);
         ChannelServices.RegisterChannel(channel);

 

         Class1 class1 
=   new  Class1();
         RemotingServices.Marshal(class1, 
" class1 " );

 

         ProcessStartInfo startInfo 
=   new  ProcessStartInfo( " cmd.exe " );
         startInfo.UseShellExecute 
=   false ;
         Process process 
=  Process.Start(startInfo);

 

         RemotingServices.Disconnect(class1);
         ChannelServices.UnregisterChannel(channel);

         channel 
=   null ;
         class1 
=   null ;
         startInfo 
=   null ;
         process 
=   null ;

         GC.Collect();
         GC.WaitForPendingFinalizers();
      }
   }

}

 


     帖子2:


Sounds like cmd.exe is inheriting the handles of the parent process.  That is normally controlled by the bInheritHandles argument of CreateProcess().  The .NET ProcessInfo class doesn't let you specify whether or not handles are inherited.  And Process.Start() indeed calls CreateProcess() with bInheritHandles = true.  You could try P/Invoking CreateProcess() to override this behavior.

 

 

 

五、在.net下调用CreateProcess()的方法参见http://www.pinvoke.net/default.aspx/kernel32/CreateProcess.html

 

转载于:https://www.cnblogs.com/h2appy/archive/2008/09/09/1287582.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值