How to create Service Bus queues, topics and subscriptions using a PowerShell script


In my previous post How to create a Service Bus Namespace and an Event Hub using a PowerShell script I provided a PowerShell script to create a Service Bus namespace, an event hub and a custom consumer group. In this post I provide 3 new scripts that you can use to automate the creation of queues, topics and subscriptions:

CreateQueue.ps1

This script can be used to create a subscription for an existing queue.

<#
    .SYNOPSIS
    This script can be used to provision a namespace and queue.
            
    .DESCRIPTION
    This script can be used to provision a namespace and a queue. 
    
    .PARAMETER  Path
    Specifies the full path of the queue.

    .PARAMETER  AutoDeleteOnIdle
    Specifies after how many minutes the queue is automatically deleted. The minimum duration is 5 minutes.

    .PARAMETER  DefaultMessageTimeToLive
    Specifies default message time to live value in minutes. This is the duration after which the message expires, 
    starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.
    Messages older than their TimeToLive value will expire and no longer be retained in the message store. 
    Subscribers will be unable to receive expired messages.A message can have a lower TimeToLive value than that specified here, 
    but by default TimeToLive is set to MaxValue. Therefore, this property becomes the default time to live value applied to messages.
    
    .PARAMETER  DuplicateDetectionHistoryTimeWindow
    Specifies the duration of the duplicate detection history in minutes. The default value is 10 minutes.
    
    .PARAMETER  EnableBatchedOperations
    Specifies whether server-side batched operations are enabled.
    
    .PARAMETER  EnableDeadLetteringOnMessageExpiration
    Specifies whether this queue has dead letter support when a message expires.
    
    .PARAMETER  EnableExpress
    Specifies whether to enable the queue to be partitioned across multiple message brokers. 
    An express queue holds a message in memory temporarily before writing it to persistent storage.
     
    .PARAMETER  EnablePartitioning
    Specifies whether the queue to be partitioned across multiple message brokers is enabled. 
    
    .PARAMETER  ForwardDeadLetteredMessagesTo
    Specifies the path to the recipient to which the dead lettered message is forwarded.
    
    .PARAMETER  ForwardTo
    Specifies the path to the recipient to which the message is forwarded.
    
    .PARAMETER  IsAnonymousAccessible
    Specifies whether the message is anonymous accessible.

    .PARAMETER  LockDuration
    Specifies the duration of a peek lock in seconds; that is, the amount of time that the message is locked for other receivers. 
    The maximum value for LockDuration is 5 minutes; the default value is 1 minute.
    
    .PARAMETER  MaxDeliveryCount
    Specifies the maximum delivery count. A message is automatically deadlettered after this number of deliveries.
    
    .PARAMETER  MaxSizeInMegabytes
    Specifies the maximum size of the queue in megabytes, which is the size of memory allocated for the queue.
    
    .PARAMETER  RequiresDuplicateDetection
    Specifies whether the queue requires duplicate detection.
    
    .PARAMETER  RequiresSession
    Specifies whether the queue supports the concept of session.
    
    .PARAMETER  SupportOrdering
    Specifies whether the queue supports ordering.
    
    .PARAMETER  UserMetadata
    Specifies the user metadata.

    .PARAMETER  Namespace
    Specifies the name of the Service Bus namespace.

    .PARAMETER  CreateACSNamespace
    Specifies whether  to create an ACS namespace associated to the Service Bus namespace.

    .PARAMETER  Location
    Specifies the location to create the namespace in. The default value is "West Europe". 

    Valid values:
    -- East Asia
    -- East US
    -- Central US
    -- North Central US
    -- North Europe
    -- West Europe
    -- West US
    
    .NOTES  
    Author     : Paolo Salvatori
    Twitter    : @babosbird
    Blog       : http://blogs.msdn.com/b/paolos/
