[英]MSMQ Application does not process queued messages when running as Windows Service
這是一個簡單的問題:
作為標准程序運行時,我的應用程序行為正確。 現在,當我將其作為Windows服務運行時,它不會處理其專用隊列中的消息(使用MSMQ)。
我嘗試以我的用戶帳戶和本地服務的身份運行該服務。 在這兩種情況下,隊列僅填充了消息,沒有一個被處理。
請注意,Windows服務似乎運行正常:與之關聯的Wcf服務已打開並正在偵聽。
為了確保這不是權限問題,我授予了我能想到的每個組/用戶的完全訪問權限。 這是處理隊列創建和主機初始化的代碼。 請注意,在此嘗試中,我將用戶的本地化命名更改為他們的英語對應名稱。 還要注意,我嘗試在所有可能的帳戶下安裝服務:我自己以admin,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
幾個想法。
嘗試允許該服務以您的身份但以交互用戶身份運行。
配置文件是否在正確的文件夾中? 運行Windows服務時,它會將appdomain的基本目錄默認為%SYSDIR%(您可以在OnStart中覆蓋它)
除此之外,我建議添加一個跟蹤器並記錄實際發生的活動或使用調試器附加到進程的活動。
如果您需要覆蓋BaseDir。
System.IO.Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory)
最有可能是由於權利。 Windows服務在網絡服務下運行,因此沒有訪問MSMQ隊列的權限。 您必須提供訪問權限。
在開發計算機或測試服務器上而不是在生產環境上嘗試此操作。 嘗試為要與之交談的隊列授予“所有人”權限,並在具有管理權限的用戶下運行該服務。 如果它開始處理消息,那么您將知道這是一個權限問題。
然后縮小范圍。 刪除越來越多的權限以查看其是否仍在工作。
還嘗試一些日志記錄,以查看服務是否正確啟動。 嘗試加載配置設置並記錄它們。 嘗試使用Sysinternals DebugView查看它們或將它們記錄到文件中。 如果服務正在記錄到文件,並且您看到正在記錄正確的配置項值,那么您將知道這不是問題。
我還看到人們認為他們應該訪問queuename / service.svc隊列。 但這僅適用於IIS托管的WCF服務。
如果我是您,請發布整個配置。 您沒有提供很多信息,我也看不出配置是否有問題。
真正的問題很簡單,我試圖通過console.readline阻止服務線程退出-(顯然,可能)在將應用程序作為服務運行時不適用。 不好意思,很抱歉首先提出這個問題。 無論如何,感謝您的所有嘗試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.