Ive got a program im writing in C# .NET that reads a queue - filters it for
various labels and where appropriate, forwards the messages onto another
queue.
The queues are populated originally by a program written in VB .NET and
simply contain Unicode text using an ActiveX formatter.
The trouble is, when I try to access the body property, i get the exception
"cannot find a formatter capable of reading this message"
Any ideas?
Chris
The source code is;
public void Poll()
{
StringBuilder sMQPath = new StringBuilder();
try
{
sMQPath.Append("FormatName:DIRECT=OS:");
sMQPath.Append ( sInServer );
sMQPath.Append ( @"\private$\" );
sMQPath.Append ( sInQueue );
Console.WriteLine ( "Checking Queue " + sMQPath );
MessageQueue qPoll = new MessageQueue();
qPoll.Path = sMQPath.ToString();
MessageEnumerator msg = qPoll.GetMessageEnumerator();
while ( msg.MoveNext())
{
// Establish whether this is a messge we are interested in
if ( msg.Current.Label == sLabelFilter )
{
msg.Current.Formatter = new ActiveXMessageFormatter();
// Construct String to hold path of output queue
StringBuilder sOutput = new StringBuilder();
sOutput.Append("FormatName:DIRECT=OS:");
sOutput.Append ( sOutServer );
sOutput.Append ( @"\private$\" );
sOutput.Append ( sOutQueue );
// Forward to OutQueue
MessageQueue qForward = new MessageQueue();
Message mForward = new Message();
qForward.Path = sOutput.ToString();
mForward.Label = msg.Current.Label;
mForward.Body = msg.Current.Body; // FAILS HERE!!!
mForward.Formatter = new ActiveXMessageFormatter();
qForward.Send( mForward );
// Remote the item from the queue
msg.RemoveCurrent();
Console.WriteLine( msg.Current.Label + " written to output queue " +
sOutput );
// Log Message to Database
// TODO
}
}
Console.WriteLine("Finished");
}
catch ( System.Exception e )
{
Console.WriteLine( e.Message );
}
}
}
Set a breakpoint on this line, run to it and then step over it. Put
msg.Current.Formatter in the watch window and you'll discover that the
formatter is null even though you just set it to a new
ActiveXMessageFormatter!
The problem is that every time you access msg.Current you get a new instance
of the Message class. Thus, what happens when you execute the line above is
1) The msg.Current property accessor creates instance m1 of the Message
class and fills m1 with all the appropriate values
2) m1.Formatter is set to new ActiveXMessageFormatter
3) m1 is now available for garbage collection since there are no outstanding
references to that instance
. . .
3+) At some indeterminate time in the future, m1 will be garbage collected
meanwhile
> mForward.Body = msg.Current.Body; // FAILS HERE!!!
4) The msg.Current property accessor creates instance m2 of the Message
class and fills m2 with all the appropriate values
5) The m2.Body property accessor attempts to extract the message contents
6) m2.Formatter is null (from step 4) so an exception is thrown.
What you need to do is declare an actual Message variable, set it to point
to msg.Current and then use that Message variable for all subsequent
manipulation...
MessageEnumerator msgEnum = qPoll.GetMessageEnumerator();
Message msg = null;
while ( msgEnum.MoveNext())
{
msg = msgEnum.Current;
. . .
' Change all msg.Current to just msg
. . .
msgEnum.RemoveCurrent();
}
Thanks for that - I got in touch with MS last week and found an equally
embarrassing ommission on my part....set the formatter of the Queue rather
than the current message to an ActiveXMessageFormatter
doh!!
Chris
"Frank Boyne" <frank...@unisys.com> wrote in message
news:uNFZ5Kc$BHA.1892@tkmsftngp02...