使用MSMQ的格式化程序出现问题 [英] Problem with formatters using MSMQ
问题描述
我正在构建一个MSMQ应用程序.我正在以文本格式从应用程序写入队列.我的Windows服务从MSMQ提取它,并将其放入数据库中.
但是我在这里面临的问题是消息中包含了MSMQ中的完整字符串.我想知道我在做什么错.
请帮忙.
请找到以下附件文件以供参考.
谢谢
Hi,
I am building a MSMQ application. I am writing from an application to a queue in Text Format . And my windows service picks it up from the MSMQ and puts it in the database.
But the problem I am facing here is that the complete string in the MSMQ is going into the message.. ITs not getting splitted up into the text fomatter pattern. I would like to know what I am doing wrong.
Please help.
Please find the below attached files for reference.
Thanks
MSMQLogDistributor.cs - MSMQ to Database
using System;
using System.Diagnostics;
using System.IO;
using System.Messaging;
using System.Runtime.Serialization;
using System.Security.Principal;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using DTG.Global.Utility.Logging.LogService.Instrumentation;
using DTG.Global.Utility.Logging.LogService.Properties;
using DTG.Global.Object;
using DTG.Global.Utility.Logging;
namespace DTG.Global.Utility.Logging.LogService
{
/// <summary>
/// Receive new log messages from MSMQ and distribute each log entry.
/// </summary>
public class MsmqLogDistributor
{
private bool isCompleted = true;
private bool stopReceiving = false;
private LogWriter logWriter;
private string msmqPath;
private DistributorEventLogger eventLogger;
/// <summary>
/// Setup the queue and the formatter of the messages.
/// </summary>
public MsmqLogDistributor(LogWriter logWriter, string msmqPath,
DistributorEventLogger eventLogger)
{
this.logWriter = logWriter;
this.msmqPath = msmqPath;
this.eventLogger = eventLogger;
}
/// <summary>
/// Read-only property to check if the synchronous receive is completed.
/// </summary>
public virtual bool IsCompleted
{
get { return this.isCompleted; }
}
/// <summary>
/// Instructs the listener to stop receiving messages.
/// </summary>
public virtual bool StopReceiving
{
get { return this.stopReceiving; }
set { this.stopReceiving = value; }
}
/// <summary>
/// Start receiving the message(s) from the queue.
/// The messages will be taken from the queue until the queue is empty.
/// This method is triggered every x seconds. (x is defined in application
configuration file)
/// </summary>
public virtual void CheckForMessages()
{
try
{
ReceiveQueuedMessages();
}
catch (MessageQueueException qex)
{
string errorMsg = LogMessageQueueException(qex.MessageQueueErrorCode, qex);
throw new LoggingException(errorMsg, qex);
}
catch (LoggingException)
{
throw;
}
catch (Exception ex)
{
string errorMsg = string.Format(Resources.Culture,
Resources.MsmqReceiveGeneralError, msmqPath);
this.eventLogger.LogServiceFailure(
errorMsg,
ex,
TraceEventType.Error);
throw new LoggingException(errorMsg, ex);
}
finally
{
this.isCompleted = true;
}
}
/// <summary>
/// This method supports the Enterprise Library infrastructure and is not intended
to be used directly from your code.
/// </summary>
/// <param name="code">The error code.</param>
/// <param name="e">The exception, or null.</param>
/// <returns>The logged message.</returns>
protected string LogMessageQueueException(MessageQueueErrorCode code, Exception e)
{
TraceEventType logType = TraceEventType.Error;
string errorMsg = string.Empty;
if (code == MessageQueueErrorCode.TransactionUsage)
{
errorMsg = string.Format(Resources.Culture,
Resources.MsmqInvalidTransactionUsage, msmqPath);
}
else if (code == MessageQueueErrorCode.IOTimeout)
{
errorMsg = string.Format(Resources.Culture, Resources.MsmqReceiveTimeout,
msmqPath);
logType = TraceEventType.Warning;
}
else if (code == MessageQueueErrorCode.AccessDenied)
{
errorMsg = string.Format(Resources.Culture, Resources.MsmqAccessDenied,
msmqPath, WindowsIdentity.GetCurrent().Name);
}
else
{
errorMsg = string.Format(Resources.Culture, Resources.MsmqReceiveError,
msmqPath);
}
this.eventLogger.LogServiceFailure(
errorMsg,
e,
logType);
return errorMsg;
}
private MessageQueue CreateMessageQueue()
{
MessageQueue messageQueue = new MessageQueue(msmqPath, false, true);
((XmlMessageFormatter)messageQueue.Formatter).TargetTypeNames = new string[] {
"System.String" };
return messageQueue;
}
private bool IsQueueEmpty()
{
bool empty = false;
try
{
using (MessageQueue msmq = CreateMessageQueue())
{
msmq.Peek(new TimeSpan(0));
}
}
catch (MessageQueueException e)
{
if (e.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
empty = true;
}
}
return empty;
}
private void ReceiveQueuedMessages()
{
this.isCompleted = false;
while (!IsQueueEmpty())
{
using (MessageQueue msmq = CreateMessageQueue())
{
System.Messaging.Message message = msmq.Peek();
string serializedEntry = message.Body.ToString();
LogEntry logEntry = new LogEntry();
try
{
logEntry.Message = serializedEntry;
}
catch (FormatException formatException)
{
string logMessage = string.Format(
Resources.Culture,
Resources.ExceptionCouldNotDeserializeMessageFromQueue,
message.Id,
msmq.Path);
this.eventLogger.LogServiceFailure(
logMessage,
formatException,
TraceEventType.Error);
throw new LoggingException(logMessage, formatException);
}
catch (SerializationException serializationException)
{
string logMessage = string.Format(
Resources.Culture,
Resources.ExceptionCouldNotDeserializeMessageFromQueue,
message.Id,
msmq.Path);
this.eventLogger.LogServiceFailure(
logMessage,
serializationException,
TraceEventType.Error);
throw new LoggingException(logMessage, serializationException);
}
if (logEntry != null)
{
msmq.Formatter = new ActiveXMessageFormatter();
//
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(logEntry);
logWriter.Write(logEntry);
//logEntry.Title = "Consumer Service Log";
// logWriter.Write(logEntry);
}
message = msmq.Receive();
if (this.StopReceiving)
{
this.isCompleted = true;
return;
}
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;
using System.ServiceModel;
using System.Configuration;
using System.Xml.Serialization;
using System.Xml;
using System.Web;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Common;
using Microsoft.Practices.EnterpriseLibrary.Data;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Database;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using DTG.Global.Utility;
using DTG.Global.Object;
namespace WCF_MSMQ.MSMQ
{
class Program
{
[STAThread]
static void Main(string[] args)
{
Console.WriteLine();
////LogManager.WriteLog("Error in Rate Shop request.",null,LogManager.LogCategory.Error,LogManager.LogPriority.High, 200, System.Diagnostics.TraceEventType.Error,"RateShop", null);
////LogManager.WriteLog("Message Test",null, "Error", 1, 2223, "Normal", "No Title", null);
////LogManager.WriteLog<String>("Trail Message");
Microsoft.Practices.EnterpriseLibrary.Logging.LogEntry logEntry = new LogEntry();
logEntry.EventId = 100;
logEntry.Priority = 2;
logEntry.Message = "DISTRIBUTOR TEST";
logEntry.Brand = "Thrifty";
logEntry.Farm = "ZTZRBrands";
DTG.Global.Object.Message message = new DTG.Global.Object.Message(5, "error trying to make a res");
Exception exceptionMessage = new Exception("Wrong");
string category = "Information";
int priority = 50;
string title = "CSLOG";
string brand = "ZT";
string farm = "ZTZR";
Dictionary<string, object> properties = new Dictionary<string, object>();
properties.Add("Test String", new Guid());
//LogManager.Log(message, exceptionMessage, category, priority, TraceEventType.Resume, title, brand, farm);
Logger.Write(logEntry);
// Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Write(logEntry);
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="loggingConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
<section name="dataConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data" />
</configSections>
<loggingConfiguration name="Logging Application Block"
tracingEnabled="true"
defaultCategory="General"
logWarningsWhenNoCategoriesMatch="true">
<listeners>
<add name="Formatted EventLog TraceListener"
source="Enterprise Library Logging"
formatter="Text Formatter"
log="Application"
machineName="8W-64217"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
traceOutputOptions="None"
filter="All"
type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
/>
<add name="Msmq TraceListener"
type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.MsmqTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.MsmqTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
traceOutputOptions="None"
filter="All"
queuePath="Formatname:DIRECT=OS:8W-64217\private$\anjana"
formatter="Text Formatter"
messagePriority="Normal"
timeToReachQueue="49710.06:28:15"
timeToBeReceived="49710.06:28:15"
recoverable="false"
useAuthentication="false"
useDeadLetterQueue="false"
useEncryption="false"
transactionType="None" />
</listeners>
<formatters>
<add template="Timestamp: {timestamp}
Message: {message}
Category: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title: {title}
Brand: {brand}
Farm: {farm}
Machine: {machine}
Application Domain: {appDomain}
Process Id: {processId}
Process Name: {processName}
Win32 Thread Id: {win32ThreadId}
Thread Name: {threadName}
Extended Properties: {dictionary({key} - {value}
)}"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All"
name="Error">
<listeners>
<add name="Msmq TraceListener" />
</listeners>
</add>
<add switchValue="All"
name="General">
<listeners>
<add name="Msmq TraceListener" />
</listeners>
</add>
<add switchValue="All"
name="Information">
<listeners>
<add name="Msmq TraceListener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All"
name="All Events" />
<notProcessed switchValue="All"
name="Unprocessed Category" />
<errors switchValue="All"
name="Logging Errors & Warnings">
<listeners>
<add name="Formatted EventLog TraceListener" />
<add name="Msmq TraceListener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
</configuration>
MSMQLogDistributor.APP.CONFIG
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="loggingConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" />
<section name="dataConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data " />
<section name="msmqDistributorSettings"
type="DTG.Global.Utility.Logging.LogService.Configuration.MsmqDistributorSettings, ConsumerService_LoggingService" />
</configSections>
<loggingConfiguration name="Logging Application Block"
tracingEnabled="true"
defaultCategory="General"
logWarningsWhenNoCategoriesMatch="true">
<listeners>
<add databaseInstanceName="LogConnection"
writeLogStoredProcName="WriteLog"
addCategoryStoredProcName="AddCategory"
formatter="Text Formatter"
listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
traceOutputOptions="None"
filter="All"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
name="Database Trace Listener" />
</listeners>
<formatters>
<add template="Timestamp: {timestamp}
Message: {message}
Category: {category}
Priority: {priority}
EventId: {eventid}
Severity: {severity}
Title: {title}
Brand: {brand}
Farm: {farm}
Machine: {machine}
Application Domain: {appDomain}
Process Id: {processId}
Process Name: {processName}
Win32 Thread Id: {win32ThreadId}
Thread Name: {threadName}
Extended Properties: {dictionary({key} - {value}
)}"
type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=null"
name="Text Formatter" />
</formatters>
<categorySources>
<add switchValue="All"
name="General">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</add>
<add switchValue="All"
name="Information">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</add>
<add switchValue="All"
name="Error">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</add>
</categorySources>
<specialSources>
<allEvents switchValue="All"
name="All Events" />
<notProcessed switchValue="All"
name="Unprocessed Category" />
<errors switchValue="All"
name="Logging Errors Warnings">
<listeners>
<add name="Database Trace Listener" />
</listeners>
</errors>
</specialSources>
</loggingConfiguration>
<connectionStrings>
<add name="LogConnection"
connectionString="Database=Logging;Server=XXXXX\XXXXXX;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />
</connectionStrings>
<msmqDistributorSettings msmqPath="Formatname:DIRECT=OS:8W-64217\private$\aXXXX"
queueTimerInterval="50000"
serviceName="Consumer Service Logging Service" />
</configuration>
推荐答案
我尝试了一个像您一样的示例,它在我的本地环境中效果很好.我可以正确获取主体字符串.这是我完整的代码:
使用 使用 使用 使用 使用 使用 使用 使用
命名空间 {
公共 部分 class Form3 : Form
public partial class Form3 : Form
{
公共 Form3()
public Form3()
{
InitializeComponent();
}
MessageQueue mq;
MessageQueue mq;
私有 void Form3_Load(对象发送者, EventArgs e)
private void Form3_Load(object sender, EventArgs e)
{
字符串 strDestQ = @.\ private
string strDestQ = @".\private
\ bian' ; ;\bian";
尝试
try
{
//根据需要创建队列
//create the queue if needed
如果(! MessageQueue .Exists(strDestQ))
if (!MessageQueue.Exists(strDestQ))
消息框.Show(strDestQ + 不存在" );
MessageBox.Show(strDestQ + " doesn't exist");
新 MessageQueue (strDestQ);
mq = new MessageQueue(strDestQ);
新 System.Messaging. XmlMessageFormatter (类型 [] { string )});
mq.Formatter = new System.Messaging.XmlMessageFormatter(new Type[] { typeof(string) });
//构建消息
//build message
消息 m = 新 System.Messaging.
System.Messaging.Message m = new System.Messaging.Message();
"Hello World" ;
m.Label = "Hello World";
"hi david"; ;
m.Body = "hi david";
//发送并关闭队列
// send and close queue
mq.Send(m);
消息框.Show(&消息已发送!" );
MessageBox.Show("Message sent!");
}
捕获(异常例如)
catch (Exception ex)
{
消息框 .Show(ex.ToString());
MessageBox.Show(ex.ToString());
}
}
私有 bool IsQueueEmpty()
private bool IsQueueEmpty()
{
布尔 empty = false ;
bool empty = false;
尝试
try
{
新 TimeSpan (0));
mq.Peek(new TimeSpan(0));
}
捕获( MessageQueueException e)
catch (MessageQueueException e)
{
如果(例如,MessageQueueErrorCode == MessageQueueErrorCode .IOTimeout)
if (e.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout)
{
true ;
empty = true;
}
}
返回为空;
return empty;
}
私有 void button1_Click(对象发送者, EventArgs e)
private void button1_Click(object sender, EventArgs e)
{
同时(!IsQueueEmpty())
while (!IsQueueEmpty())
{
消息 messageReceived = 新 System.Messaging.
System.Messaging.Message messageReceived = new System.Messaging.Message();
messageReceived = mq.Peek();
字符串 body = messageReceived.Body.ToString();
string body = messageReceived.Body.ToString();
消息框 .Show(body);
MessageBox.Show(body);
messageReceived = mq.Receive();
}
}
}
}
看来您的代码是正确的,我建议您逐行调试,然后检测哪个行代码引起了原因.您也可以尝试我的代码. By the way, I would like to point out a code problem in your code, see following code:
using (MessageQueue msmq = CreateMessageQueue())
This line code will run in every loop, this will cause bad performance. We can create a global MessageQueue variable.
If I misunderstood your question, please let me know and provide detailed explanation. Thanks.
Best regards,
Guang-Ming Bian - MSFT
MSDN Subscriber Support in Forum
If you have any feedback on our support, please contact msdnmg@microsoft.com
这篇关于使用MSMQ的格式化程序出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!