Jump to content


BzowK

Reading & Writing Task Sequence Variables in PowerShell

Recommended Posts

Hey Guys / Niall -

 

So I've got a bit of a challenge deploying some legacy apps right now. The installation process for many of these applications requires that files manually be copied to to local paths on the PC or certain registry settings added based on the location of the system. Easy to do with TS conditions, but finding a common variable between each of the locations is difficult. The locations they define are based on systems in specific OUs, but the OU formatting is different at each site (name of OU they give me could be at 3rd, 4th, or 5th level).

 

I want a universal solution that I can use for all and all pretty much define different steps by the name of the OU the system is in. Below is what I came up with and have been trying to put together, but haven't had much luck - especially since my PowerShell isn't that great.

 

The solution I came up with was to add the following in task sequences that needed it:

  1. Define TS variable for each name of OUs (which required different TS steps to be run)
  2. Per TS variable set above, run PowerShell script to grab system's DN then keyword search it for the TS variable's name
  3. If TS variable was found in DN string, set variable's value to TRUE else FALSE
  4. Create TS steps that copy the files as needed per site then set condition on it to run only if that site's TS variable had a TRUE value

As for the PowerShell portion of this, below is what I have so far with comments per line...

#Defines SCCM TS Variable Environment?
$tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
#Reads variable from Task Sequence
$v = $tsenv.Value("Site")
#Grabs system's DN from Registry
$dn = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\Machine") | Select-Object -ExpandProperty distinguished-name
#Searches DN string for TS Variable no matter case and sets it to $d (TRUE or FALSE)
$d = $dn.ToLower().Contains($v.ToLower())
#Sets the original TS Variable "Site" to TRUE or FALSE
$tsenv.Value("Site") = $d

So far, no luck. So - is what I'm doing even possible? If so, what am I missing - or - any idea for a better way to go about this, perhaps? I tried to thing of something WMI-based, but couldn't :(

 

Any ideas?

 

Share this post


Link to post
Share on other sites

Are the machines already in your database? You could create a collection based on each of the OUs and assign a collection variable to those collections. Where I work we have a collection for each OU so we can deploy OU specific software and I can easily define a variable to those collections. Those will be readable inside of your TS so you have the 'TRUE' set on whichever OUs actually require the file.

Share this post


Link to post
Share on other sites

can you give some examples of what your Distinguished Name looks like ?

 

also, dont use TRUE or FALSE in PowerShell, use

$true

or

$false

instead

Share this post


Link to post
Share on other sites

Thanks guys - Good idea about the OU -> collection thing. Was playing with scenario again this morning and don't think what I had before will work exactly. The goal I had was to be able to use a simple PowerShell script which wouldn't require editing and pull all variables from the TS so that only the TS needed to be configured. Below are some examples of the environment plus what I'm trying to do as Niall requested...

 

What I'm Trying to Do

Create task sequence for application install which requires different source files to be copied to local system based on its common site name. The common site name isn't defined in a common area that I can locate, but is listed as one of the OUs in each system's DN. The current install only has files to copy for 6 different sites and future ones wouldn't be many more - but we have almost 1,000 OUs in our domain and probably 150 - 200 different "common names." (explained below)

 

5 Examples of DNs

As you can see, there is no common formatting of OU structure

  • CN=HOSTNAME1,OU=MainGround,OU=Workstations,OU=AMC,OU=Oklahoma,OU=Markets,DC=domain,DC=abc,DC=com
  • CN=HOSTNAME2,OU=DiabetesMgt,OU=UPCBell2,OU=Workstations,OU=Clinics,OU=Oklahoma,OU=Markets,DC=domain,DC=abc,DC=com
  • CN=HOSTNAME3,OU=Workstations,OU=TSSH,OU=New Mexico,OU=Markets,DC=domain,DC=abc,DC=com
  • CN=HOSTNAME4,OU=Workstations,OU=WHCFloorG,OU=HMC,OU=Oklahoma,OU=Markets,DC=domain,DC=abc,DC=com
  • CN=HOSTNAME5,OU=NMAlturaFloor1,OU=Workstations,OU=Altura,OU=New Mexico,OU=Markets,DC=domain,DC=abc,DC=com
Common Site Names from Above List
I searched the registry for a common location for these names, but no go except for fact they were included somewhere in each system's DN
  • AMC
  • Clinics
  • TSSH
  • HMC
  • Altura
TS Idea I Considered Initially
A task sequence which did the following (only using 3 of the above to keep short):
  • Type: Set Task Sequence Variable / TSVariable = AMC TSValue = blank
  • Type: Set Task Sequence Variable / TSVariable = Clinics TSValue = blank
  • Type: Set Task Sequence Variable / TSVariable = TSSH TSValue = blank
  • Type: Run PS Script / Pkg with PS1 in root selected / Script Name: SearchDNforKeyword.ps1 (Exact script from original post)
  • Type: Run Command Line / xcopy folder1\*.* c:\folder / Condition: AMC = $true
  • Type: Run Command Line / xcopy folder2\*.* c:\folder / Condition: Clinics = $true
  • Type: Run Command Line / xcopy folder3\*.* c:\folder / Condition: TSSH = $true

What I discovered after creating a test TS is that I wrote it to pull one specific variable from the TS yet must define multiple ones. This means I'd either have to write (and constantly update) a script that contains all common names. Given the fact we have almost 1,000 OUs, this wouldn't be fun. It would be compatible with future usage, but blows away the simplicity I was looking for.

So... any thoughts? Thanks again for your help and suggestions!

Share this post


Link to post
Share on other sites

Try this. The script will simply split the DistinguishedName of your computer object and compare all the OU partial strings to all existing AD site names and return the valid one.

$SysInfo = New-Object -ComObject "ADSystemInfo"
$Computer = [ADSI]("LDAP://{0}" -f $SysInfo.GetType().InvokeMember("ComputerName", [System.Reflection.BindingFlags]::GetProperty, $null, $SysInfo, $null))
$sitesDN="LDAP://CN=Sites," + $([adsi] "LDAP://RootDSE").Get("ConfigurationNamingContext")

($Computer.distinguishedName).split(',') | % {
    $OU = ($_).split('=')
    if($OU[0] -eq 'OU'){
        foreach ($site in $([adsi] $sitesDN).psbase.children){
            if($site.objectClass -eq "site"){
                $siteName=([string]$site.cn).toUpper()
                if($OU[1] -eq $siteName){
                    write-host "found valid site name $siteName in CN"
                    break outer
                }
            }
        }
    }
}

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.