This blog shows how to write to MSMQ from C#. In an earlier blog, I showed how to write to MSMQ from Powershell.

There are two tricks:
1) With Transactional Queues you have to include the Transaction, and also specify the second parm on the .Send method.
2) MessagePriority is only supported in non-transactional queues.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Messaging;

namespace MSMQCSharpConsoleDemo
{
    class Program
    {
        static void Main(string[] args)
        {

            string queueName = @"FormatName:DIRECT=OS:ServerName\Private$\biztalknontrans";
            string message = "<helloWorld><MyMessage language='English' /></helloWorld>";
            // a good label with a key and date/time helps to see what's in the queue if the queue gets backed up  
            string label = "Order=12345 Date=" + System.DateTime.Now.ToString("yyyyMMdd hh:mm:ss");
            //label = null; 
            MessagePriority msgPriority = MessagePriority.Highest;
            WriteMSMQNoTrans(queueName, message, label, msgPriority);

            //queueName = @"FormatName:DIRECT=OS:ServerName\Private$\biztalktrans";
            //WriteMSMQTrans(queueName, message, label);  // Transactional queues do not support priority 

            Console.WriteLine("\n\nPress enter to end:");
            Console.ReadLine(); 
        }

        public static void WriteMSMQNoTrans(string queueName, string messageText, string label, MessagePriority msgPriority)
        {
            MessageQueue mq;
            try 
            {
                mq = new System.Messaging.MessageQueue(queueName);
                UTF8Encoding utf8 = new System.Text.UTF8Encoding(); 

                byte[] msgBytes = utf8.GetBytes(messageText);
                System.IO.MemoryStream msgStream = new System.IO.MemoryStream(); 
                msgStream.Write(msgBytes, 0, msgBytes.Length); 

                Message mm = new Message(); 
                mm.BodyStream = msgStream; 
                if (label != null) 
                {
                   mm.Label = label;
                }
                mm.Priority = msgPriority;
                mq.Send(mm);
                Console.WriteLine("Message sent (NonTrans)"); 
            }
            catch (Exception ex) 
            {
                string errMessage = "QueueName: " + queueName + " Error:" + ex.Message; 
                Console.WriteLine(errMessage); 
                System.Diagnostics.EventLog.WriteEntry("Logger",errMessage); 
            }
        }


        public static void WriteMSMQTrans(string queueName, string messageText, string label)
        {
            try
            {
                MessageQueue mq;
                MessageQueueTransaction tran = new MessageQueueTransaction();
                tran.Begin();
                mq = new System.Messaging.MessageQueue(queueName);
                UTF8Encoding utf8 = new System.Text.UTF8Encoding();

                byte[] msgBytes = utf8.GetBytes(messageText);
                System.IO.MemoryStream msgStream = new System.IO.MemoryStream();
                msgStream.Write(msgBytes, 0, msgBytes.Length);
                
                Message mm = new Message();
                mm.BodyStream = msgStream; 
                if (label != null)
                {
                    mm.Label = label;
                }
                //mq.Send(mm);  // wow with transactioanl queue this will run, not give an error, but no data will be written 
                                // You must include second parm below. 
                mq.Send(mm, MessageQueueTransactionType.Single);  
                 

                Console.WriteLine("Message sent (Trans)");
                tran.Commit();
                tran.Dispose(); 
            }
            catch (Exception ex)
            {
                string errMessage = "QueueName: " + queueName + " Error:" + ex.Message;
                Console.WriteLine(errMessage);
                System.Diagnostics.EventLog.WriteEntry("Logger", errMessage);
            }

            
        }

    }  // end class 
}

For further examples: https://msdn.microsoft.com/en-us/library/ms978430.aspx and https://support.microsoft.com/en-us/kb/815811

If you are getting the error “Invalid queue path name” from C# or other language, it could be that when reference a remote queue, you need to add the “FormatName:DIRECT:OS:” on the front,

Instead of:

MyServer\private$\MyQueue

Prefix it as shown below

FormatName:DIRECT=OS:MyServer\private$\MyQueue

