96

I'm looking for minimal example of WCF Named Pipes (I expect two minimal applications, server and client, which can communicate via a named pipe.)

Microsoft has the briliant article Getting Started Tutorial that describes WCF via HTTP, and I'm looking for something similar about WCF and named pipes.

I've found several posts in the Internet, but they are a little bit "advanced". I need something minimal, only mandatory functionality, so I can add my code and get the application working.

How do I replace that to use a named pipe?

<endpoint address="http://localhost:8000/ServiceModelSamples/Service/CalculatorService"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ICalculator"
    contract="ICalculator" name="WSHttpBinding_ICalculator">
    <identity>
        <userPrincipalName value="OlegPc\Oleg" />
    </identity>
</endpoint>

How do I replace that to use a named pipe?

// Step 1 of the address configuration procedure: Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8000/ServiceModelSamples/Service");

// Step 2 of the hosting procedure: Create ServiceHost
ServiceHost selfHost = new ServiceHost(typeof(CalculatorService), baseAddress);

try
{
    // Step 3 of the hosting procedure: Add a service endpoint.
    selfHost.AddServiceEndpoint(
        typeof(ICalculator),
        new WSHttpBinding(),
        "CalculatorService");

    // Step 4 of the hosting procedure: Enable metadata exchange.
    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
    smb.HttpGetEnabled = true;
    selfHost.Description.Behaviors.Add(smb);

    // Step 5 of the hosting procedure: Start (and then stop) the service.
    selfHost.Open();
    Console.WriteLine("The service is ready.");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.WriteLine();
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    selfHost.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine("An exception occurred: {0}", ce.Message);
    selfHost.Abort();
}

How do I generate a client to use a named pipe?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Oleg Vazhnev
  • 23,239
  • 54
  • 171
  • 305
  • 1
    have you looked at http://stackoverflow.com/questions/184878/expose-a-wcf-service-through-a-named-pipes-binding? – Christoph Sep 08 '11 at 20:05

4 Answers4

83

I just found this excellent little tutorial. broken link (Cached version)

I also followed Microsoft's tutorial which is nice, but I only needed pipes as well.

As you can see, you don't need configuration files and all that messy stuff.

By the way, he uses both HTTP and pipes. Just remove all code lines related to HTTP, and you'll get a pure pipe example.

Juan
  • 15,274
  • 23
  • 105
  • 187
  • 2
    Thanks! Also, when trying to build a service that uses the web.config for its configuration instead of hardcoded config, see this microsoft example: http://msdn.microsoft.com/en-us/library/ms752253.aspx – Nullius Jul 26 '13 at 13:11
  • 3
    The link doesn't work, is the tutorial anywhere else? – user1069816 Jul 21 '15 at 14:22
  • Just spent a while trying to figure out why the "pipe has been ended". Here's my solve on that one, hopefully helps out: https://stackoverflow.com/a/49075797/385273 – Ben Mar 02 '18 at 19:08
63

Try this.

Here is the service part.

[ServiceContract]
public interface IService
{
    [OperationContract]
    void  HelloWorld();
}

public class Service : IService
{
    public void HelloWorld()
    {
        //Hello World
    }
}

Here is the Proxy

