The last article looked at displaying MSMQ contents for a MSMQ queue used with NetMsmqBinding using Powershell. The message queues contained characters that were unreadable. That is because
the message queue items contains actually ready to consume WCF messages. This article will present a new Powershell script where the MSMQ body contents is finally readable using Powershell
and .NET WCF classes in System.ServiceModel.
Here is how the contents looks using regular methods to extract the MSMQ Message queue items with garbled contents. This is as noted due to the MSMQ queue items each containing a corresponding WCF message.
Let's fix this up by using System.ServiceModel classes!
[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);
$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
}
}
The soap envelope is found looking after the escape sequence "V" followed with the special ANSI character 0x02 (STX = Start of Text). From this point on, the rest of the WCF Message is our SOAP body!
We then get readable output!
Finally, the WCF messages inside the MSMQ queue that is filled up using NetMsmqBinding is readable! In my next article I will present a demo solution of how to use NetMsmqBinding in WCF! Until then, you can clone the solution already from here:
git clone git@bitbucket.org:toreaurstad/demonetmsmqwcfgit.git
No comments:
Post a Comment