locked
How to call Azure Service Bus - Generic Method in PowerShell BrokeredMessage.GetBody<>()? RRS feed

  • Question

  • Import-Module ".\Microsoft.ServiceBus.dll" 
    
    $connectionString = "Endpoint=sb://...."
    
    $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
    $message = [Microsoft.ServiceBus.Messaging.BrokeredMessage] $client.Receive([System.TimeSpan]::FromSeconds(5))
        if ($message -ne $null) {
            $message.GetType().GetMethod("GetBody").MakeGenericMethod([String]).Invoke()
    
            # Getting an error message for the above Invoke()
        }
        else {
            Write-Host 'Zero Message in the Queue'
        }
        $client.Close()
    }
    

    Error Message:

    Exception calling "GetMethod" with "1" argument(s): "Ambiguous match found."
    At AzureServiceBusTest.ps1:23 char:3
    +         $message.GetType().GetMethod("GetBody").MakeGenericMethod([St ...
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
        + FullyQualifiedErrorId : AmbiguousMatchException

    If I am using GetMethods instead of GetMethod (I get)

    the following error:

    Cannot convert argument "bindingAttr", with value: "GetBody", for "GetMethods" to type
    "System.Reflection.BindingFlags": "Cannot convert value "GetBody" to type "System.Reflection.BindingFlags". Error:
    "Unable to match the identifier name GetBody to a valid enumerator name. Specify one of the following enumerator
    names and try again:
    Default, IgnoreCase, DeclaredOnly, Instance, Static, Public, NonPublic, FlattenHierarchy, InvokeMethod,
    CreateInstance, GetField, SetField, GetProperty, SetProperty, PutDispProperty, PutRefDispProperty, ExactBinding,
    SuppressChangeType, OptionalParamBinding, IgnoreReturn""
    At AzureServiceBusTest.ps1:23 char:3
    +         $message.GetType().GetMethods("GetBody").MakeGenericMethod([S ...
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : NotSpecified: (:) [], MethodException
        + FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument
     

    1. Do you know how to make this Work ?

    I am very much interested in knowing how to call generic method from PowerShell.

    2. I have follow instruction from this page to Install AzureRM

    https://docs.microsoft.com/en-us/powershell/azure/get-started-azureps?view=azurermps-3.8.0

    But I can't find sample to how use AzureRM CmdLet

    - to Receive Message from Message Queue

    3. How to receive individual message from PowerShell (one by one from Azure Service Bus ?)

    and mark only them as complete when the message has been consume and processed. 

    Many Thanks.

    Regards Dat.

    Thursday, May 4, 2017 9:50 AM

Answers

  • Here is my simple working solution (send/receive using MicrosoftAzure.ServiceBus Library) from PowerShell

    Hope this would help future user who stumble into this post.

    Save the following script into testazureservicebus.ps1 (or any file name with .ps1 extension)

    The following script read the following 2 file
    * connectionstring.txt
    * testdata.json

    Clear-Host
    # Download using Nugget (Visual Studio Package Manager) MicrosoftAzure.ServiceBus 4.0
    Import-Module ".\WindowsAzure.ServiceBus.4.0.0\lib\net45-full\Microsoft.ServiceBus.dll"
    
    # Connection String - Copy from your Queue
    # Login to Azure Portal
    # Navigate to > Your Subscriped Service Bus > Overview 
    # > Your Queue > Shared access policies > Your Policy > Copy the connection string
    $connectionString = (get-content '.\connectionstring.txt') -join "`r`n"
    
    # my test data was just { "greeting":"Hello World" }
    $payload = (Get-Content '.\testdata.json') -join "`r`n"
    
    function SendMessage($message) {
        $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
        $message = New-Object Microsoft.ServiceBus.Messaging.BrokeredMessage($message);
        $client.Send($message)
        if ($client -ne $null) {
            $client.Close()
        }
    }
    
    function ReceiveMessage() {
        $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
        $message = [Microsoft.ServiceBus.Messaging.BrokeredMessage] $client.Receive([System.TimeSpan]::FromSeconds(5))
        if ($message -ne $null) {
            Write-Host 'Message Id:' $message.MessageId
            Write-Host 'Message Body:' 
    
            $BindingFlags= [Reflection.BindingFlags] "Public,Instance"
            $generic_method = $message.GetType().GetMethod("GetBody",$BindingFlags,$null, @(),$null).MakeGenericMethod([String])
            $generic_method.Invoke($message,$null)
    
        }
        else {
            Write-Host 'Zero Message in the Queue'
        }
    
        $client.Close()
    }
    
    # Send Message to the Queue
    SendMessage $payload
    
    # Receive Message from the Queue
    ReceiveMessage
    Thank again Serkant Karacafor and Samee.Patel

    • Marked as answer by Dati.MCAD Friday, May 5, 2017 11:55 PM
    • Edited by Dati.MCAD Saturday, May 6, 2017 10:42 PM Forgot to thanks Samee.Patel
    Friday, May 5, 2017 11:50 PM

All replies

  • The problem here is PowerShell goes crazy with a generic method that is overloaded. For this you will have to get the exact method and then use MakeGenericMethod on it. Below code will help.

    Import-Module ".\Microsoft.ServiceBus.dll"
    $connectionString = "Endpoint=sb://...."
    $BindingFlags= [Reflection.BindingFlags] "Public,Instance"
    $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
    $message = [Microsoft.ServiceBus.Messaging.BrokeredMessage] $client.Receive([System.TimeSpan]::FromSeconds(5))
        if ($message -ne $null) {
            $message.GetType().GetMethod("GetBody",$BindingFlags,$null, @(),$null).MakeGenericMethod([String]).Invoke()

            # Getting an error message for the above Invoke()
        }
        else {
            Write-Host 'Zero Message in the Queue'
        }
        $client.Close()
    }

    Your second question on RM CmdLet is very generic. Please provide more details on what you exactly want to ask.

    Friday, May 5, 2017 6:04 PM
  • Thank you Serkant Karaca and Samee.Patel

    I have manage to get it working with your suggested code:

    Here is the amended code:

    $BindingFlags= [Reflection.BindingFlags] "Public,Instance"

    $message.GetType().GetMethod("GetBody",$BindingFlags,$null, @(),$null).MakeGenericMethod([String]).Invoke($message,$null)

    Note:Invoke method need to pass in $message, $null

    Regards Dat.


    • Edited by Dati.MCAD Saturday, May 6, 2017 10:45 PM Forgot to thanks Samee.Patel
    Friday, May 5, 2017 11:48 PM
  • Here is my simple working solution (send/receive using MicrosoftAzure.ServiceBus Library) from PowerShell

    Hope this would help future user who stumble into this post.

    Save the following script into testazureservicebus.ps1 (or any file name with .ps1 extension)

    The following script read the following 2 file
    * connectionstring.txt
    * testdata.json

    Clear-Host
    # Download using Nugget (Visual Studio Package Manager) MicrosoftAzure.ServiceBus 4.0
    Import-Module ".\WindowsAzure.ServiceBus.4.0.0\lib\net45-full\Microsoft.ServiceBus.dll"
    
    # Connection String - Copy from your Queue
    # Login to Azure Portal
    # Navigate to > Your Subscriped Service Bus > Overview 
    # > Your Queue > Shared access policies > Your Policy > Copy the connection string
    $connectionString = (get-content '.\connectionstring.txt') -join "`r`n"
    
    # my test data was just { "greeting":"Hello World" }
    $payload = (Get-Content '.\testdata.json') -join "`r`n"
    
    function SendMessage($message) {
        $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
        $message = New-Object Microsoft.ServiceBus.Messaging.BrokeredMessage($message);
        $client.Send($message)
        if ($client -ne $null) {
            $client.Close()
        }
    }
    
    function ReceiveMessage() {
        $client = [Microsoft.ServiceBus.Messaging.QueueClient]::CreateFromConnectionString($connectionString)
        $message = [Microsoft.ServiceBus.Messaging.BrokeredMessage] $client.Receive([System.TimeSpan]::FromSeconds(5))
        if ($message -ne $null) {
            Write-Host 'Message Id:' $message.MessageId
            Write-Host 'Message Body:' 
    
            $BindingFlags= [Reflection.BindingFlags] "Public,Instance"
            $generic_method = $message.GetType().GetMethod("GetBody",$BindingFlags,$null, @(),$null).MakeGenericMethod([String])
            $generic_method.Invoke($message,$null)
    
        }
        else {
            Write-Host 'Zero Message in the Queue'
        }
    
        $client.Close()
    }
    
    # Send Message to the Queue
    SendMessage $payload
    
    # Receive Message from the Queue
    ReceiveMessage
    Thank again Serkant Karacafor and Samee.Patel

    • Marked as answer by Dati.MCAD Friday, May 5, 2017 11:55 PM
    • Edited by Dati.MCAD Saturday, May 6, 2017 10:42 PM Forgot to thanks Samee.Patel
    Friday, May 5, 2017 11:50 PM
  • Your second question on RM CmdLet is very generic. Please provide more details on what you exactly want to ask.

    I am currently using MicrosoftAzure.ServiceBus Library, I was wondering whether AzureRM CmdLet would make life easier to send and receive message from the Queue. I also notice from google search there are sample code and also there is another way was using factory (I was so confuse, therefore I just want to try a simple send/receive)

    Therefore my Second Question is can I use AzureRM to Send and Receive Message from the Queue, if yes do you have any example of how ? I find with Azure Service Bus, I have to grab bit and pieces of code to just get a simple scenario working.

    I was trying out DocumentDB, by creating from the Azure Portal and it was having a getting start which have a complete code solution.

    Saturday, May 6, 2017 12:05 AM