working with -ge and -le

hey guys, struggling to understand why this is happening.

I’ve written a script to go out to our Azure ServiceBus, check the message count in the message queues, then call up a function to scale the instances if that count is greater or less than specified thresholds. However, I’ve noticed that the first set of If/Elseif/Else works fine, however, the second set does not and it appears to be due to the comparison statements. Here’s more script:

$clientTriggerOut = "50"
$clientTriggerIn = "25"
$ServerTriggerOut = "2000"
$ServerTriggerIn = "1000"

$queueAR = "Client", "Server"

foreach ($i in $queueAR){
$queue = $i
Get-AzureRmServiceBusqueue -ResourceGroupName servicebus -NamespaceName  -Name $Queue 
Get-AzureRmServiceBusqueue -ResourceGroupName servicebus -NamespaceName  -Name $Queue | Select MessageCount | Export-csv -Path "\\Server\c$\Temp\Azure Scripts\ServiceBus\$queue.txt" -NoTypeInformation
$MessageCount = (Get-Content "\\Server\c$\Temp\Azure Scripts\ServiceBus\$queue.txt" | Select-Object -Skip 1 | Out-String) -replace '"'

if ($queue -match "Client"){
     If ($MessageCount -le $clientTriggerIn){
       write-host "in"    #Clientin
           }
    elseif ($MessageCount -ge $Clienttriggerout) {
       write-host "out"     #Clientout

           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
}

elseif ($queue -match "Server"){

     If ($MessageCount -le $ServerTriggerIn){
     write-host "in"      #Serverin
           }
    elseif ($MessageCount -ge $Servertriggerout) {
        write-host "out"   #Serverout
           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
 }
else {Write-Host "Didn't work Bob!"}

}

When I run this right now, Client comes back with 0 messages and write-host tells me “in”. That’s good since the IN trigger is 25.

However, when it gets to server, the count is currently 541 which is less than or equal to the IN trigger, however, that comparison comes back false, moves on to the out trigger and comes back true, thus write-host returns “out”.

My understanding is that $messagecount -ge $servertriggerout should return a boolean value of $true if $messagecount (541) is greater than or equal to $servertriggerout (2000) and $false if not.

So what am I missing here?

Also, if you know of a better way to format the message count value so that its just the numerical value without any headers or spaces please let me know.

I’m curious as to why you’ve defined those initial values as strings rather than as integers?

Cause I don’t know any better obviously ;-).
I’ve only been in powershell for about a year so by all means if you see something not quite right let me know.

Yeah, I’d drop the quotes. When you ask PowerShell to compare strings, in terms of less or greater, it thinks about them in terms of their lengths. It isn’t going to implicitly make those into numeric values. But if you define them as numbers you should get the results you’re expecting.

For example, try:

“55” -gt “00001”

versus

55 -gt 00001

And, BTW, it takes the first operand as its cue for the data type if it’s going to do coercion.

“5” + 5

versus

5 + “5”

As another example you can try to see how the behavior changes.

Oh, you also asked:

Also, if you know of a better way to format the message count value so that its just the numerical value without any headers or spaces please let me know.

Write-Host isn’t how you want to create output in PowerShell. It kills puppies. You probably want to construct an object and output that to the pipeline. For example:

$props = @{'ClientName'=$clientName
           'MessageCount'=$messageCount}
New-Object -Type PSObject -Prop $props

That will let PowerShell engage its formatting system to display the output on-screen. I’ve a lovely couple of books about all this if you’re interested ;).

That makes more sense. So I’ve removed the double quotes from the trigger variables and added [int] before $messagecount so I wouldn’t have to rearrange things and their now returning the expected results.

So it now looks like this


$clientTriggerOut = 50
$clientTriggerIn = 25
$ServerTriggerOut = 2000
$ServerTriggerIn = 1000

$queueAR = "client", "server"

foreach ($i in $queueAR){
$queue = $i
Get-AzureRmServiceBusqueue -ResourceGroupName servicebus -NamespaceName  -Name $Queue 
Get-AzureRmServiceBusqueue -ResourceGroupName servicebus -NamespaceName  -Name $Queue | Select MessageCount | Export-csv -Path "\\server\c$\Temp\Azure Scripts\ServiceBus\$queue.txt" -NoTypeInformation
$MessageCount = (Get-Content "\\server\c$\Temp\Azure Scripts\ServiceBus\$queue.txt" | Select-Object -Skip 1) -replace '"'

if ($queue -match "client"){
     If ([int]$MessageCount -le $clientTriggerIn){
       write-host "in"    #Clientin
           }
    elseif ([int]$MessageCount -ge $Clienttriggerout) {
       write-host "out"     #Clientout

           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
}

elseif ($queue -match "server"){

     If ([int]$MessageCount -le $ServerTriggerIn){
     write-host "in"      #Serverin
           }
    elseif ([int]$MessageCount -ge $Servertriggerout) {
        write-host "out"   #Serverout
           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
 }
else {Write-Host "Didn't work Bob!"}

}

Would you mind expounding on your formatting recommendation though? I’m not sure i understand what this is doing or where it should go.

$props = @{‘ClientName’=$clientName
‘MessageCount’=$messageCount} New-Object -Type PSObject -Prop $props

oh also, the script won’t actually use write-host, i’m just using it to verify that the if/else statements are working properly. I’ve commented out the function calls so that they won’t trigger while i’m testing. a $true will call a function to either spin up a new instance or remove one using a function that i did not include here.

Also book recommendations are great!

Write-Verbose would be a suitable replacement for the way you’re using Write-Host.

Output from a PowerShell script/function/whatever should be objects. Objects are basically a data structure, where you create properties to contain bits of information. PowerShell’s formatting commands - like Format-Table, ConvertTo-HTML, etc - all understand objects. So if you get your output into that kind of data structure, it becomes a lot easier to consume that output in various ways, format it in various ways, etc. As opposed to just dumping out numbers or strings. This is, in fact, the entire reason PowerShell exists (object-based output) and is what MS has patents on. It’s what makes PowerShell not Bash.

Ok,

I think I understand what you’re saying. Based on that, this would be the better way to do it.

Get-AzureRmServiceBusQueue -ResourceGroupName servicebus -NamespaceName -Name $Queue  <---will be removed in final $messages = Get-AzureRmServiceBusQueue -ResourceGroupName servicebus -NamespaceName  -Name $Queue | Select MessageCount
$MessageCount = $messages.MessageCount
if ($queue -match "client"){
     If ($MessageCount -le $clientTriggerIn){
       Clientin
           }
    elseif ($MessageCount -ge $Clienttriggerout) {
       Clientout

           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
}

elseif ($queue -match "server"){

     If ($MessageCount -le $ServerTriggerIn){
     Serverin
           }
    elseif ($MessageCount -ge $Servertriggerout) {
     Serverout
           }
    else {Write-Host "Uhhhhh.... Something went wrong"}
 }
else {Write-Host "Didn't work Bob!"}

}

I’d use Write-Warning instead of Write-Host when something goes wrong if you want the processing to continue. if you want it to stop use throw