# MSMQ Transport Scripting This article contains code and scripts to facilitate deployment and operational actions with MSMQ. These examples use the [System.Messaging](https://learn.microsoft.com/en-us/dotnet/api/system.messaging?view=netframework-4.8) and [System.Transactions](https://learn.microsoft.com/en-us/dotnet/api/system.transactions?view=netframework-4.8) assemblies. > [!WARNING] > The `System.Messaging` namespace is not available in .NET Core. > [!NOTE] > When using the C# code samples, be sure to add the proper includes for both the `System.Messaging` and `System.Transactions` assemblies in the program that's using these functions. When using the PowerShell scripts, include these assemblies by calling `Add-Type` in the script. ## Create queues Queue creation can be done for a specific endpoint or queues shared between multiple endpoints. > [!NOTE] > It may be necessary to script the creation of extra instance-specific queues. For example when using [callbacks](/nservicebus/messaging/callbacks.md#message-routing) or scale-out based on sender-side distribution. See also: [Queue Permissions](/transports/msmq/index.md#permissions) ### The create queue helper methods #### In C# ```cs public static class QueueCreationUtils { public static void CreateQueue(string queueName, string account) { var path = $@"{Environment.MachineName}\private$\{queueName}"; if (!MessageQueue.Exists(path)) { using (var messageQueue = MessageQueue.Create(path, true)) { SetDefaultPermissionsForQueue(messageQueue, account); } } } static void SetDefaultPermissionsForQueue(MessageQueue queue, string account) { var allow = AccessControlEntryType.Allow; queue.SetPermissions(AdminGroup, MessageQueueAccessRights.FullControl, allow); queue.SetPermissions(account, MessageQueueAccessRights.WriteMessage, allow); queue.SetPermissions(account, MessageQueueAccessRights.ReceiveMessage, allow); queue.SetPermissions(account, MessageQueueAccessRights.PeekMessage, allow); queue.SetPermissions(account, MessageQueueAccessRights.GetQueueProperties, allow); } static string AdminGroup = GetGroupName(WellKnownSidType.BuiltinAdministratorsSid); static string GetGroupName(WellKnownSidType wellKnownSidType) { return new SecurityIdentifier(wellKnownSidType, null) .Translate(typeof(NTAccount)) .ToString(); } } ``` #### In PowerShell ```ps1 Function CreateQueue { param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $QueueName, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateScript({ValidateAccount -Account $_})] [string] $Account ) $queuePath = '{0}\private$\{1}' -f $env:COMPUTERNAME, $QueueName if (-Not [System.Messaging.MessageQueue]::Exists($queuePath)) { $messageQueue = [System.Messaging.MessageQueue]::Create($queuePath, $true) SetDefaultPermissionsForQueue -Queue $messageQueue -Account $Account } else { Write-Warning "$queuepath already exists - no changes were made" } } Function GetAccountFromWellKnownSid { param( [Parameter(Mandatory=$true)] [System.Security.Principal.WellKnownSidType] $WellKnownSidType ) $account = New-Object System.Security.Principal.SecurityIdentifier $WellKnownSidType,$null return $account.Translate([System.Security.Principal.NTAccount]).ToString() } Function ValidateAccount { param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Account ) # Test Account is valid $userAccount = new-object System.Security.Principal.NTAccount($Account) try { [void] $userAccount.Translate([System.Security.Principal.SecurityIdentifier]) return $true } catch [System.Security.Principal.IdentityNotMappedException] { Write-Warning "$account does not resolve to a Windows Account" return $false } } Function SetDefaultPermissionsForQueue { param( [Parameter(Mandatory=$true)] [System.Messaging.MessageQueue] $Queue, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $Account ) $adminGroup = GetAccountFromWellKnownSid -wellKnownSidType ([System.Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid) $Queue.SetPermissions($AdminGroup, "FullControl", "Allow") $Queue.SetPermissions($Account, "WriteMessage", "Allow") $Queue.SetPermissions($Account, "ReceiveMessage", "Allow") $Queue.SetPermissions($Account, "PeekMessage", "Allow") $Queue.SetPermissions($Account, "GetQueueProperties", "Allow") } ``` ### Creating queues for an endpoint To create all queues for a given endpoint name. #### In C# ```cs public static void CreateQueuesForEndpoint(string endpointName, string account) { // main queue QueueCreationUtils.CreateQueue(endpointName, account); // timeout queue QueueCreationUtils.CreateQueue($"{endpointName}.timeouts", account); // timeout dispatcher queue QueueCreationUtils.CreateQueue($"{endpointName}.timeoutsdispatcher", account); // retries queue // TODO: Only required in Versions 5 and below QueueCreationUtils.CreateQueue($"{endpointName}.retries", account); } ``` #### In PowerShell ```ps1 Function CreateQueuesForEndpoint { param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [string] $EndpointName, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [ValidateScript({ValidateAccount -Account $_})] [string] $Account, [Parameter(HelpMessage="Only required for NSB Versions 5 and below")] [Switch] $IncludeRetries ) # main queue CreateQueue -QueueName $EndpointName -Account $Account # timeout queue CreateQueue -QueueName "$EndpointName.timeouts" -Account $Account # timeout dispatcher queue CreateQueue -QueueName "$EndpointName.timeoutsdispatcher" -Account $Account # retries queue if ($IncludeRetries) { CreateQueue -QueueName "$EndpointName.retries" -Account $Account } } ``` ### Using the create endpoint queues #### In C# ```cs CreateQueuesForEndpoint( endpointName: "myendpoint", account: Environment.UserName); ``` #### In PowerShell ```ps1 # For NServiceBus 6 Endpoints CreateQueuesForEndpoint -EndpointName "myendpoint" -Account $env:USERNAME # For NServiceBus 5 and below Endpoints CreateQueuesForEndpoint -EndpointName "myendpoint" -Account $env:USERNAME -IncludeRetries ``` ### To create shared queues #### In C# ```cs QueueCreationUtils.CreateQueue( queueName: "error", account: Environment.UserName); QueueCreationUtils.CreateQueue( queueName: "audit", account: Environment.UserName); ``` #### In PowerShell ```ps1 CreateQueue -QueueName "error" -Account $env:USERNAME CreateQueue -QueueName "audit" -Account $env:USERNAME ``` ## Delete queues ### The delete helper queue methods #### In C# ```cs public static class QueueDeletionUtils { public static void DeleteAllQueues() { var machineQueues = MessageQueue.GetPrivateQueuesByMachine("."); foreach (var q in machineQueues) { MessageQueue.Delete(q.Path); } } public static void DeleteQueue(string queueName) { var path = $@"{Environment.MachineName}\private$\{queueName}"; if (MessageQueue.Exists(path)) { MessageQueue.Delete(path); } } } ``` #### In PowerShell ```ps1 Set-StrictMode -Version 2.0 Add-Type -AssemblyName System.Messaging Function DeleteQueuesForEndpoint { param( [Parameter(Mandatory=$true)] [string] $endpointName ) # main queue DeleteQueue $endpointName # timeout queue DeleteQueue ($endpointName + ".timeouts") # timeout dispatcher queue DeleteQueue ($endpointName + ".timeoutsdispatcher") # retries queue # TODO: Only required in Versions 5 and below DeleteQueue ($endpointName + ".retries") } Function DeleteQueue { param( [Parameter(Mandatory=$true)] [string] $queueName ) $queuePath = '{0}\private$\{1}'-f [System.Environment]::MachineName, $queueName if ([System.Messaging.MessageQueue]::Exists($queuePath)) { [System.Messaging.MessageQueue]::Delete($queuePath) } } Function DeleteAllQueues { foreach ($queue in [System.Messaging.MessageQueue]::GetPrivateQueuesByMachine(".")) { [System.Messaging.MessageQueue]::Delete($queue.Path) } } ``` ### To delete all queues for a given endpoint ```cs public static void DeleteQueuesForEndpoint(string endpointName) { // main queue QueueDeletionUtils.DeleteQueue(endpointName); // timeout queue QueueDeletionUtils.DeleteQueue($"{endpointName}.timeouts"); // timeout dispatcher queue QueueDeletionUtils.DeleteQueue($"{endpointName}.timeoutsdispatcher"); // retries queue // TODO: Only required in Versions 5 and below QueueDeletionUtils.DeleteQueue($"{endpointName}.retries"); } ``` ```cs DeleteQueuesForEndpoint("myendpoint"); ``` ### To delete shared queues ```cs QueueDeletionUtils.DeleteQueue(queueName: "error"); QueueDeletionUtils.DeleteQueue(queueName: "audit"); ```