title: How to enable remote communication in a C# Windows Service without IIS?
body: <p>I'm becoming increasingly baffled by how difficult it is to create a simple Windows Service with a single remotely invocable method using WCF, and then to call that method from a console application.</p>
  
  <p>I can get as far as creating and installing the Windows Service, but can't find any way to allow a console application to communicate with it.</p>
  
  <p>My goals are as follows:</p>
  
  <ul>
  <li>Allow a Windows Service to self host a WCF service exposing a single method, regardless of what machine it is installed onto.</li>
  <li>Want a console application to be able to invoke that method on a machine whose name is entered by the user.</li>
  <li>Don't want to require the presence of IIS.</li>
  <li>Want to have a clean, simple, short solution. Bonus points for a single page of code or less.</li>
  <li>No pesky overengineered configuration file.</li>
  </ul>
  
  <p>I suppose I can forgo the goal of not having a configuration file if necessary, but I'm pretty determined about the other goals.</p>
  
  <p>Does anyone have any sample code for exposing and consuming the service, beyond pointing me to long and complicated MSDN articles, or books? Your assistance is much appreciated. I promise to eventually read up fully on WCF - all I need is a kick start!</p>
  
  <p>As a point of interest: Are interfaces necessary when defining WCF services? Why are service interfaces so prevelent in WCF example code?</p>
  
  <p>Thanks in advance all,</p>
  
  <p>Nick</p>
  
  <hr>
  
  <p>Thanks to everyone I managed to put together the following solution!</p>
  
  <p>The following infrastructure exposes the Comms class via WCF inside a Windows Service, without needing a configuration file. Metadata publishing is enabled so that we can add a service reference to the related Console Application tester:</p>
  
  <pre><code>namespace AgentService
      {
      using System;
      using System.ServiceModel;
      using System.ServiceModel.Description;
      using System.ServiceProcess;
  
      [ServiceContract]
      public class Comms
          {
          [OperationContract]
          public string GetStatus() { return "Running"; }
          }
  
      public class SelfHost&lt;T&gt;
          {
  
          private ServiceHost host = null;
  
          public void Start()
              {
              var baseAddress = new Uri("http://localhost:8080/AgentService/");
              host = new ServiceHost(typeof(T), baseAddress);
              var behaviour = new ServiceMetadataBehavior() { HttpGetEnabled = true };
              host.Description.Behaviors.Add(behaviour);
              host.Open();
              }
  
          public void Stop() { host.Close(); }
  
          }
  
      public static class Program
          {
  
          public static void Main(string[] args)
              {
              if (args.Length &gt; 0)
                  {
                  var host = new SelfHost&lt;Comms&gt;();
                  host.Start();
                  Console.WriteLine("Press any key to exit...");
                  Console.ReadKey();
                  host.Stop();
                  }
              else
                  {
                  var servicesToRun = new ServiceBase[] { new AgentService() };
                  ServiceBase.Run(servicesToRun);
                  }
              }
  
          }
  
      }
  </code></pre>
  
  <p>The following class comprises the entirety of the tester Console Application. Again, no configuration files required:</p>
  
  <pre><code>namespace Tester
      {
      using System;
      using System.ServiceModel;
      using Tester.Comms;
  
      public class Program
          {
  
          public static void Main(string[] args)
              {
              var comms = new CommsClient(new BasicHttpBinding(),
                                          new EndpointAddress("http://localhost:8080/AgentService/"));
              Console.WriteLine(comms.GetStatus());
              Console.ReadKey();
              }
  
          }
  
      }
  </code></pre>
  
  <p>Thanks for all the help.</p>