Getting the $Value of True

This topic contains 12 replies, has 2 voices, and was last updated by Profile photo of Graham Beer Graham Beer 2 years, 3 months ago.

  • Author
    Posts
  • #24203
    Profile photo of Graham Beer
    Graham Beer
    Participant

    In my SCCM task sequence i'm trying to get the values of the ZTIGather and put the option that comes back true to a variable. So far i can get a result list of 'false, false and true' Which tells me its working. Just not sure how i can get out the "$true" value.

    $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment

    $Type = @{ "Desktop" = $Desktop = ('IsDesktop')
    "Laptop" = $Laptop = ('IsLaptop')
    "VM" = $VM = ('IsVM')
    }

    foreach ($Model in $Type.Values)
    {($TSEnv.value($Model))}

    Can anyone help ?

  • #24206
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    You probably want to generate an object with the results:

    $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
    $models = "IsDesktop", "IsLaptop", "IsVM" | foreach{
        New-Object -TypeName PSObject -Property @{"TSVariable"=$_;"Value"=$($TSEnv.value($_))}
    }
    
    $models | Where{$_.Value -eq "True"}
    

    What you need to understand is that the values are strings, not Boolean values (e.g. $true\$false). If you wanted to convert them to Boolean values (http://www.jonathanmedd.net/2012/05/powershell-quick-tip-converting-a-string-to-a-boolean-value.html), then you could use $true for comparison:

    $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
    $models = "IsDesktop", "IsLaptop", "IsVM" | foreach{
        New-Object -TypeName PSObject -Property @{"TSVariable"=$_;"Value"=$([System.Convert]::ToBoolean($TSEnv.value($_)))}
    }
    
    $models | Where{$_.Value -eq $true}
    

    I didn't test this, but it should get you in the right direction.

  • #24207
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Thank you Rob. Been banging my head against a brick wall.

    I was so far off the correct script 🙁

  • #24208
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Would you be able to break it down to help me understand please Rob ?

  • #24213
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    Let's take the TS stuff out of the equation.

    #$TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
    
    #loop through the 3 varaibles and assign the output of the loop to $models
    $models = "IsDesktop", "IsLaptop", "IsVM" | foreach{
        #Create a new object with the property TSVariable and Value that is being returned to $models
        #In the Value, we take a string value and convert it to boolean
        New-Object -TypeName PSObject -Property @{"TSVariable"=$_;"Value"="True"}
    }
    

    No matter if it's a string or a Boolean value, your output would look like this:

    Value TSVariable
    —– ———-
    True IsDesktop
    True IsLaptop
    True IsVM

    However, if you look deeper, if we do the conversion to Boolean, we'll see this:

    PS C:\Users\rsimmers> $models[0].Value.GetType()
    
    IsPublic IsSerial Name                                     BaseType                                                                                               
    -------- -------- ----                                     --------                                                                                               
    True     True     Boolean                                  System.ValueType     
    

    If we change the line to

    New-Object -TypeName PSObject -Property @{"TSVariable"=$_;"Value"="True"}
    

    Now, True is a string.

    PS C:\Users\rsimmers> $models[0].Value.GetType()
    
    IsPublic IsSerial Name                                     BaseType                                                                                               
    -------- -------- ----                                     --------                                                                                               
    True     True     String                                   System.Object      
    

    At this point, you are doing string comparison, so checking if a string is a boolean value could give false-positive results. If you read through the article link, "This is because PowerShell will convert any string greater than 0 characters to a Boolean 'true'" You either have to test string to string, or boolean to boolean. Anything else is going to provide inconsistent results, especially across Powershell versions. It's better to cast or force the variable to the data type than assume Powershell is going to convert it for you. If you read some Powershell books, Powershell does do some automatic conversions, but there are rules:

    #This is basically just string concatenation, put these strings together.  If you are wrapping single or double quotes around it,  basically you saying it's a string...
    PS C:\Users\rsimmers> "10" + "30"
    1030
    #The first item takes precedence, so even though 30 is last, Powershell converts it to a string because the string preceded it
    PS C:\Users\rsimmers> "10" + 30
    1030
    #This is casting, basically saying that I want the data type to be an integer, now Powershell does the math
    PS C:\Users\rsimmers> [int]"10" + 30
    40
    # To the earlier point, an integer preceded the string, so Powershell converts the next number to a integer
    PS C:\Users\rsimmers> 30 + "30"
    60
    

    Understanding data types and what commands are expecting is integral to using Powershell. Passing a string when a command expects an integer could cause issue and when you see "Type Mismatch", that is basically saying you passed me something that is not was is defined. You passed me a letter and I expected a number. Hopefully this makes sense.

  • #24220
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Thanks Rob.

    New-Object -TypeName PSObject -Property @{"TSVariable"=$_;"Value"="True"}
    }

    Can you explain what is gong in in the {} please ?

  • #24223
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    It is a hash table. If you do "Get-Help New-Object", you will see that the -Property parameter is looking for IDictionary, which is base object of Hashtable. Back in vbScript days, we used the Dictionary object which basically was a key and a value to store data. There are several ways to create them like:

    PS C:\Users\rsimmers> $iDictionary = @{}
    
    PS C:\Users\rsimmers> $iDictionary.Add("MyColumn","MyValue")
    
    PS C:\Users\rsimmers> $iDictionary.GetType()
    
    IsPublic IsSerial Name                                     BaseType                                                                                               
    -------- -------- ----                                     --------                                                                                               
    True     True     Hashtable                                System.Object                                                                                          
    
    

    or short-hand like so:

    
    PS C:\Users\rsimmers> $iDictionary2 = @{"MyColumn"="MyValue"}
    
    PS C:\Users\rsimmers> $iDictionary2.GetType()
    
    IsPublic IsSerial Name                                     BaseType                                                                                               
    -------- -------- ----                                     --------                                                                                               
    True     True     Hashtable                                System.Object   
    

    They can get more complicated with nested tables, but basically we are defining the column (key) and the value assoicated with that column (key). In short-hand, semicolon (;) represents the end of a line to place multiple key\values in on step. If you have not yet, you need to really pick up the Month of Lunches book by Don and try to get a good foundation on these concepts.

  • #24224
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Awesome, thank you so much. Very much appreciated.

  • #24283
    Profile photo of Graham Beer
    Graham Beer
    Participant

    I hope someone can help as this is driving me crazy !

    I'm trying to, from Rob's brilliant script, just output the model. So, if for example i run it on a desktop i want it to come back with, if IsDesktop is true, just display "IsDesktop".

    I've been trying all sorts and i can't work it out ! problably some clever dude knows how i can already !

    Thanks.

  • #24284
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    $models | Where {$_.Value -eq $true} | Select -ExpandProperty TSVariable

  • #24287
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Thanks Rob, so easy when you know how ! I've been trying all sorts !

  • #24288
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    The way those variables are designed is that you would have a group of items in the TS that would be run if IsVM = True. Something like this:
    IsLaptop = True
    Install VPN Software
    Script for a laptop

    IsVM = True
    Install VM tools
    Disable unnecessary services
    Script for a VM

    However, if you wanted to use a single script to configure these services, you should modularize the code and make a function to get the variable. Here is an idea of how I would do it (not tested):

    
    function Get-TSModel {
        param()
        begin{
            $TSEnv = New-Object -ComObject Microsoft.SMS.TSEnvironment
        } #begin
        process{
            #loop through the 3 varaibles and assign the output of the loop to $models
            $models = "IsDesktop", "IsLaptop", "IsVM" | foreach{
                #Create a new object with the property TSVariable and Value that is being returned to $models
                #In the Value, we take a string value and convert it to boolean
                New-Object -TypeName PSObject -Property @{"TSVariable"=($_ -replace "Is", "");"Value"=$([System.Convert]::ToBoolean($TSEnv.value($_)))}
    
                $modelType = $models | Where {$_.Value -eq $True} | Select -ExpandProperty TSVariable
            } #models foreach
        }#process
        end {
            $modelType
        }#end
    }#function Get-TSModel
    
    
    
    switch (Get-TSModel) {
        "Desktop" {
            #Stuff for desktops
        }
        "Laptop" {
            #Stuff for laptops
        }
        "VM" {
            #Stuff for VMs
        }
    }
    
  • #24293
    Profile photo of Graham Beer
    Graham Beer
    Participant

    Again, thank you Rob. I'm running the script in SCCM so it will populate $tsenv.value("ModelType") with either IsVM, IsDesktop or IsLaptop. Then i can use a Task Sequence variable in against the various apps (i.e. wireless profile) for model type.

    For me its and excuse to learn PowerShell while working ! The more i do the more i hope it will help me learn.

    That script is very cool....

You must be logged in to reply to this topic.