【问题标题】:Read WCF MSMQ Message from C#从 C# 读取 WCF MSMQ 消息
【发布时间】:2017-03-20 06:18:45
【问题描述】:

我使用 WCF 客户端向 WCF Service 发送 msmq 消息,在 WCF Service 处理 msmq 消息之前,我想检查消息的正文。
检查 msmq 消息正文的内容后,我得到以下结果。

但是,我没能得到确切的字符串。
下面是WCF服务的定义

    [ServiceContract]
public interface IMSMQService
{

    [OperationContract(IsOneWay = true)]       

    void ShowMessage(string msg);
}

我使用下面的方法来检索消息体,它输出为空,如果我在ms上添加watch,我可以得到

"\0\u0001\0\u0001\u0004\u0002(net.msmq://vdi-v-tazho/private/TestQueue\u0003\aV\u0002\v\u0001s\u0004\v\u0001a\u0006V \bD\n\u001e\0��+http://tempuri.org/IMSMQService/ShowMessage@\u0017VsDebuggerCausalityData\bAhttp://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink�

                //message.Formatter = new XmlMessageFormatter(new String[] { });
            //StreamReader sr = new StreamReader(message.BodyStream);
            string ms = "";
            //while (sr.Peek() >= 0)
            //{
            //    ms += sr.ReadLine();
            //}
            message.Formatter = new ActiveXMessageFormatter();
            string result = System.Text.Encoding.UTF8.GetString(message.Body as byte[]);
            StreamReader reader = new StreamReader(message.BodyStream);

            ms = reader.ReadToEnd();
            MessageBox.Show(ms);

