Menu Close

Using a .NET Assembly in PowerShell when a cmdlet doesn’t exist

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:

Then I drilled down and quickly find “QueueDescription” class which looks like exactly what I need:

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 = "" #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.

1 Comment

  1. Christian Emond

    Hi Mr. Holman’s,
    Did you ever got the problem below :

    On my SCOM agent strictly, because when I’m running this powershell (with a frequency of 60 seconds/24/7) in [MTA] directly on the machine, i never get the problem.

    I have a UnitMonitorType hosting a homemade powershell script. A monitor use this script and runs once a day. In this script, I am loading IIS module/snapin named ‘WebAdministration’, this one is loaded to call some function needed to get my object (Get-WebSite, Get-WebBinding).

    The script is running well for hours and days. But sometimes, on some random instance, once the module is loaded, the code continue and it crash (not always) with the message : The specified module ‘WebAdministration’ was not loaded because no valid module file was found in any module directory.

    Since it is [MTA], i am suspecting that SCOM or a management pack is running a cleaning task simultaneously and unload my module …
    Do you have an idea of which task, management pack or anything else that can do that?


Leave a Reply

Your email address will not be published.