Using a .NET Assembly in PowerShell when a cmdlet doesn’t exist – a Microsoft Service Bus example


 

I was recently working with a customer who wanted to monitor the Queue Size of Microsoft Service Bus Queues.  We looked in Perfmon, and this value doesn’t exist. 

Next, I’d look in PowerShell to see if a PowerShell cmdlet exists that could deliver what I need.  Unfortunately – that didn’t exist either.

I have seen tools however, like Service Bus Explorer that would show the current Queue size, and this tool talked to an API, so I knew it must be possible to get.  One of the common methods to do this, is to load a .NET assembly (DLL) into PowerShell then invoke commands made possible.

I did a quick server for “Microsoft Service Bus API” and found:  https://msdn.microsoft.com/en-us/library/azure/microsoft.servicebus.aspx

Then I drilled down and quickly find “QueueDescription” class which looks like exactly what I need:  https://msdn.microsoft.com/en-us/library/azure/microsoft.servicebus.messaging.queuedescription.aspx

The easiest thing is to search the web and find script samples where other people worked on the same or similar namespaces, so you can better understand what you need to load in order to get at the data you are after.  Here is an example of my script:

param($NamespaceName, $QueueName, $HostName) #$NamespaceName = "ServiceBusDefaultNamespace" #$QueueName = "testqueue3" #$HostName = "sb01.opsmgr.net" #Provide a path to the DLL you wish to load that provides and SDK API $assemblyLocation = "C:\Program Files\Service Bus\1.1\Microsoft.ServiceBus.dll" #Load the .NET assembly [Void][System.Reflection.Assembly]::LoadWithPartialName("System") [Void][System.Reflection.Assembly]::LoadFile($assemblyLocation) #Create a connection string which is required for the service bus API for a given namespace in Service Bus $conn = "Endpoint=sb://" + $HostName + "/" +$NamespaceName + ";StsEndpoint=https://" + $HostName +":9355/" + $NamespaceName +";RuntimePort=9354;ManagementPort=9355" #Load the NamespaceManager Class from the connectionstring $NamespaceManager = [Microsoft.ServiceBus.NamespaceManager]::CreateFromConnectionString($conn) #Get the array of all queues in the namespace $Queues = $NamespaceManager.GetQueues() #Get the current Queue Size in bytes from the Queue object foreach ($queue in $Queues) { IF ($queue.Path -eq $QueueName) { $QueueSize = $queue.SizeInBytes } } $QueueSize

Essentially you must pass a path to the binaries, then load each one using “[System.Reflection.Assembly]::LoadFile”

In this case of Service Bus, each Service Bus Namespace contains queues, and queues could be named the same, so I need to first load the namespace and then match on the queues contained in it.

So we create a connection string to the namespace, then using NameSpaceManager I was able to get a queue by name within the Namespace.  From there, SizeInBytes is a simple property of the Queue object.  The script will simply output an integer of queue size in bytes.

My next project will be to wrap this script into something that SCOM can understand, as a performance collection rule or monitor.


Skip to main content