Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MessageQueue.Formatter question

754 views
Skip to first unread message

Jellobiaffra

unread,
Aug 16, 2007, 12:15:37 PM8/16/07
to
I have written an app in C# that needs to send a message (just a
string) to a MessageQueue. The problem is that the message will be
read by a general purpose app written in C++ that is used by lots of
applications, and therefore the format of the message I send from my
C# app must be exactly right.

I have tried setting the MessageQueue.Formatter property to all three
different types, but the message is strange whichever type I use. If I
look at messages in the message queue after I send them I see that:

- XMLMessageFormatter encloses message in XML, I don't want this.
- BinaryMessageFormatter has added some strange chars to beggining of
the message, the app that reads the queue says the size of the message
is 0.
- ActiveXMessageFormatter looks to be some kind of wide string? The
reading app can only read the first char of the message, saying the
size is 1.

Isn't there a way to just put a plain string on a message queue? I
don't want to have to change the app that reads the queue, and don't
even know if I can...

Thanks for any help.

Regards,
- Jellobiaffra

Dejan Grujic

unread,
Aug 16, 2007, 2:37:13 PM8/16/07
to
You can use Message's BodyStream property to directly access body bytes,
without any formatter. All you have to do is to convert your string to
byte array. Dot Net strings are Unicode, so you'll have to decide how
you'll convert them to bytes. For instance:

byte[] bytes = Encoding.UTF8.GetBytes( yourString );
message.BodyStream = new MemoryStream( bytes );

Dejan

--
Find out how QueueExplorer makes MSMQ more manageable
http://www.cogin.com

Frank Boyne

unread,
Aug 16, 2007, 4:55:53 PM8/16/07
to
"Jellobiaffra" <grek...@hotmail.com> wrote in message
news:1187280937.6...@g4g2000hsf.googlegroups.com...

> I have tried setting the MessageQueue.Formatter property to all three
> different types, but the message is strange whichever type I use.

I wouldn't call them strange

> - XMLMessageFormatter encloses message in XML,

Tht's right. The XMLMessageFormatter serializes any object (well any
object capable of being serialized) using XML as the representation.
Not really strange (but not what you are looking for).

> - BinaryMessageFormatter has added some strange chars to beggining of
> the message, the app that reads the queue says the size of the message
> is 0.

BinaryFormatter uses the native in-memory representation of the object
(in this case a string). It's a very fast way of 'encoding' an object
(you just copy a bunch of bytes) but of limited use to anything that
doesn't use the same binary representation.

Off-hand I have no idea what all the bytes at the start of the message
mean but they are all part of the in-memory representation of an
instance of the a string class. Remember that a C# string is not null
terminated but rather has a separate length property. At least part of
the 'extra' characters is the length of this string. I suspect another
part is an indication of the enocding used (UTF-8, UTF-16 etc) but that
is just a guess on my part.

Your receiving app is probably treating the message bdy as if it were a
null-terminated sequence of 8-bit characters so the leading 00 in the
message body is being interpreted as the end of string indicator - hence
the size of message = zero.

> - ActiveXMessageFormatter looks to be some kind of wide string? The
> reading app can only read the first char of the message, saying the
> size is 1.

Strings in C# _are_ Unicode so a wide string is needed to fully
represent the contents. The ActiveXMessageFormatter encodes the string
as a BSTR - the OLE Automation version of a string. I'm guessing your
string contains characters from the Controls and Basic Latin code page
so their hex representation lies somewhere between 0x0000 and 0x00FF.
Let's say your string starts with an A 0x0041. Since the x86 chip set
is little-endian the lower order byte will appear first in the message
body so the message body will look like this 0x41 0x00 ...etc... Your
receiving app will see an 8-bit null terminated string consisting of
0x41 followed by null. hence the size is one.

If you could change your C++ application, ActiveXMessageFormatter would
probably be your best choice for encoding. You could change your C++
application to use the COM API to receive the message and so get the
full benefit of the ActiveXMessageFormatter as shown in this example:
http://msdn2.microsoft.com/en-us/library/ms705040.aspx

Or, if you didn;t want to make that drastic a change you could use any
of the BSTR types (BSTR, _bstr_t, CComBSTR etc.) to take the message
body and message body size parameters and turn them into a BSTR

> Isn't there a way to just put a plain string on a message queue? I
> don't want to have to change the app that reads the queue, and don't
> even know if I can...

It sounds like your application is expecting a null terminated,
eight-bit wide sequence of characters. Since C# strings are made up of
sixteen-bit wide characters, you'll have to convert the string before
placing it into the message body. One challenge you face is deciding
how to convert those sixteen-bit characters - what eight-bit encoding do
you use, what do you do with characters that cannot be represented by
whatever encoding you select, etc.

Here's one quick and dirty way of getting something close to what you
want. The code 'cheats' by taking advantage of the fact that the
ActiveXMessageFormatter's physical representation of a byte array is
more or less a byte array (if we ignore the body type property). I
could have directly manipulated the message body contents via the
BodyStream property but using the ActiveXMessageFormatter simplifies the
code below (no need for a StreamWriter of some sort) and also gives us a
representation that makes some sense to the COM API.

The code explicitly adds a null to the end of the string (\u0000) so
that the resulting message body contents are null terminated and then
uses the built-in ASCII encoding to translate the Unicode string in
'txt' into something your C++ app is likely to recognise.

string txt = "hello MSMQ world!";

MessageQueue q = new MessageQueue(@".\private$\testQueue");
q.Formatter = new ActiveXMessageFormatter();

txt = txt + "\u0000";

byte[] bt = Encoding.ASCII.GetBytes(txt);

q.Send(bt);


Jellobiaffra

unread,
Aug 17, 2007, 3:07:14 AM8/17/07
to
Thanks to both of you for the answers, and thanks Frank for the
extensive explanation of how things work, I feel smarter for reading
it :-)

In the end I went for the code below, Frank you were correct in
assuming I needed to null-terminate the string.

Message msg = new Message();
stringToSend += "\u0000";
byte[] bytes =
Encoding.UTF8.GetBytes(stringToSend );
msg.BodyStream = new MemoryStream(bytes);
m_msgQueue.Send(msg);

Thanks again for your quick help!

Regards,
- Jellobiaffra

0 new messages