How can I test to see if a net pipe service is lis

2019-06-22 01:59发布

问题:

How can I test programmatically to see if a particular net pipe service is running and listening, so I don't get a "There was no endpoint listening at..." exception?

So for instance if I have this code:

Uri baseAddress = new Uri("http://localhost/something");
var _ServiceHost = new ServiceHost(typeof(Automation), new Uri[] { baseAddress });
NetNamedPipeBinding nnpb = new NetNamedPipeBinding();
_ServiceHost.AddServiceEndpoint(typeof(IAutomation), nnpb, "ImListening");
_ServiceHost.Open();

I want from another application communicate with http://localhost/something/ImListening but before I want to make sure is listening so I don't get an exception, or is the exception the only way to test this?

回答1:

Listen for the exception. That is the proper way to do it.



回答2:

Exceptions exists for a reason, I would just handle the exception, as long a you handle it the user wont get a cryptic error message, which I guess is what you are trying to avoid.



回答3:

Perhaps is not the best way, but I not found another way to test an endpoint using NetNamedPipe.

I usually do this approach:

    public void IsValid()
    {
        RegisterConfiguration();

        var endPoints = Host.Description.Endpoints;
        if (!endPoints.HasElements())
        {
            throw new NullReferenceException("endpoints (WCF Service).");
        }

        foreach (var item in endPoints)
        {
            var service = new ChannelFactory<ITcoService>(item.Binding, item.Address);
            try
            {
                var client = (IClientChannel)service.CreateChannel();

                try
                {
                    client.Open(TimeSpan.FromSeconds(2));
                    throw new InvalidOperationException(
                        string.Format(
                            "A registration already exists for URI: \"{0}\" (WCF Service is already open in some IChannelListener).",
                            item.Address));
                }
                catch (Exception ex)
                {
                    if (ex is System.ServiceModel.CommunicationObjectFaultedException ||
                        ex is System.ServiceModel.EndpointNotFoundException)
                    {
                        Debug.WriteLine(ex.DumpObject());
                    }
                    else
                    {
                        throw;
                    }
                }
                finally
                {
                    new Action(client.Dispose).InvokeSafe();
                }
            }
            finally
            {
                new Action(service.Close).InvokeSafe();
            }
        }
    }

(sorry the extension methods in this code, InvokeSafe is just a try/catch to execute a Action and HasElements just test if a collection is different of null and empty).



回答4:

If you use ChannelFactory.CreateChannel, it returns a proxy that implements your service's interface without opening a communication channel. However, the proxy also implements IClientChannel, which you can use this to check if the endpoint is up. In my case I also needed to wait for the endpoint to start, so I used a loop with a timeout:

public static Interface CreateOpenChannel<Interface>(Binding protocol, EndpointAddress address, int timeoutMs = 5000)
{
    for (int startTime = Environment.TickCount;;) {
        // a proxy is unusable after comm failure ("faulted" state), so create it within the loop
        Interface proxy = ChannelFactory<Interface>.CreateChannel(protocol, address);
        try {
            ((IClientChannel) proxy).Open();
            return proxy;
        } catch (CommunicationException ex) {
            if (unchecked(Environment.TickCount - startTime) >= timeoutMs)
                throw;
            Thread.Sleep(Math.Min(1000, timeoutMs / 4));
        }
    }
}

This was tested with NetNamedPipeBinding. I am unsure whether this will behave the same way with other bindings, or whether Open() merely opens a connection or also tests the validity of the connection (e.g. whether the host interface matches the client interface).