Finding and using .Net code to work with Powershell

I’ve been looking through Kent Agerlund SCCM tools module and came across this :

Function Set-CMCollectionQueryRule
{
    [CmdletBinding()]
    Param(
         [Parameter(Mandatory=$True,HelpMessage="Please Enter Primary Server Site Server")]
                $SiteServer,
         [Parameter(Mandatory=$True,HelpMessage="Please Enter Primary Server Site code")]
                $SiteCode,
         [Parameter(Mandatory=$True,HelpMessage="Please Enter the query for collection")]
                $Query,
         [Parameter(Mandatory=$True,HelpMessage="Please Enter the query name")]
                $QueryName,
         [Parameter(Mandatory=$True,HelpMessage="Please Enter the query type eg. User or Device")]
         [ValidateSet("User","Device")]
                $QueryType,       
         [Parameter(Mandatory=$True,HelpMessage="Please Enter the collection name where do you want to set new rule")]
                $CollectionName     
         )
         
     $Class = "SMS_CollectionRuleQuery"
     [Array]$ColRules
     
     Switch($QueryType)
     {
        "User" {$QueryTypeNumber = 1}
        "Device" {$QueryTypeNumber = 2}
     }
     
     If(($RuleCollection = Get-CMCollection -SiteCode $SiteCode -SiteServer $SiteServer -Filter "Name='$CollectionName' and CollectionType='$QueryTypeNumber'") -eq $Null){
         Write-Host "There is no such $QueryType collection like: $CollectionName"
     }
     Else{
     
        If((Get-CMQueryValidation -SiteCode $SiteCode -SiteServer $SiteServer -Query $Query)){
               
            $ColRules += ([WMI]$RuleCollection.__PATH).CollectionRules
            
            Try{       
                $NewRule = ([WMIClass]"\\$SiteServer\root\SMS\Site_$($SiteCode):$Class").CreateInstance()
                $NewRule.QueryExpression = $Query
                $NewRule.RuleName = $QueryName
                       
                  $ColRules += [System.Management.ManagementBaseObject]$NewRule
                   
                $RuleCollection.CollectionRules = $ColRules
                $RuleCollection.Put()
            }
            Catch{
                Write-Host "Error: $($_.Exception.Message)"
            }
         }
         Else{
            Write-Host "Please check your query rule syntax"
         }

     }
      

}

I saw the use of this command

$ColRules += [System.Management.ManagementBaseObject]$NewRule

How would you know to use this .net type ? I know people will say google and look at the MSDN documentation, but that can be confusing. How would I know that I need a .net type to over come a problem or enhance a script ? I see a lot of snippets of .net in peoples script and wonder how they work out how to use this sort of thing ? A .net background ?

Hi Graham,

It’s one of the classes used by WMI if i recall right.

I don’t have SCCM to hand, but I’m pretty certain that $newRule returns this type of object already. So it could literally just be that at one point he did.

$NewRule.GetType()

And saw the object type, and is forcing a cast.

PowerShell’s not a strongly typed language though, so it is not so often that you need to do casting, unless either you need to do a transformation of type that does not dynamically happen, or it is not supported by another method or property you need to use.

The best way to check i think would be do use the code but without the

[System.Management.ManagementBaseObject]
cast. Put a breakpoint on the $ColRules += line, and then run the code.

When it halts, enter

$NewRule.GetType() | FL *

into the console, and look for the FullName property.

It’s definitely a learning curve there. The .NET Framework is quite large, and you can always learn something more. However, you can tend to cheat a bit by searching the internet for examples of how to do something in C#, and then convert that code to PowerShell.

Thanks Dave and Tim. It’s certainly a big beast, just knowing when and how to use it to improve or do a function PowerShell can’t natively do on its on.

while we are on this topic of Dot net and using in powershell there are a few good posts on Using enumerations. That I really have found are useful for functions that you create in powershell especially for parameter validation.

SEE these two posts:

http://mikefrobbins.com/2015/06/15/using-a-net-enumeration-for-powershell-parameter-validation/

They are really cool when you are looking for something to help you with validating that you get the right data passed to your function.

Thanks Thom. So trying to understand ENUM’s.

I found this description:

"Enumerations are special sets of named values which all maps to a set of numbers, usually integers. They come in handy when you wish to be able to choose between a set of constant values, and with each possible value relating to a number, they can be used in a wide range of situations. As you will see in our example, enumerations are defined above classes, inside our namespace. This means we can use enumerations from all classes within the same namespace. "

But can’t quite get it to process in my head. Could anyone help simplify it? Also how is this useful?

Thanks !

Probably the best way to summarise it is that you can have a piece of text that .NET actually translates into another type. It makes it easier to work with some items without having to remember specific values.

A classic example of this would be colors. Instead of you having to specify RGB values for a lot of colours, you can use a name. Take Black, which has an RGB value of 0,0,0. Instead of having to provide those numbers, you can often refer to the color by name.

 $HOST.UI.RawUI.BackgroundColor= "Black"

PowerShell handles finding out what Black actually represents and deals with the rest.

A bit more advanced, but another use of Enums is for combining flags, where you can have a single object with multiple possibilities of values. Take mixing two well known colors together, red and blue. Without using enums, you’d need to look up the two RGB values and then run a function that performed this.

Instead, with enums, you might be able to do something like this (ficticious example)

$newcolor = [color]::red + [color]::blue

SCCM uses enums quite a lot, so it’s worthwhile looking into these like Thom said.

Hope this helps!

Sorry Tim, just getting my head around this. So if the enum [color] ? I thought this was the “type” ? Might have not processed this correctly.

No worries. I found a Scripting Guy article, which is a great read into enums and also has much better examples. Have a look at that.

http://blogs.technet.com/b/heyscriptingguy/archive/2013/01/20/weekend-scripter-using-net-framework-enumerations-in-windows-powershell.aspx

Thanks Tim, i’ll have a read and play !
Just wanted to add that i’ve looked at your website, http://www.powershell.amsterdam/, and how impressed i am, its great. It would be great to chat to you about Powershell and such. My e-mail is graham.beer@outlook.com. Thanks again for your help.