public class ServiceProxy : ClientBase<IService>
{
    public ServiceProxy()
        : base(new ServiceEndpoint(ContractDescription.GetContract(typeof(IService)),
            new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/MyAppNameThatNobodyElseWillUse/helloservice")))
    {

    }
    public void InvokeHelloWorld()
    {
        Channel.HelloWorld();
    }
}

And here is the service hosting part.

var serviceHost = new ServiceHost
        (typeof(Service), new Uri[] { new Uri("net.pipe://localhost/MyAppNameThatNobodyElseWillUse") });
    serviceHost.AddServiceEndpoint(typeof(IService), new NetNamedPipeBinding(), "helloservice");
    serviceHost.Open();

    Console.WriteLine("Service started. Available in following endpoints");
    foreach (var serviceEndpoint in serviceHost.Description.Endpoints)
    {
        Console.WriteLine(serviceEndpoint.ListenUri.AbsoluteUri);
    }
Anuraj
  • 18,859
  • 7
  • 53
  • 79
  • This may work, but it's not as flexible as just editing the app.config files for the client and server... – Alan S Jan 09 '12 at 02:49
  • 10
    Nice, since exposing the application details via app.config files is often not desired. – Frank Hileman Sep 03 '14 at 16:13
  • 15
    This is a wonderful example, however, never use a base address of just net.pipe://localhost/. If you do and the machine has any other program that also uses net.pipe://localhost/ then ServiceHost will throw an exception when you open it. Instead, use something unique like net.pipe://localhost/MyAppNameThatNobodyElseWillUse. Hope this helps save someone else some time and frustration! – Doug Clutter May 11 '16 at 12:47
  • This solution works well. Particularly for internal endpoints where having a service reference in config is not necessary. Just keep the contracts - simply the interface definitions - in their own assembly and perhaps the address in config. Its not so likely that the binding will change. – Rob Von Nesselrode Dec 04 '16 at 22:20
  • 2
    I needed to add `/helloservice` to the end of the endpoint address in the proxy. – Mormegil Feb 13 '17 at 14:50
  • Anuraj you should update your answer to add /helloservice to the ServiceProxy endpoint address. – CathalMF Feb 20 '17 at 09:27
  • How to use multiple service endpoints with a single ClientProxy. There must be a way to use multiple endpoints without defining multiple instances of ClientProxy for every one of them. – thunderbird May 01 '18 at 05:40
16

Check out my highly simplified Echo example: It is designed to use basic HTTP communication, but it can easily be modified to use named pipes by editing the app.config files for the client and server. Make the following changes:

Edit the server's app.config file, removing or commenting out the http baseAddress entry and adding a new baseAddress entry for the named pipe (called net.pipe). Also, if you don't intend on using HTTP for a communication protocol, make sure the serviceMetadata and serviceDebug is either commented out or deleted:

<configuration>
    <system.serviceModel>
        <services>
            <service name="com.aschneider.examples.wcf.services.EchoService">
                <host>
                    <baseAddresses>
                        <add baseAddress="net.pipe://localhost/EchoService"/>
                    </baseAddresses>
                </host>
            </service>
        </services>
        <behaviors>
            <serviceBehaviors></serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

Edit the client's app.config file so that the basicHttpBinding is either commented out or deleted and a netNamedPipeBinding entry is added. You will also need to change the endpoint entry to use the pipe:

<configuration>
    <system.serviceModel>
        <bindings>
            <netNamedPipeBinding>
                <binding name="NetNamedPipeBinding_IEchoService"/>
            </netNamedPipeBinding>
        </bindings>
        <client>
            <endpoint address              = "net.pipe://localhost/EchoService"
                      binding              = "netNamedPipeBinding"
                      bindingConfiguration = "NetNamedPipeBinding_IEchoService"
                      contract             = "EchoServiceReference.IEchoService"
                      name                 = "NetNamedPipeBinding_IEchoService"/>
        </client>
    </system.serviceModel>
</configuration>

The above example will only run with named pipes, but nothing is stopping you from using multiple protocols to run your service. AFAIK, you should be able to have a server run a service using both named pipes and HTTP (as well as other protocols).

Also, the binding in the client's app.config file is highly simplified. There are many different parameters you can adjust, aside from just specifying the baseAddress...

VoteCoffee
  • 4,692
  • 1
  • 41
  • 44
Alan S
  • 457
  • 4
  • 8
3

I created this simple example from different search results on the internet.

public static ServiceHost CreateServiceHost(Type serviceInterface, Type implementation)
{
  //Create base address
  string baseAddress = "net.pipe://localhost/MyService";

  ServiceHost serviceHost = new ServiceHost(implementation, new Uri(baseAddress));

  //Net named pipe
  NetNamedPipeBinding binding = new NetNamedPipeBinding { MaxReceivedMessageSize = 2147483647 };
  serviceHost.AddServiceEndpoint(serviceInterface, binding, baseAddress);

  //MEX - Meta data exchange
  ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
  serviceHost.Description.Behaviors.Add(behavior);
  serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexNamedPipeBinding(), baseAddress + "/mex/");

  return serviceHost;
}

Using the above URI I can add a reference in my client to the web service.

Rahbek
  • 1,331
  • 14
  • 9