2014-08-28 115 views
0

这是一个简单的问题,运行时不处理排队的消息。现在,当我将其作为Windows服务运行时,它不会处理私有队列中的消息(使用MSMQ)。MSMQ应用程序作为Windows服务

我试着以我的用户帐户和本地服务运行服务。在这两种情况下,队列中都充满了消息,其中没有一个正在处理。

请注意,Windows服务似乎运行正常:它是关联Wcf服务打开并收听。

只是为了确保它不是权限问题,我授予我可以想到的每个组/用户的完全访问权限。这是处理队列创建和主机初始化的代码。请注意,在这次尝试中,我将用户的本地化命名更改为他们的英文版本。另外请注意,我尝试在所有可能的帐户下安装该服务:我自己以管理员身份运行,LocalSystem,LocalService和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; 
      } 
     } 
    } 
} 

这里是我的服务全面的app.config:

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

下面是重现该问题有点快捷方式:在分布式MSDN上的WCF代码样本,有两涉及客户端/服务器设置的MSMQ样例;我修改了这个示例,将服务器安装为Windows服务。如果运行服务器并启动客户端,则所有消息都应该停留在服务器的队列中,而不会进一步处理。这里是一个链接到该样本:

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

回答

0

真正的问题只是,我试图从一个到Console.ReadLine退出停止服务线程 - 运行的应用程序作为服务时(显然也许)不适用。我的不好,首先提出这个问题,我真的很抱歉。无论如何,所有的答案尝试。

0

夫妇的想法。

  1. 试着让服务像你一样运行,但是作为一个交互式用户。

  2. 配置文件是否在正确的文件夹中?当你运行一个Windows服务,它默认的应用程序域到%SYSDIR%(你可以在OnStart中覆盖)的基本目录

除此之外,我建议你在示踪剂添加和记录什么活动实际上正在发生或附加到调试器处理。

如果您需要重写BaseDir。

System.IO.Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory) 
0

很可能是由于权限。在网络服务下运行的Windows服务或者不具有访问MSMQ队列的权限。你必须提供访问权限。

在开发计算机或测试服务器上尝试此操作,而不是生产。尝试将“所有人”权限授予您正在与之通话的队列,并在具有管理权限的用户下运行该服务。如果它开始处理消息,那么您会知道这是一个供应问题。

然后缩小范围。删除越来越多的权利,看看它是否仍然有效。

还可以做一些记录,看看该服务已正确启动。尝试加载配置设置并记录它们。尝试使用Sysinternals DebugView查看它们或将它们记录到文件中。如果服务正在记录到文件中,并且您看到正确的配置项值被记录,那么您就会知道这里没有问题。

什么我也看到的是,人们认为他们应该访问QUEUENAME/service.svc队列。但这仅适用于IIS托管的WCF服务。

如果我是你,张贴整个配置。你没有提供很多信息,我也看不出配置是否有问题。

+0

对不起在上面的代码本地化用户/组。实际上,我确实给了“每个人”(Tout le monde),网络服务(SERVICERÉSEAU),本地服务等的完全访问权限。我还尝试以我自己的用户身份(以管理员权限)运行服务,作为本地服务,作为本地系统作为网络服务。队列总是保持不变(我删除了它,并且在每次尝试之前都为我所能想到的每个帐户分配了完整权限)。我将编辑我的文章,以包含更多可能对此问题负责的代码。感谢您的答复! – Strav 2014-08-30 02:13:39

+0

如果以编程方式将绑定设置为MSMQ,该怎么办?我觉得它不是使用App.config通过MSMQ来收听,而是使用默认值来收听HTTP 我忘了确切的语法是什么,但它是这样的: _host.AddServiceEndpoint(typeof(MachineCommunication .MachineTypeSpecificInfrastructure.ZeissInfrastructure.IZeissListener) 新NetTcpBinding的(), “SomeName”); 而且在同一个MSMQ队列上也不可能有两个监听器。你们都应该为他们提供自己的队列。从配置中删除一个以进行测试。 – 2014-09-02 13:26:17