For more details, see “Manabu Tokunaga blog” or “Stack Overflow”

This blog shows you how to How to Add and Delete MSMQ Queues from Powershell, programmatically, via a simple re-usable function.

I used the code from this blog as a base: http://blogs.msdn.com/b/sajay/archive/2010/03/18/powershell-script-to-create-an-msmq.aspx. His code is fine, but it’s from an administrators perspective, i.e. run this Powershell, pass it some parms. I wanted the same code to be callable as a function that could be called from other Powershell code.  Another source of similar information is here: http://blogs.msdn.com/b/biztalknotes/archive/2013/08/19/powershell-scripts-to-manage-msmq.aspx

In earlier blogs, I demonstrated How to Write to MSMQ from Powershell and How to Read MSMQ from Powershell. Those dealt with read and writing individual queue messages from an existing queue in MSMQ. In this blog, the topic is creating and removing the entire queue in MSMQ.

function CreateMSMQQueue($queuename, $YNPrivate, $YNTransactional, $user, $permission) 
{

    if ($permission -ne "all" -and $permission -ne "restricted") 
        {
           Write-Host "Error: fifth parameter "permission" must have value 'all' or 'restricted'" 
           exit 
        }

    [Reflection.Assembly]::LoadWithPartialName("System.Messaging")


    if ($YNPrivate -ieq "Y")
        { 
          $queuename = ".\private$\" + $queuename 
        }

    if ($YNTransactional -ieq "Y")
        {
            $transactional = 1
            Write-Host "Creating a transactional queue."
        }
    else
        {
            $transactional = 0
            Write-Host "Creating a non-trasactional queue"
        }
    
    $msgQueue = [System.Messaging.MessageQueue]::Create($queuename, $transactional) 
    
    if($msgQueue -eq $null)
        {
            Write-Host "Error: got a 'null' back from the Create MSMQ function" 
            exit
        }
    
    $msgQueue.label = $queuename
           
    if ($permission -ieq "all")
        {
            Write-Host "Granting all permissions to "  $User
            $msgQueue.SetPermissions($User, [System.Messaging.MessageQueueAccessRights]::FullControl, [System.Messaging.AccessControlEntryType]::Allow) 
        }
    else
        {
            Write-Host "Restricted Control for user: "  $User
            Write-Host ""
            $msgQueue.SetPermissions($User, [System.Messaging.MessageQueueAccessRights]::DeleteMessage, [System.Messaging.AccessControlEntryType]::Set) 
            $msgQueue.SetPermissions($User, [System.Messaging.MessageQueueAccessRights]::GenericWrite, [System.Messaging.AccessControlEntryType]::Allow) 
            $msgQueue.SetPermissions($User, [System.Messaging.MessageQueueAccessRights]::PeekMessage, [System.Messaging.AccessControlEntryType]::Allow) 
            $msgQueue.SetPermissions($User, [System.Messaging.MessageQueueAccessRights]::ReceiveJournalMessage, [System.Messaging.AccessControlEntryType]::Allow)
        }
}


function DeleteMSMQQueue($queuename, $YNPrivate) 
{
    Write-Host "DeleteMSMQQUEUE QueueName: " + $queuename
    if ($YNPrivate -ieq "Y")
    { 
      $queuename = ".\private$\" + $queuename 
    }
    Write-Host "Delete Queue: " + $queuename
    [System.Messaging.MessageQueue]::Delete($queuename)
}


cls
$myQueueName = "NealTestPSMSMQ1" 
$ynIsTransactional = "Y" 
$ynIsPrivate = "Y" 
$user ="Administrator" 
$permission = "all" 
CreateMSMQQueue $myQueueName $ynIsPrivate $ynIsTransactional $user $permission 

#use the following instead of Create to Delete the Queue
#DeleteMSMQQueue $myQueueName $ynIsPrivate 

Results

To view the results, open “Server Manager”, expand “Features” and “Message Queueing”, and look for the queue just created. In my example above, the queue name was ‘nealtestpsmsmq1’.
ServerManager_Features_MessageQueueing_Results

 

