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
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.