#>

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Path,                                           # required    needs to be alphanumeric    
    [Int]$AutoDeleteOnIdle = -1,                             # optional    default to -1
    [Int]$DefaultMessageTimeToLive = -1,                     # optional    default to -1
    [Int]$DuplicateDetectionHistoryTimeWindow = 10,          # optional    default to 10
    [Bool]$EnableBatchedOperations = $True,                  # optional    default to true
    [Bool]$EnableDeadLetteringOnMessageExpiration = $False,  # optional    default to false
    [Bool]$EnableExpress = $False,                           # optional    default to false
    [Bool]$EnablePartitioning = $False,                      # optional    default to false
    [String]$ForwardDeadLetteredMessagesTo = $Null,          # optional    default to null
    [String]$ForwardTo = $Null,                              # optional    default to null
    [Bool]$IsAnonymousAccessible = $False,                   # optional    default to false
    [Int]$LockDuration = 30,                                 # optional    default to 30
    [Int]$MaxDeliveryCount = 10,                             # optional    default to 10
    [Int]$MaxSizeInMegabytes = 1024,                         # optional    default to 1024
    [Bool]$RequiresDuplicateDetection = $False,              # optional    default to false
    [Bool]$RequiresSession = $False,                         # optional    default to false
    [Bool]$SupportOrdering = $True,                          # optional    default to true
    [String]$UserMetadata = $Null,                           # optional    default to null
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Namespace,                                      # required    needs to be alphanumeric
    [Bool]$CreateACSNamespace = $False,                      # optional    default to $false
    [String]$Location = "West Europe"                        # optional    default to "West Europe"
    )

# Set the output level to verbose and make the script stop on error
$VerbosePreference = "Continue"
$ErrorActionPreference = "Stop"

# WARNING: Make sure to reference the latest version of the \Microsoft.ServiceBus.dll
Write-Output "Adding the [Microsoft.ServiceBus.dll] assembly to the script..."
Add-Type -Path "C:\Projects\Azure\ServiceBusExplorerNew\ServiceBusExplorer2.4Git\bin\Debug\Microsoft.ServiceBus.dll"
Write-Output "The [Microsoft.ServiceBus.dll] assembly has been successfully added to the script."

# Mark the start time of the script execution
$startTime = Get-Date

# Create Azure Service Bus namespace
$CurrentNamespace = Get-AzureSBNamespace -Name $Namespace


# Check if the namespace already exists or needs to be created
if ($CurrentNamespace)
{
    Write-Output "The namespace [$Namespace] already exists in the [$($CurrentNamespace.Region)] region." 
}
else
{
    Write-Host "The [$Namespace] namespace does not exist."
    Write-Output "Creating the [$Namespace] namespace in the [$Location] region..."
    New-AzureSBNamespace -Name $Namespace -Location $Location -CreateACSNamespace $CreateACSNamespace -NamespaceType Messaging
    $CurrentNamespace = Get-AzureSBNamespace -Name $Namespace
    Write-Host "The [$Namespace] namespace in the [$Location] region has been successfully created."
}

# Create the NamespaceManager object to create the queue
Write-Host "Creating a NamespaceManager object for the [$Namespace] namespace..."
$NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($CurrentNamespace.ConnectionString);
Write-Host "NamespaceManager object for the [$Namespace] namespace has been successfully created."

# Check if the queue already exists
if ($NamespaceManager.QueueExists($Path))
{
    Write-Output "The [$Path] queue already exists in the [$Namespace] namespace." 
}
else
{
    Write-Output "Creating the [$Path] queue in the [$Namespace] namespace..."
    $QueueDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.QueueDescription -ArgumentList $Path
    if ($AutoDeleteOnIdle -ge 5)
    {
        $QueueDescription.AutoDeleteOnIdle = [System.TimeSpan]::FromMinutes($AutoDeleteOnIdle)
    }
    if ($DefaultMessageTimeToLive -gt 0)
    {
        $QueueDescription.DefaultMessageTimeToLive = [System.TimeSpan]::FromMinutes($DefaultMessageTimeToLive)
    }
    if ($DuplicateDetectionHistoryTimeWindow -gt 0)
    {
        $QueueDescription.DuplicateDetectionHistoryTimeWindow = [System.TimeSpan]::FromMinutes($DuplicateDetectionHistoryTimeWindow)
    }
    $QueueDescription.EnableBatchedOperations = $EnableBatchedOperations
    $QueueDescription.EnableDeadLetteringOnMessageExpiration = $EnableDeadLetteringOnMessageExpiration
    $QueueDescription.EnableExpress = $EnableExpress
    $QueueDescription.EnablePartitioning = $EnablePartitioning
    $QueueDescription.ForwardDeadLetteredMessagesTo = $ForwardDeadLetteredMessagesTo
    $QueueDescription.ForwardTo = $ForwardTo
    $QueueDescription.IsAnonymousAccessible = $IsAnonymousAccessible
    if ($LockDuration -gt 0)
    {
        $QueueDescription.LockDuration = [System.TimeSpan]::FromSeconds($LockDuration)
    }
    $QueueDescription.MaxDeliveryCount = $MaxDeliveryCount
    $QueueDescription.MaxSizeInMegabytes = $MaxSizeInMegabytes
    $QueueDescription.RequiresDuplicateDetection = $RequiresDuplicateDetection
    $QueueDescription.RequiresSession = $RequiresSession
    if ($EnablePartitioning)
    {
        $QueueDescription.SupportOrdering = $False
    }
    else
    {
        $QueueDescription.SupportOrdering = $SupportOrdering
    }
    $QueueDescription.UserMetadata = $UserMetadata
    $NamespaceManager.CreateQueue($QueueDescription);
    Write-Host "The [$Path] queue in the [$Namespace] namespace has been successfully created."
}

