How to create a Service Bus Namespace and an Event Hub using a PowerShell script


This week I received the same two questions twice from two different customers: how can I create a Service Bus namespace from a PowerShell script? Moreover, after I created the Service Bus namespace, how can I create an event hub from a PowerShell script? The answer to the first question is easy: to create a new Azure Service Bus namespace you can use the New-AzureSBNamespace PowerShell cmdlet. The answer to the second question is also straightforward: to create a new Event Hub you can use the CreateEventHub method of the NamespaceManager class. The second question should be posed in a different way: how can I use the classes of the Microsoft.ServiceBus.dll assembly inside a PowerShell script? The following post shows a PowerShell script that you can use to create a Service Bus namespace, an Event Hub and a Consumer Group for the newly created Event Hub.

<#
    .SYNOPSIS
    This script can be used to provision a namespace and an event hub.
            
    .DESCRIPTION
    This script can be used to provision a namespace and an event hub. 
    In particular, the script allows to specify the following parameters:
    -- Event Hub path
    -- Event hub message retention in days
    -- Event Hub partition count
    -- Event Hub user metadata
    -- Service Bus Namespace
    -- Azure Datacenter location
    
    .PARAMETER  Path
    Specifies the full path of the event hub.

    .PARAMETER  PartitionCount
    Specifies the current number of shards on the event hub.

    .PARAMETER  MessageRetentionInDays
    Specifies the number of days to retain the events for this event hub.

    .PARAMETER  UserMetadata
    Specifies the user metadata for the event hub.
    
    .PARAMETER  ConsumerGroupName
    Specifies the name of a custom consumer group.

    .PARAMETER  ConsumerGroupUserMetadata
    Specifies the user metadata for the custom consumer group.

    .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
    -- North Central US
    -- North Europe
    -- West Europe
    -- West US
    
#>

