2011-05-02 66 views
2

我有一个应用程序在MSMQ消息队列中显示消息的内容。 Windows 7上的MSMQ存在一个问题,它不保留消息正文中数据的真实对象类型。在这个例子中,我发送了一个字节[],然后当我收到它时,它不再是一个字节数组,而是包装的XML容器文档。在Windows XP中,我从来没有遇到过这个问题,并且Message.Body属性总是正确设置为byte []。MSMQ + C#,接收带编码字节[]体的消息在Windows 7与Windows XP上的行为有所不同

这里是压缩代码:

public void SendWithCompression(string Message) 
    { 
     try 
     { 
      // Compress the message data in memory. 
      byte[] UncompressedData = Encoding.UTF8.GetBytes(Message); 
      byte[] CompressedData = null; 

      MemoryStream s = new MemoryStream(); 
      using (GZipStream z = new GZipStream(s, CompressionMode.Compress)) 
      { 
       z.Write(UncompressedData, 0, UncompressedData.Length); 
      } 
      CompressedData = s.ToArray(); 

      if (_Transaction != null) 
      { 
       _Transaction.Begin(); 
       base.Send(CompressedData, _Transaction); 
       _Transaction.Commit(); 
      } 
      else 
      { 
       base.Send(CompressedData); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
     } 
    } 

下面是测试消息的消息内容。它结束了作为一个包装编码的二进制数据: <?xml version="1.0"?>..<base64Binary>H4sIAAAAAAAEAO29B2AcSZYlJi9tynt/SvVK1+B0oQiAYBMk2JBAEOzBiM3mkuwdaUcjKasqgcplVmVdZhZAzO2dvPfee++999577733ujudTif33/8/XGZkAWz2zkrayZ4hgKrIHz9+fB8/Ih63edMefTsvy2rv8V3+4/8ByygBlxMAAAA=</base64Binary>


这里是它使用的解压缩代码的XML文档:

 String Data; 
     //Get message and format XML 
     System.Messaging.Message m = MessagesList[ListIndex].Tag; 
     m.Formatter = new XmlMessageFormatter(new Type[] 
     { 
      typeof(string), // Send raw plain strings 
      typeof(byte[]), // Array of binary data 
      typeof(XmlNode) // Xml document 
     }); 

     m.BodyStream.Position = 0; 

     Data = m.Body.ToString(); 
      if (m.Body.GetType() == typeof(byte[])) 
      { 
       try 
       { 
        // The message body is an array of binary data. 
        // Assume it is a GZIP stream of compressed data. 
        byte[] CompressedData = (byte[])m.Body; 
        byte[] UncompressedData = null; 

        // Decompress it. 
        MemoryStream s = new MemoryStream(CompressedData); 
        using (GZipStream z = new GZipStream(s, CompressionMode.Decompress)) 
        { 
         UncompressedData = MyExtensions.ReadRemainingBytes(z); 
        } 

        // Turn the bytes back into a string. 
        Data = Encoding.UTF8.GetString(UncompressedData); 
       } 
       catch 
       { 
        Data = "Unknown binary data: " + 
        BitConverter.ToString((byte[])m.Body, 0); 
       } 
      } 
      if (m.Body.GetType() == typeof(XmlElement)) 
      { 
       XmlElement el = (XmlElement)m.Body; 
       if (el.Name == "string") 
        Data = el.InnerText; 
       else 
        Data = el.OuterXml; 
      } 

我想指出,我我正在设置消息的格式化程序,这是让身体在队列中自动“框”和“开箱”的第一步。

在Windows XP中,m.Body.GetType()== byte [],如预期的那样。但是,在Windows 7中,m.Body.GetType()== XmlElement,即包装器XML。它不再“解开”信息。

我们需要做不同的事情吗?我们已经为它发送了一次字符串,就像你在接收函数结束时看到的一样,但是我想找到一个真正的答案,说明为什么这个代码在Windows 7上表现不同。

+0

从XmlMessageFormatter构造函数调用中移除XmlNode。 – 2011-05-03 00:32:57

回答

7

使用Message.BodyStream财产,如果要发送的字节数组:用于发送和接收消息

System.Messaging.MessageQueue queue = new MessageQueue(queueFormatName, false, true, QueueAccessMode.Send); 

System.Messaging.Message msg = new System.Messaging.Message(); 
msg.BodyStream = new MemoryStream(buffer); 

queue.Send(msg, MessageQueueTransactionType.Single); 
2

使用Message.BodyStream财产,看看下面的代码,你可以发送和使用它接收byte[]

public void SendMessage() 
{ 
    MessageQueue myQueue = new MessageQueue(".\\QUEUE"); 
    byte[] msg = new byte[2]; 
    msg[0] = 29;    
    // Send the array to the queue. 
    Message msg1 = new Message(); 
    msg1.BodyStream = new MemoryStream(msg); 
    messageQueue.Send(msg1);     
} 

public void ReceiveMessage() 
{ 
    MessageQueue myQueue = new MessageQueue(".\\QUEUE");    
    Message myMessage =myQueue.Receive(); 
    byte[] msg = ReadFully(myMessage.BodyStream); 
} 

public static byte[] ReadFully(Stream input) 
{ 
    byte[] buffer = new byte[16 * 1024]; 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     int read; 
     while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      ms.Write(buffer, 0, read); 
     } 
     return ms.ToArray(); 
    } 
}