To read or write individual messages to that queue, see previous blogs (links at top of this article).

One potential enhancement to the above code might be to pass an array or collection of userids and desired privileges to the function, or to create a third function to manage the security privileges for the queue.

In summary, this article has shown how to create and remove a MSMQ queue using Powershell.

 

[Reflection.Assembly]::LoadWithPartialName("System.Messaging")

cls

$queueName = '.\Private$\NealTest'
$queue = new-object System.Messaging.MessageQueue $queueName
$utf8  = new-object System.Text.UTF8Encoding

$msgs = $queue.GetAllMessages()
 
write-host "Number of messages=$($msgs.Length)" 

foreach ($msg in $msgs)
  {
      write-host $msg_.Id
      write-host $utf8.GetString($msg.BodyStream.ToArray())
  }


Depending on how many times you wrote messages to the queue, the output will look something like this:

MSMQ_Read_Results

First make sure MMSQ is installed, and then for now, manually create your queue using the Server Manager MMC (Microsoft Management Console) GUI (Graphical User Interface). Perhaps in an upcoming blog I will demonstrate the creation of the queue itself in Powershell.

NOTE: MSMQ can only hold messages up to 4MB!

MSMQ_New_PrivateQueue1

Select whether you want your queue to be transactional or not (for help in making this decision, see this link: http://msdn.microsoft.com/en-us/library/ms704006%28v=vs.85%29.aspx
MSMQ_New_PrivateQueue2

Here is the sample code. I have created two functions, one which supports transactional queues, and one non-transactional queues. Note, if I wanted to make the routines more flexible, I could allow the encoding type to be passed as a parameter; the code below assumes UTF8 encoding.

[Reflection.Assembly]::LoadWithPartialName("System.Messaging")


function WriteMessageToMSMQTrans($queueName, $message, $label)
  {
     $queue = new-object System.Messaging.MessageQueue $queueName
     $utf8 = new-object System.Text.UTF8Encoding

     $tran = new-object System.Messaging.MessageQueueTransaction
     $tran.Begin()

     $msgBytes = $utf8.GetBytes($message)

     $msgStream = new-object System.IO.MemoryStream
     $msgStream.Write($msgBytes, 0, $msgBytes.Length)

     $msg = new-object System.Messaging.Message
     $msg.BodyStream = $msgStream   
     if ($label -ne $null)
       {
         $msg.Label = $label
       }
     $queue.Send($msg, $tran)

     $tran.Commit()
     Write-Host "Message written"
  }

function WriteMessageToMSMQNonTrans($queueName, $message, $label)
  {
     $queue = new-object System.Messaging.MessageQueue $queueName
     $utf8 = new-object System.Text.UTF8Encoding

     $msgBytes = $utf8.GetBytes($message)

     $msgStream = new-object System.IO.MemoryStream
     $msgStream.Write($msgBytes, 0, $msgBytes.Length)

     $msg = new-object System.Messaging.Message
     $msg.BodyStream = $msgStream
     if ($label -ne $null)
       {
         $msg.Label = $label
       }
     $queue.Send($msg)

    Write-Host "Message written"
  }

#-------------------------
#Test the above functions 
#-------------------------
cls  #clear screen (junk from prior runs) 
$queueName = ".\Private$\nealtest"

$message = "This is my first test message"
WriteMessageToMSMQNonTrans $queueName $message $null

$message = "This is my second test message"
WriteMessageToMSMQNonTrans $queueName $message "MyLabel"

Write-Host "Completed"

 

Now we can go view the two messages written to the queue.

MSMQ_in_Server_Manager

 

You can right-click “Properties” on either message.  Below, I’m showing the “General” tab with the date the message was written, then the “Body” tag which shows the hex and text of the message.

 

MSMQ_Properties_Tab_General

 

MSMQ_Properties_Tab_BodyText

 

 

We recently learned that when you have MSMQ clustered, you cannot go to the normal “Manage Computer” to manage the queue. Instead, you have to run a special utility:

MMCV –s YourMSMQClusterName


The above utility can be downloaded from Microsoft.