C# MSMQ应用程序在作为Windows服务运行时不处理排队的消息
这是一个直截了当的问题: 作为标准程序运行时,我的应用程序运行正常。现在,当我将其作为windows服务运行时,它不会处理其专用队列中的消息(使用MSMQ) 我尝试将该服务作为我的用户帐户和本地服务运行。在这两种情况下,队列中都充满了消息,没有消息被处理 请注意,Windows服务似乎运行正常:它的关联Wcf服务已打开并正在侦听。 为了确保这不是权限问题,我授予了我能想到的每个组/用户的完全访问权限。下面是处理队列创建和主机初始化的代码。请注意,在这次尝试中,我将用户的本地化命名更改为其英语对应名称。还请注意,我尝试在所有可能的帐户下安装该服务:我自己以管理员、LocalSystem、LocalService和NetworkService的身份运行C# MSMQ应用程序在作为Windows服务运行时不处理排队的消息,c#,wcf,windows-services,msmq,C#,Wcf,Windows Services,Msmq,这是一个直截了当的问题: 作为标准程序运行时,我的应用程序运行正常。现在,当我将其作为windows服务运行时,它不会处理其专用队列中的消息(使用MSMQ) 我尝试将该服务作为我的用户帐户和本地服务运行。在这两种情况下,队列中都充满了消息,没有消息被处理 请注意,Windows服务似乎运行正常:它的关联Wcf服务已打开并正在侦听。 为了确保这不是权限问题,我授予了我能想到的每个组/用户的完全访问权限。下面是处理队列创建和主机初始化的代码。请注意,在这次尝试中,我将用户的本地化命名更改为其英语对应
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;
}
}
}
}
namespace MachineCommunication.ZeissCMMAdapter
{
部分类ZeissService:ServiceBase
{
公共ZeissService()
{
初始化组件();
}
ServiceHost _host=null;
启动时受保护的覆盖无效(字符串[]args)
{
WriteLine(“正在启动ZeissAdapter服务…”);
字符串adapterQueueName=ConfigurationManager.AppSettings[“adapterQueueName”];
//如有必要,创建已处理的MSMQ队列。
消息队列适配器队列;
如果(!MessageQueue.Exists(adapterQueueName))
{
Trace.WriteLine(“创建队列:+adapterQueueName”);
adapterQueue=MessageQueue.Create(adapterQueueName,true);
adapterQueue.SetPermissions(@“NT AUTHORITY\System”,MessageQueueAccessRights.FullControl);
adapterQueue.SetPermissions(@“匿名登录”,MessageQueueAccessRights.FullControl);
adapterQueue.SetPermissions(@“Everyone”,MessageQueueAccessRights.FullControl);
adapterQueue.SetPermissions(@“我的用户”,MessageQueueAccessRights.FullControl);
}
其他的
{
WriteLine(“队列已存在:+adapterQueueName”);
}
字符串machineQueueName=ConfigurationManager.AppSettings[“machineQueueName”];
消息队列机器;
//如有必要,创建已处理的MSMQ队列。
如果(!MessageQueue.Exists(machineQueueName))
{
Trace.WriteLine(“创建队列:+machineQueueName”);
machineQueue=MessageQueue.Create(machineQueueName,true);
machineQueue.SetPermissions(@“NT AUTHORITY\System”,MessageQueueAccessRights.FullControl);
machineQueue.SetPermissions(@“匿名登录”,MessageQueueAccessRights.FullControl);
machineQueue.SetPermissions(@“Everyone”,MessageQueueAccessRights.FullControl);
machineQueue.SetPermissions(@“我的用户”,MessageQueueAccessRights.FullControl);
}
使用(_host=newServiceHost(typeof(ZeissAdapterService)))
{
_host.Open();
Console.WriteLine(“服务准备就绪”);
控制台。WriteLine(“按以停止服务”);
Console.ReadLine();
}
}
受保护的覆盖void OnStop()
{
尝试
{
WriteLine(“关闭A类电子邮件服务…”);
if(_host!=null&&u host.State==CommunicationState.Opened)
{
_host.Close();
_host=null;
}
}
捕获(例外情况除外)
{
WriteLine(“关闭ServiceHost时出错:“+ex.Message”);
投
}
}
}
}
以下是我的服务的完整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>
几点想法
尝试允许服务以您的身份运行,但以交互用户的身份运行
配置文件是否位于正确的文件夹中?运行windows服务时,appdomain的基本目录默认为%SYSDIR%(您可以在OnStart中覆盖该目录)
除此之外,我建议添加一个跟踪程序,并记录实际发生的活动,或使用调试器将其附加到进程
如果需要重写BaseDir
System.IO.Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory)
很可能是因为权利。在网络服务或其他服务下运行的Windows服务无权访问MSMQ队列。您必须提供访问权限
在开发计算机或测试服务器上尝试此操作,而不是在生产环境中。尝试为您正在通话的队列授予“所有人”权限,并在具有管理权限的用户下运行服务。如果它开始处理消息,你就会知道这是一个权利问题
然后缩小范围。删除越来越多的权限以查看它是否仍在工作
还要尝试一些日志记录,看看服务是否正确启动。尝试加载配置设置并记录它们。尝试使用Sysinternals DebugView查看它们或将它们记录到文件中。如果服务正在记录到文件,并且您看到记录了正确的配置项值,您就会知道这不是问题
我还看到,人们认为他们应该访问queuename/service.svc队列。但这仅适用于IIS托管的WCF服务
如果我是你,发布整个配置。您没有提供太多信息,我也看不出配置是否有任何问题。真正的问题只是我试图使用console.readline阻止服务线程退出-这(显然可能)在将应用程序作为服务运行时不适用。我的错,我真的很抱歉问你