Search code examples
c#wcfwindows-servicesmsmq

MSMQ Application does not process queued messages when running as Windows Service


This is a straight forward question:

My application behaves correctly when running as a standard program. Now when I run it as a windows service, it does not process the messages in it's private queue (using MSMQ).

I tried running the service as both my user account and as a LOCAL SERVICE. In both cases, the queue just filled up with messages, none of them being processed.

Note that the Windows Service seems to be running correctly: it's associated Wcf service is opened and listening.

Just to make sure it wasn't a permission problem, I granted full access to every group/user I could think of. Here is the code dealing with the queue creation and host initialisation. Note that in this attempt, I changed the localized naming of users to their english counterpart. Also note that I tried to install the service under all possible accounts: my own running as admin, LocalSystem, LocalService and NetworkService.

namespace MachineCommunication.ZeissCMMAdapter
{
    partial class ZeissService : ServiceBase
    {
        public ZeissService()
        {
            InitializeComponent();
        }
        ServiceHost _host = null;

        protected override void OnStart(string[] args)
        {
            Trace.WriteLine("Starting ZeissAdapter Service...");
            string adapterQueueName = ConfigurationManager.AppSettings["adapterQueueName"];

            // Create the transacted MSMQ queue if necessary.

            MessageQueue adapterQueue;
            if (!MessageQueue.Exists(adapterQueueName))
            {
                Trace.WriteLine("Creating Queue: " + adapterQueueName);
                adapterQueue = MessageQueue.Create(adapterQueueName, true);
                adapterQueue.SetPermissions(@"NT AUTHORITY\System", MessageQueueAccessRights.FullControl);
                adapterQueue.SetPermissions(@"ANONYMOUS LOGON", MessageQueueAccessRights.FullControl);
                adapterQueue.SetPermissions(@"Everyone", MessageQueueAccessRights.FullControl);
                adapterQueue.SetPermissions(@"my_user", MessageQueueAccessRights.FullControl);
            }
            else
            {
                Trace.WriteLine("Queue already exists: " + adapterQueueName);
            }


            string machineQueueName = ConfigurationManager.AppSettings["machineQueueName"];
            MessageQueue machineQueue;
            // Create the transacted MSMQ queue if necessary.
            if (!MessageQueue.Exists(machineQueueName))
            {
                Trace.WriteLine("Creating Queue: " + machineQueueName);
                machineQueue = MessageQueue.Create(machineQueueName, true);
                machineQueue.SetPermissions(@"NT AUTHORITY\System", MessageQueueAccessRights.FullControl);
                machineQueue.SetPermissions(@"ANONYMOUS LOGON", MessageQueueAccessRights.FullControl);
                machineQueue.SetPermissions(@"Everyone", MessageQueueAccessRights.FullControl);
                machineQueue.SetPermissions(@"my_user", MessageQueueAccessRights.FullControl);
            }
            using (_host = new ServiceHost(typeof(ZeissAdapterService)))
            {
                _host.Open();
                Console.WriteLine("The service is ready");
                Console.WriteLine("Press <Enter> to stop the service.");
                Console.ReadLine();
            }
        }

        protected override void OnStop()
        {
            try
            {
                Trace.WriteLine("Shutting down Class-A E-mail Service...");
                if (_host != null && _host.State == CommunicationState.Opened)
                {
                    _host.Close();
                    _host = null;
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine("Something went wrong closing the ServiceHost : " + ex.Message);
                throw;
            }
        }
    }
}

Here is the full app.config for my service:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <appSettings>
    <!-- use appSetting to configure MSMQ queue name -->
    <add key="adapterQueueName" value=".\private$\Zeiss/ZeissAdapterService"/>
    <add key="machineQueueName" value=".\private$\Zeiss/ZeissMachineService"/>
  </appSettings>
  <system.serviceModel>
    <services>
      <service name="MachineCommunication.ZeissCMMAdapter.ZeissAdapterService" behaviorConfiguration="DefaultBehavior">
        <!-- Define NetMsmqEndpoint -->
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:12000/" />
          </baseAddresses>
        </host>
        <endpoint address="net.msmq://localhost/private/Zeiss/ZeissAdapterService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.Contracts.AdapterContracts.IAdapterService"/>
        <endpoint address="net.msmq://localhost/private/Zeiss/ZeissMachineService" binding="netMsmqBinding" bindingConfiguration="TransactedBinding" contract="MachineCommunication.MachineTypeSpecificInfrastructure.ZeissInfrastructure.IZeissListener"/>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior">
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceMetadata httpGetEnabled="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <netMsmqBinding>
        <binding name="TransactedBinding" deadLetterQueue="System" useActiveDirectory ="False" useMsmqTracing="True">
          <security mode="None">
            <message clientCredentialType="None"/>
            <transport msmqAuthenticationMode="None" msmqProtectionLevel="None"  />
          </security>
        </binding>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>
  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="sdt"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "SdrConfigExample.e2e" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

Here is a somewhat quick way to reproduce the issue: In the WCF code samples distributed on MSDN, there is a Two-Way MSMQ sample involving a client/server setup; I modified this sample to install the server as a Windows Service. If you run the server and launch the client, all messages should end up stuck in the server's queue without being further processed. Here is a link to that sample:

https://drive.google.com/file/d/0B5-APK5bfBpMUGU2cW5iaV9ybnM/edit?usp=sharing


Solution

  • The real issue was simply that I tried to stop the service thread from exiting with a console.readline - which (obviously perhaps) is not applicable when running an application as a service. My bad, I'm really sorry to have asked the question in the first place. Thanks anyhow for all the answers attempts.