# Mark the finish time of the script execution
$finishTime = Get-Date

# Output the time consumed in seconds
$TotalTime = ($finishTime - $startTime).TotalSeconds
Write-Output "The script completed in $TotalTime seconds."

The picture below shows the result of the execution of the script with the following parameters:

powershell .\CreateQueue.ps1 -Path iotqueue -Namespace iotsolution -DefaultMessageTimeToLive 5 -EnableExpress $True -EnablePartitioning $True -MaxSizeInMegabytes 3072 -UserMetadata 'This queue is used by the IoT solution'    

CreateQueue

 

CreateTopic.ps1

This script can be used to provision a namespace and topic.

<#
    .SYNOPSIS
    This script can be used to provision a namespace and topic.
            
    .DESCRIPTION
    This script can be used to provision a namespace and a topic. 
    
    .PARAMETER  Path
    Specifies the full path of the topic.

    .PARAMETER  AutoDeleteOnIdle
    Specifies after how many minutes the topic is automatically deleted. The minimum duration is 5 minutes.

    .PARAMETER  DefaultMessageTimeToLive
    Specifies default message time to live value in minutes. This is the duration after which the message expires, 
    starting from when the message is sent to Service Bus. This is the default value used when TimeToLive is not set on a message itself.
    Messages older than their TimeToLive value will expire and no longer be retained in the message store. 
    Subscribers will be unable to receive expired messages.A message can have a lower TimeToLive value than that specified here, 
    but by default TimeToLive is set to MaxValue. Therefore, this property becomes the default time to live value applied to messages.
    
    .PARAMETER  DuplicateDetectionHistoryTimeWindow
    Specifies the duration of the duplicate detection history in minutes. The default value is 10 minutes.
    
    .PARAMETER  EnableBatchedOperations
    Specifies whether server-side batched operations are enabled.
    
    .PARAMETER  EnableExpress
    Specifies whether to enable the topic to be partitioned across multiple message brokers. 
    An express topic holds a message in memory temporarily before writing it to persistent storage.

    .PARAMETER  EnableFilteringMessagesBeforePublishing
    Specifies whether messages should be filtered before publishing.
    
    .PARAMETER  EnablePartitioning
    Specifies whether the topic to be partitioned across multiple message brokers is enabled. 
    
    .PARAMETER  IsAnonymousAccessible
    Specifies whether the message is anonymous accessible.
    
    .PARAMETER  MaxSizeInMegabytes
    Specifies the maximum size of the topic in megabytes, which is the size of memory allocated for the topic.
    
    .PARAMETER  RequiresDuplicateDetection
    Specifies whether the topic requires duplicate detection.
    
    .PARAMETER  SupportOrdering
    Specifies whether the topic supports ordering.
    
    .PARAMETER  UserMetadata
    Specifies the user metadata.

    .PARAMETER  Namespace
    Specifies the name of the Service Bus namespace.

    .PARAMETER  CreateACSNamespace
    Specifies whether  to create an ACS namespace associated to the Service Bus namespace.

    .PARAMETER  Location
    Specifies the location to create the namespace in. The default value is "West Europe". 

    Valid values:
    -- East Asia
    -- East US
    -- Central US
    -- North Central US
    -- North Europe
    -- West Europe
    -- West US
    
    .NOTES  
    Author     : Paolo Salvatori
    Twitter    : @babosbird
    Blog       : http://blogs.msdn.com/b/paolos/
