這是一個簡單的問題,運行時不處理排隊的消息。現在,當我將其作爲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
對不起在上面的代碼本地化用戶/組。實際上,我確實給了「每個人」(Tout le monde),網絡服務(SERVICERÉSEAU),本地服務等的完全訪問權限。我還嘗試以我自己的用戶身份(以管理員權限)運行服務,作爲本地服務,作爲本地系統作爲網絡服務。隊列總是保持不變(我刪除了它,並且在每次嘗試之前都爲我所能想到的每個帳戶分配了完整權限)。我將編輯我的文章,以包含更多可能對此問題負責的代碼。感謝您的答覆! – Strav 2014-08-30 02:13:39
如果以編程方式將綁定設置爲MSMQ,該怎麼辦?我覺得它不是使用App.config通過MSMQ來收聽,而是使用默認值來收聽HTTP 我忘了確切的語法是什麼,但它是這樣的: _host.AddServiceEndpoint(typeof(MachineCommunication .MachineTypeSpecificInfrastructure.ZeissInfrastructure.IZeissListener) 新NetTcpBinding的(), 「SomeName」); 而且在同一個MSMQ隊列上也不可能有兩個監聽器。你們都應該爲他們提供自己的隊列。從配置中刪除一個以進行測試。 – 2014-09-02 13:26:17