问题:有没有办法快速检查会话0中是否正在托管特定的pipename - 在ServiceHost.Open调用期间是否优先?
情景:
两个进程 PipeHost 和 PipeUser 正在尝试通过名为 PeacePipe 的管道在系统上进行通信。它们不需要以特殊权限启动。
PipeHost 已启动并托管 PeacePipe ,没有任何问题。
PipeUser 已启动并连接到 PeacePipe ,没有任何问题。
PipeUser 尝试通过 PeacePipe 与 PipeHost 进行通信,它会发送消息,但 PipeHost 不会消息看到了什么。
实际上 PipeUser 连接到 DifferentPipeHostInSession0 ,它在托管(或服务)进程中托管具有相同名称(但操作系统创建不同管道)的管道。
背景
当所选的pipename已经被托管时,ServiceHost.Open应抛出AddressAlreadyInUseException。
但是,如果管道在会话0中托管并且您尝试在不同的会话中托管相同的管道,则不会抛出它。由于窗口命名管道通常不会在会话中使用。除会话0中托管的管道外。任何进程都可以连接到此类管道。这可能导致上述情况。
代码:
[ServiceContract]
public interface IService
{
[OperationContract]
void Ping();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, IncludeExceptionDetailInFaults = true)]
public class Service: IService
{
public void Ping()
{
Console.WriteLine("Client Pinged me");
}
}
private static readonly Uri _pipeUri = new Uri("net.pipe://localhost/aaa");
private static readonly Binding _pipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
static void PipeHostTest()
{
ServiceHost serviceHost = new ServiceHost(new Service(), _pipeUri);
serviceHost.AddServiceEndpoint(typeof(IService), _pipeBinding, "");
try
{
//Fail here if same pipe already opened - even in Global space
serviceHost.Open();
Console.WriteLine("OPENED");
}
catch (AddressAlreadyInUseException e)
{
Console.WriteLine(e);
throw;
}
Console.ReadKey();
}
static void PipeClient()
{
ChannelFactory<IService> channelFactory =
new ChannelFactory<IService>(_pipeBinding, new EndpointAddress(_pipeUri));
var proxy = channelFactory.CreateChannel();
proxy.Ping();
}
static void Main(string[] args)
{
if (args.Any())
{
PipeClient();
}
else
{
PipeHostTest();
}
}
在没有参数提升的情况下运行一次,一次不提升参数。两个进程都将托管具有相同名称的管道 - 但这些管道是不同的管道。 然后使用任何参数运行一次。客户端进程将连接到由提升进程托管的管道。
可能的解决方案:
在全局会话new Mutex(true, "Global\\MutexForMyPipeName", out createdNew)
中使用命名的互斥锁,以查看是否有其他进程尝试执行相同操作。
然而,即使管道处于2个不同的会话中,这也不合格。
由于我使用多种绑定类型(net.tcp,net.pipe,net.udp)并且拥有用于创建和托管ServiceHost的单一代码,所以ServiceHost.Open会优先考虑这一点。 NamedPipes是唯一可以允许在没有AddressAlreadyInUseException异常的情况下创建新主机的地方,而地址实际上已经在使用中。