[CmdletBinding(PositionalBinding=$True)]
Param(
    [Parameter(Mandatory = $true)]
    [ValidatePattern("^[a-z0-9]*$")]
    [String]$Path,                                  # required    needs to be alphanumeric    
    [Int]$PartitionCount = 16,                      # optional    default to 16
    [Int]$MessageRetentionInDays = 7,               # optional    default to 7
    [String]$UserMetadata = $null,                  # optional    default to $null
    [String]$ConsumerGroupName = "MyConsumerGroup", # optional    default to "MyConsumerGroup"
    [String]$ConsumerGroupUserMetadata = $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 event hub
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 event hub already exists
if ($NamespaceManager.EventHubExists($Path))
{
    Write-Output "The [$Path] event hub already exists in the [$Namespace] namespace." 
}
else
{
    Write-Output "Creating the [$Path] event hub in the [$Namespace] namespace: PartitionCount=[$PartitionCount] MessageRetentionInDays=[$MessageRetentionInDays]..."
    $EventHubDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.EventHubDescription -ArgumentList $Path
    $EventHubDescription.PartitionCount = $PartitionCount
    $EventHubDescription.MessageRetentionInDays = $MessageRetentionInDays
    $EventHubDescription.UserMetadata = $UserMetadata
    $NamespaceManager.CreateEventHub($EventHubDescription);
    Write-Host "The [$Path] event hub in the [$Namespace] namespace has been successfully created."
}

# Create the consumer group if not exists
Write-Output "Creating the consumer group [$ConsumerGroupName] for the [$Path] event hub..."
$ConsumerGroupDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.ConsumerGroupDescription -ArgumentList $Path, $ConsumerGroupName
$ConsumerGroupDescription.UserMetadata = $ConsumerGroupUserMetadata
$NamespaceManager.CreateConsumerGroupIfNotExists($ConsumerGroupDescription);
Write-Host "The consumer group [$ConsumerGroupName] for the [$Path] event hub 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."

Note 1: as highlighted in the comments, make sure to load the latest version of the Microsoft.ServiceBus.dll assembly in the script.

Note 2: you can follow the same approach to create topics, queues, subscriptions and notification hubs instead of event hubs.

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

powershell .\CreateEventHub.ps1 -Path ioteventhub -PartitionCount 32 -MessageRetentionInDays 3 -UserMetadata 'This event hub is used by the devices of the IoT solution' -ConsumerGroupName iotconsumergroup -ConsumerGroupUserMetadata 'This consumer group is used by the IoT solution' -Namespace iotsolution -Location 'West Europe'

CommandPrompt

I’d like to remark that this kind of scripts should be:

  • parametric to be reusable
  • included in the source control system (Visual Studio Online or GitHub) along with the solution and versioned as the application code
  • executed as part of the Continuous Delivery process used to automatically deploy the solution to a QA environment when a new version of the application is built

In fact, you probably heard the term DevOps more and more times. The term remarks the need to integrate development and operations tasks to build software solutions efficiently over time. This goal can be achieved using a process in which you develop an application, deploy it, learn from production usage of it, change it in response to what you learn, and repeat the cycle quickly and reliably.

To achieve this result, you have to build a development and deployment cycle that is repeatable, reliable, predictable, and has low cycle time. In particular, to create the staging and production environment for an Azure application and to deploy the solution in an automated way and integrate this task in the Continuous integration (CI) and Continuous delivery (CD) processes, you should use parametric PowerShell scripts.    

Note: Continuous integration (CI) means that whenever a developer checks in code to the source repository, a build is automatically triggered. Continuous delivery (CD) takes this one-step further: after a build and automated unit tests are successful, you automatically deploy the application to an environment where you can do more in-depth testing.

You can download the script along with the PowerShell scripts to create queues, topics and Subscription on MSDN Code Gallery: Service Bus PowerShell Scripts


Comments (21)

  1. Radu Vunvulea says:

    Hello,

    I tried to run the solution but I getting the following exception that the functions "EventHubExists" was not found. I'm loading the ServiceBus assembly with the version 2.5.41204.0.

    I tried in the following ways:

    Add-Type -Path ".Microsoft.ServiceBus.dll"

    Add-Type -Path ".Microsoft.ServiceBus.dll" -ReferencedAssemblies "System.Runtime.Serialization.dll"

    , but still I support that the assembly is not loaded correctly. I have at the same level the SB assembly. Do you have any ideas?

  2. Radu Vunvulea says:

    Found the problem. The script should be run directly from cmd or PowerShell ISE

  3. Hi Radu… better so 😉 Thanks for the feedback!

  4. Venkatesh says:

    Hi Paalo, I am trying to create Topic with the scripts, but I am consistently getting this error "Add-Type : Could not load file or assembly 'file:///D:DeployCreateTopicMicrosoft.ServiceBus.dll' or one of its

    dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)" I have latest Azure PowerShell installed and I am referring to the latest version of ServiceBus DLL

  5. Did you check the path and version of the Microsoft.ServiceBus.dll library?

    Ciao

    Paolo

  6. alex says:

    when i run methods from PowerShell ISE it complains about missing methods EventHubExists , CreateEventHubIfNotExists

    i run

    Add-Type -Path "C:…ServiceBusExplorerpackagesWindowsAzure.ServiceBus.2.7.3libnet40-fullMicrosoft.ServiceBus.dll"

    $NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($CurrentNamespace.ConnectionString);

    and

    $NamespaceManager | gm

    does not have EventHubExists , CreateEventHubIfNotExists

    same error – missing $NamespaceManager.EventHubExists   when i run scripts from PM Console from Visual Studio 2013 (but if i put some code in C#, then it shows method presense:

    var nm = new NamespaceManager("");

    var b2 = nm.EventHubExists("asdf");  // no compile error here….

    ).

    any help appreciated, thanks

  7. alex says:

    found the problem – multiple ServiceBus packages were instelled (from 2.4..) when i deleted all except latest WindowsAzure.ServiceBus.2.7.2, WindowsAzure.ServiceBus.2.7.3 – those methods became available in powershell.

  8. It's great to see people finding the right answer by themselves 😉

    Ciao

    Paolo

  9. Alex Turetsky says:

    Hi Paolo,

    Thanks a lot for the detailed description. The script works great and it saves me a lot of time. One thing that I'm currently struggling is that I can't find a way to specify Shared Access Policy Rules for an Event Hub. Basically I can't create an instance of Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule object in PowerShell. Do you have any samples how that can be done?

    Thanks in advance,

    Alex

  10. Hi Alex

    thanks for the positive feedback 😉 I don't have time to change the script to add a SAS policy rule, but I'll show you a C# snippet to accomplish this task. 🙂

    authorizationRule = new SharedAccessAuthorizationRule(SenderSharedAccessKey,

                                                                                               SharedAccessAuthorizationRule.GenerateRandomKey(),

                                                                                               new[]

                                                                                               {

                                                                                                   AccessRights.Send

                                                                                               });

    eventHubDescription.Authorization.Add(authorizationRule);

    await namespaceManager.UpdateEventHubAsync(eventHubDescription);

    Ciao

    Paolo

  11. Alex Turetsky says:

    That's exactly what I was trying to implement in Powershell.

           $Key = [Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule]::GenerateRandomKey()

           $Rights = [Microsoft.ServiceBus.Messaging.AccessRights]::Listen, [Microsoft.ServiceBus.Messaging.AccessRights]::Send

           $AccessRule = New-Object -TypeName  Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule -ArgumentList "SendReceiveRule", $Key, (,$Rights)

           $EventHubDescription.Authorization.Add($AccessRule)

           $NamespaceManager.CreateEventHub($EventHubDescription)

    Unfortunately it doesn't work. Powershell complains about SharedAccessAuthorizationRule constructor =(

  12. Alex Turetsky says:

    I found a way to do it =)

    One extra step was needed:

           $Key = [Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule]::GenerateRandomKey()

           $Rights = [Microsoft.ServiceBus.Messaging.AccessRights]::Listen, [Microsoft.ServiceBus.Messaging.AccessRights]::Send

           $RightsColl = New-Object -TypeName System.Collections.Generic.List[Microsoft.ServiceBus.Messaging.AccessRights] (,[Microsoft.ServiceBus.Messaging.AccessRights[]]$Rights)

           $AccessRule = New-Object -TypeName  Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule -ArgumentList "SendReceive", $Key, $RightsColl

           $EventHubDescription.Authorization.Add($AccessRule)

    Thanks again!

  13. Thanks Alex! I will update the script when I have some spare time! 😉

    Ciao

    Paolo

  14. Pradebban Raja says:

    found the problem – multiple ServiceBus packages were instelled (from 2.4..) when i deleted all except latest WindowsAzure.ServiceBus.2.7.2, WindowsAzure.ServiceBus.2.7.3 – those methods became available in powershell.

    How to delete other installed version of ServiceBus Packages.

    Am trying to use this method in a deployment server, with Visual Studio Installed. How to get 2.7.2 and 2.7.3 packages installed ?

    Thanks

  15. Pradebban Raja says:

    This is what am trying to do,

    Create a EventHub and create a shared access policy

    # Loading assembly from the ServiceBus Explorer downloaded

    $asm = [System.Reflection.Assembly]::LoadFrom("D:testMicrosoft.ServiceBus.dll");

    $nmType = $asm.GetType("Microsoft.ServiceBus.NamespaceManager");

    $info = $nmType.GetMethod("CreateFromConnectionString");

    $NamespaceManager = $info.Invoke($null, $CurrentNamespace.ConnectionString);

    # Check if the event hub already exists

    if ($NamespaceManager.EventHubExists($Path)) # This method exists in the local dll loaded / not from Azure SDK dlls (2.5)

    {

       Write-Verbose "The [$Path] event hub already exists in the [$Namespace] namespace."

    }

    else

    {

       Write-Output "Creating the [$Path] event hub in the [$Namespace] namespace: PartitionCount=[$PartitionCount] MessageRetentionInDays=[$MessageRetentionInDays]…"

       $EventHubDescription = New-Object -TypeName Microsoft.ServiceBus.Messaging.EventHubDescription -ArgumentList $Path

       $EventHubDescription.PartitionCount = $PartitionCount

       $EventHubDescription.MessageRetentionInDays = $MessageRetentionInDays

       $EventHubDescription.UserMetadata = $UserMetadata

      $Key = [Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule]::GenerateRandomKey()

      $Rights = [Microsoft.ServiceBus.Messaging.AccessRights]::Manage, [Microsoft.ServiceBus.Messaging.AccessRights]::Listen,  [Microsoft.ServiceBus.Messaging.AccessRights]::Send

      $RightsColl = New-Object -TypeName System.Collections.Generic.List[Microsoft.ServiceBus.Messaging.AccessRights] (,[Microsoft.ServiceBus.Messaging.AccessRights[]]$Rights)

      $AccessRule = New-Object -TypeName  Microsoft.ServiceBus.Messaging.SharedAccessAuthorizationRule -ArgumentList $ShareAccessRuleName, $Key,   $RightsColl

      $EventHubDescription.Authorization.Add($AccessRule)

      Write-Verbose ""

      Write-Verbose " Added Share Access Policy to the Event Hub"

      $NamespaceManager.CreateEventHub($EventHubDescription);

      Write-Host "The [$Path] event hub in the [$Namespace] namespace has been successfully created."

    }

    Am getting the below error when trying to add Access Rule,

    Cannot find an overload for "Add" and the argument count: "1".

    At line:1 char:1

    + $EventHubDescription.Authorization.Add($AccessRule)

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

       + CategoryInfo          : NotSpecified: (:) [], MethodException

       + FullyQualifiedErrorId : MethodCountCouldNotFindBest

    Any help!!

  16. Hi Pradebban

    The error is clear even if it's strange as the AuthorizationRules.Add method expects one argument. See msdn.microsoft.com/…/microsoft.servicebus.messaging.authorizationrules.add.aspx. By the way, look at the message by Alex Turetsky on this thread. He was able to accomplish the same task that you are trying to achieve, that is, create a custom shared access policy.

    Ciao

    Paolo

  17. Pradebban Raja says:

    Hi Paolo

    Thanks for the response. Yes i tried to implement using the same snippet. However was not able to find the method, $NamespaceManager.EventHubExists

    I made the below change to explicitly use the dll which i got along with Service Bus Explorer

    $asm = [System.Reflection.Assembly]::LoadFrom("D:testMicrosoft.ServiceBus.dll");

    $nmType = $asm.GetType("Microsoft.ServiceBus.NamespaceManager");

    $info = $nmType.GetMethod("CreateFromConnectionString");

    $NamespaceManager = $info.Invoke($null, $CurrentNamespace.ConnectionString);

    However, there is version mismatch issues with Microsoft.ServiceBus.dll and i suspect that being the reason of failure of  AuthorizationRules.Add method

    How can i get the nuget package of the latest Version. I would prefer to install the modules rather than needing a solution to install the package nuget.

    Please note: The latest version of Azure Powershell modules (2.6) gets the Microsoft.ServiceBus.dll which is not same as the one i get from the service Bus Explorer.

    I would need the Azure modules for most of other automation and make this Event Hub share access policy work. Basically i would need, both work together.

    Excuse for any wrong assumptions. I am relatively new to .net and powershell

    Thanks!

  18. Giulio says:

    Need help…I'm a beginner…following the solution by Alex Turetsky the Rule is added, but for the time of the session. (I can't see from portal; and if I close and reopen the shell the rule is not present.

    What's my mistake?

    Thanks

  19. Giulio says:

    Sorry to all…

    Just Solved: $SbnMan.UpdateEventHub($EventHubDescription)

    Thanks!

  20. Thanks Giulio for the feedback!

    Ciao

    Paolo

  21. Avi Siboni says:

    thanx a lot Paolo Salvatori its really help me !!!

    and thank u Alex Turetsky  your sharing help me too 🙂

Skip to main content