#>

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Path,                                           # required    needs to be alphanumeric    
    [Int]$AutoDeleteOnIdle = -1,                             # optional    default to -1
    [Int]$DefaultMessageTimeToLive = -1,                     # optional    default to -1
    [Int]$DuplicateDetectionHistoryTimeWindow = 10,          # optional    default to 10
    [Bool]$EnableBatchedOperations = $True,                  # optional    default to true
    [Bool]$EnableFilteringMessagesBeforePublishing = $False, # optional    default to false
    [Bool]$EnableExpress = $False,                           # optional    default to false
    [Bool]$EnablePartitioning = $False,                      # optional    default to false
    [Bool]$IsAnonymousAccessible = $False,                   # optional    default to false
    [Int]$MaxSizeInMegabytes = 1024,                         # optional    default to 1024
    [Bool]$RequiresDuplicateDetection = $False,              # optional    default to false
    [Bool]$SupportOrdering = $True,                          # optional    default to true
    [String]$UserMetadata = $Null,                           # optional    default to null
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Namespace,                                      # required    needs to be alphanumeric
    [Bool]$CreateACSNamespace = $False,                      # optional    default to $false
    [String]$Location = "West Europe"                        # optional    default to "West Europe"
    )

# Set the output level to verbose and make the script stop on error
$VerbosePreference = "Continue"
$ErrorActionPreference = "Stop"

# WARNING: Make sure to reference the latest version of the \Microsoft.ServiceBus.dll
Write-Output "Adding the [Microsoft.ServiceBus.dll] assembly to the script..."
Add-Type -Path "C:\Projects\Azure\ServiceBusExplorerNew\ServiceBusExplorer2.4Git\bin\Debug\Microsoft.ServiceBus.dll"
Write-Output "The [Microsoft.ServiceBus.dll] assembly has been successfully added to the script."

# Mark the start time of the script execution
$startTime = Get-Date

# Create Azure Service Bus namespace
$CurrentNamespace = Get-AzureSBNamespace -Name $Namespace


# Check if the namespace already exists or needs to be created
if ($CurrentNamespace)
{
    Write-Output "The namespace [$Namespace] already exists in the [$($CurrentNamespace.Region)] region." 
}
else
{
    Write-Host "The [$Namespace] namespace does not exist."
    Write-Output "Creating the [$Namespace] namespace in the [$Location] region..."
    New-AzureSBNamespace -Name $Namespace -Location $Location -CreateACSNamespace $CreateACSNamespace -NamespaceType Messaging
    $CurrentNamespace = Get-AzureSBNamespace -Name $Namespace
    Write-Host "The [$Namespace] namespace in the [$Location] region has been successfully created."
}

# Create the NamespaceManager object to create the topic
Write-Host "Creating a NamespaceManager object for the [$Namespace] namespace..."
$NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($CurrentNamespace.ConnectionString);
Write-Host "NamespaceManager object for the [$Namespace] namespace has been successfully created."

# Check if the topic already exists
if ($NamespaceManager.TopicExists($Path))
{
    Write-Output "The [$Path] topic already exists in the [$Namespace] namespace." 
}
else
{
    Write-Output "Creating the [$Path] topic in the [$Namespace] namespace..."
    $TopicDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.TopicDescription -ArgumentList $Path
    if ($AutoDeleteOnIdle -ge 5)
    {
        $TopicDescription.AutoDeleteOnIdle = [System.TimeSpan]::FromMinutes($AutoDeleteOnIdle)
    }
    if ($DefaultMessageTimeToLive -gt 0)
    {
        $TopicDescription.DefaultMessageTimeToLive = [System.TimeSpan]::FromMinutes($DefaultMessageTimeToLive)
    }
    if ($DuplicateDetectionHistoryTimeWindow -gt 0)
    {
        $TopicDescription.DuplicateDetectionHistoryTimeWindow = [System.TimeSpan]::FromMinutes($DuplicateDetectionHistoryTimeWindow)
    }
    $TopicDescription.EnableBatchedOperations = $EnableBatchedOperations
    $TopicDescription.EnableExpress = $EnableExpress
    $TopicDescription.EnableFilteringMessagesBeforePublishing = $EnableFilteringMessagesBeforePublishing
    $TopicDescription.EnablePartitioning = $EnablePartitioning
    $TopicDescription.IsAnonymousAccessible = $IsAnonymousAccessible
    $TopicDescription.MaxSizeInMegabytes = $MaxSizeInMegabytes
    $TopicDescription.RequiresDuplicateDetection = $RequiresDuplicateDetection
    if ($EnablePartitioning)
    {
        $TopicDescription.SupportOrdering = $False
    }
    else
    {
        $TopicDescription.SupportOrdering = $SupportOrdering
    }
    $TopicDescription.UserMetadata = $UserMetadata
    $NamespaceManager.CreateTopic($TopicDescription);
    Write-Host "The [$Path] topic in the [$Namespace] namespace has been successfully created."
}