【问题讨论】:

    标签: wcf msmq netmsmqbinding msmq-wcf msmq-transaction


    【解决方案1】:

    我得到了下面的代码来实现我的要求。

    private void MSMQStringBody_Click(object sender, EventArgs e)
    {
        System.Messaging.MessageQueue[] queueList = System.Messaging.MessageQueue.GetPrivateQueuesByMachine(Environment.MachineName);
        MessageQueue myQueue = queueList[1];
        List<System.Messaging.Message> messages = myQueue.GetAllMessages().ToList();
        foreach (System.Messaging.Message message in messages)
        {
            System.Xml.XmlDocument result = ConvertToXMLDoc(message);
            MessageBox.Show(result.InnerText);
        }
    
    }
    public System.Xml.XmlDocument ConvertToXMLDoc(System.Messaging.Message msg)
    {
        byte[] buffer = new byte[msg.BodyStream.Length];
        msg.BodyStream.Read(buffer, 0, (int)msg.BodyStream.Length);
        int envelopeStart = FindEnvolopeStart(buffer);
        System.IO.MemoryStream stream = new System.IO.MemoryStream(buffer, envelopeStart, buffer.Length - envelopeStart);
        System.ServiceModel.Channels.BinaryMessageEncodingBindingElement elm = new System.ServiceModel.Channels.BinaryMessageEncodingBindingElement();
        System.ServiceModel.Channels.Message msg1 = elm.CreateMessageEncoderFactory().Encoder.ReadMessage(stream, Int32.MaxValue);
        System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
        doc.Load(msg1.GetReaderAtBodyContents());
        msg.BodyStream.Position = 0;
        return doc;
    }
    private int FindEnvolopeStart(byte[] stream)
    {
        int i = 0;
        byte prevByte = stream[i];
        byte curByte = (byte)0;
        for (i = 0; i < stream.Length; i++)
        {
            curByte = stream[i];
            if (curByte == (byte)0x02 &&
            prevByte == (byte)0x56)
                break;
            prevByte = curByte;
        }
        return i - 1;
    }
    

    【讨论】:

      【解决方案2】:

      当您向/从 MSMQ 发送/检索消息正文时,您应该使用相同的“类型”。请参阅下面的通用类型“T”。 T 可以是您的任何自定义类。

          public T GetQueueMessage()
          {
              Message message = queue.Receive(new TimeSpan(0, 0, 0, 1, 0));
              return (T)message.Body;
          }
      
          public void InsertQueueMessage(T message)
          {
              using (Message msg = new Message((object)message))
              {
                  queue.Send(msg, MessageQueueTransactionType.Single);
              }
          }
      

      【讨论】:

        【解决方案3】:

        我知道问题是 C# 代码,但我在这里为我们这些喜欢使用 shell 快速检查 MSMQ 内容的人提供了 Powershell 脚本。使用 Edward 的代码,我还使用 Powershell 进行了这项工作,如果有人正在寻找可以提取这些 WCF 消息的脚本,这些消息作为有效负载发送到 WCF 服务,端点使用协议绑定 NetMsmqbinding 或 NetMsmqIntegrationBinding。

        我没有使用 Int32.MaxValue,而是使用了另一个我知道在大多数情况下就足够的大整数值。顺便说一下,如果知道找到 Soap Envelope 背后的逻辑,那就太好了。

        这是 Powershell 脚本:

        [System.Reflection.Assembly]::LoadWithPartialName("System.Messaging") | Out-Null
        [System.Reflection.Assembly]::LoadWithPartialName("System.Xml") | Out-Null
        [System.Reflection.Assembly]::LoadWithPartialName("System.ServiceModel") | Out-Null
        [System.Reflection.Assembly]::LoadWithPartialName("System.IO") | Out-Null
        
        
        $queuePath = ".\private$\demoqueue4"
        
        Write-Host "Powershell MSMQ queue WCF inspector v0.1. Inspecting queue contents of the queue: $queuePath"
        Write-Host ""
        
        
        Run-MainDemoIterateMsmq $queuePath
        
        
        
        Function Get-XmlFromWcfMessage([System.Messaging.Message] $msg) {
        
            $doc = New-Object System.Xml.XmlDocument;
            $messageLength = [int] $msg.BodyStream.Length
        
        
            $buffer = New-Object byte[] $messageLength
        
        
            $msg.BodyStream.Read($buffer, 0, $messageLength)
        
            $envelopeStart = Find-SoapEnvelopeStart($buffer)
        
            $envelopeStart = $envelopeStart - 0
        
            $envelopeLength = $($buffer.Length - $envelopeStart)
            #Write-Host $envelopeStart
        
        
            $stream = New-Object System.IO.MemoryStream($buffer, $envelopeStart, $envelopeLength)
        
            $elm = New-Object System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
            $elm.ReaderQuotas.MaxStringContentLength = 10000000
            $elm.ReaderQuotas.MaxBytesPerRead = 10000000
        
        
            $msg1 = $elm.CreateMessageEncoderFactory().Encoder.ReadMessage($stream, 10000000);
        
            $doc.Load($msg1.GetReaderAtBodyContents());
        
            $msg.BodyStream.Position = 0;
        
        
        
            return $doc;
        }
        
        Function Find-SoapEnvelopeStart([byte[]] $stream)
        {
            $i = 0;
            $j = 0;
            $prevByte = $stream[$i];
            $curByte = [byte]$j;
            for ($i = 0; $i -lt $stream.Length; $i++)
            {
                $curByte = $stream[$i];
                if ($curByte -eq [byte] 0x02 -and $prevByte -eq [byte] 0x56) {
                    break;
                }
                $prevByte = $curByte;
            }
            return $i - 1;
        }
        
        
        Function Run-MainDemoIterateMsmq([string] $queuePath) {
        
        $queue = New-Object System.Messaging.MessageQueue $queuePath
        
        foreach ($message in $queue.GetAllMessages()){
          $xmlDoc = Get-XmlFromWcfMessage $message 
          Write-Host $xmlDoc.OuterXml
         } 
        
        
        }
        

        然后输出可能如下所示:

            <SendMessage xmlns="http://tempuri.org/"><message>this is another test!</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>why hello srmp</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>test</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>my message to msmq</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>This is a new message!</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>Another message to MSMQ! </message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>another test here</message></SendMessage>
            <SendMessage xmlns="http://tempuri.org/"><message>This is a test message that will be sent using NetMsmqBinding. </message></SendMessage>
            <SendMessageDataContract xmlns="http://tempuri.org/"><message xmlns:b="http://schemas.datacontract.org/2004/07/WcfDemoNetMsmqBinding.Host" xmlns:i="http://www.w3.org/2001
            /XMLSchema-instance"><b:BoolValue>true</b:BoolValue><b:StringValue>This is a test of a stringvalue for a CompositeType</b:StringValue></message></SendMessageDataContract>
        

        【讨论】:

          猜你喜欢
          • 2018-12-03
          • 1970-01-01
          • 1970-01-01
          • 2013-07-02
          • 1970-01-01
          • 1970-01-01
          • 2012-02-13
          • 1970-01-01
          • 2014-05-04
          相关资源
          最近更新 更多