# Mark the finish time of the script execution
$finishTime = Get-Date

# Output the time consumed in seconds
$TotalTime = ($finishTime - $startTime).TotalSeconds
Write-Output "The script completed in $TotalTime seconds."

The picture below shows the result of the execution of the script with the following parameters:

powershell .\CreateSubscription.ps1 -TopicPath stocks -Name ORCL -Namespace stockmarket -DefaultMessageTimeToLive 1 -SqlFilter 'StockTicker=''ORCL''' -SqlRuleAction 'SET sys.Label=''Stocks''; SET Priority=''Medium''' -UserMetadata 'This subscription is used to process messages for the ORCL stock ticker'

CreateSubscription

You can download these scripts along with the PowerShell script to create event hubs on MSDN Code Gallery: Service Bus PowerShell Scripts.


Comments (11)

  1. Zanael says:

    Hi, Paolo! Awesome article! It is possible to create a Subscription Filter with PowerShell script? Thank you.

  2. Hi Zanael

    The above PowerShell script allows to specify as a parameter, respectively, the filter expression and action of the default rule of the subscription. if you want to create additional rules for the subscription being created or a pre-existing subscription, the answer is yes, modifying the following code from script:

       $SqlFilterObject = New-Object -TypeName Microsoft.ServiceBus.Messaging.SqlFilter -ArgumentList $SqlFilter

       $SqlRuleActionObject = New-Object -TypeName Microsoft.ServiceBus.Messaging.SqlRuleAction -ArgumentList $SqlRuleAction

       $RuleDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.RuleDescription

       $RuleDescription.Filter = $SqlFilterObject

       $RuleDescription.Action = $SqlRuleActionObject

    Ciao

    Paolo

  3. Frederic Torres says:

    Great script CreateQueue.ps1, there is a bug line 172,

    we shoud test variable $DuplicateDetectionHistoryTimeWindow rather than $DefaultMessageTimeToLive

  4. Thanks Frederic, I fixed the bug.

    Ciao

    Paolo

  5. Ron Bokleman says:

    Paolo,

    This was very helpful.  Have you tried creating a Shared Access Policy on a Queue?  Would be a great addition to your work above as there seems to be little documentation on accomplishing that.  Microsoft has published a PowerShell cmdlet, but I've not been able to get it to execute without an object not found error:

    New-AzureSBAuthorizationRule -Name "MyRule" -Namespace $AzureSBNameSpace -Permission $("Manage", "Listen", "Send") -EntityName $QName -EntityType Queue

  6. Hi Rob

    I tried to use the New-AzureSBAuthorizationRule  cmdlet and indeed it worked only when I created a namespace level SAS policy. When I tried to use the -EntityName and -EntityType parameters to create an entity level SAS policy, I got an Object reference not set to an instance of an object error. I'll ping the Service Bus team and I'll get back to you.

    Ciao

    Paolo

  7. harish says:

    Hi Paola,

    Good article. Even i am facing the same issue as ron, not sure how to get rid of this.

    New-AzureSBAuthorizationRule -EntityName newtopic -EntityType Topic -Name ruleone -Namespace mynamespace-Permission "Send"

    New-AzureSBAuthorizationRule : Object reference not set to an instance of an object.

    At line:1 char:1

    + New-AzureSBAuthorizationRule -EntityName newtopic -EntityType Topic -Name ruleon …

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : CloseError: (:) [New-AzureSBAuthorizationRule], NullReferenceException

       + FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceBus.NewAzureSBAuthorizationRuleCommand

  8. Pradebban Raja says:

    Hi Paolo,

    It would really help if we have any timeline on latest release solving this issue.

    Thanks,

    Pradebban Raja

  9. I'll look into this when I have some spare time.

    Ciao

    Paolo

  10. Derek Williams says:

    The property 'EnablePartitioning' cannot be found on this object. Verify that the property exists and can be set.

    The property 'EnableExpress' cannot be found on this object. Verify that the property exists and can be set.

    Have these properties been deprecated?

  11. Hi Derek

    what version of the Microsoft.ServiceBus.dll are you using? Are you sure you don't have an obsolete version of the dll in the GAC? The two properties in question have not been deprecated.

    Ciao

    Paolo

Skip to main content