Script to Copy Machine Variables from one computer to another

I recently had to create several computers in Configuration Manager in order to pre-stage them for an OSD Deployment. As the OSD Deployment is dependent on the computers having certain machine variables assigned i had to add these for every computer too. I wanted all the new computers to have exactly the same variables as an existing computer. Instead of doing that manually for every computer i came up with this script which will do it automatically.

The script takes as input the Site Code, Source Computer and Target Computer.

Source Computer is just the name of the computer in Configuration Manager that has the variables you want to copy. Target Computer can be the name of one or more Target Computers either supplied as a string of computers or as a text file where each line hold a computer name.

In this example:

Copy-MachineVariables -Source IT-14 -Target IT-13, IT-15

All machine variables will be copied from computer IT-14 to computers IT-13 and IT-15

See more examples in the code below. Enjoy!

<#
  
.SYNOPSIS
    Copy machine variables from one Configuration Manager Computer Object to one or more computers.
 
.DESCRIPTION
    By giving the name of a Source computer all machine variables from that computer will be gathered and copied to one or more 
    of the target computers specified. Target Computers can be supplied either as a string or as seperate lines in a file. 
    Existing machine variables on the target computer(s) will as default not be removed as the new variables will just be appended.
    By setting Replace to $True exsisting variables on the target computer(s) will be removed.
 
.PARAMETER Source
    Name of the computer from which the machine variables should be copied
 
.PARAMETER Target
    Name of the computer(s) to which the machine variables should be copied

.PARAMETER TargetFile
    Path to file containing name of one or more computer(s) to which the machine variables should be copied
 
.PARAMETER Replace
    Decides if machine variables on the target computer(s) should be replaced. By default variables will be appended. 
    If this is set to True all exsisting machine variables on the target computer(s) are overwritten.
  
.EXAMPLE
    Copy-MachineVariables -Source IT-14 -Target IT-13
    Copy all machine variables on computer IT-14 and append them to computer IT-13

.EXAMPLE
    Copy-MachineVariables -Source IT-14 -Target IT-13, IT-15
    Copy all machine variables on computer IT-14 and append them to computers IT-13 and IT-15
 
.EXAMPLE
    Copy-MachineVariables -Source IT-14 -Target IT-13 -OverWrite $True
    Copy all machine variables on computer IT-14 and replace them with all exsiting variables on computer IT-13

.EXAMPLE
    Copy-MachineVariables -Source IT-14 -TargetFile C:\TargetComputers.txt"
    Copy all machine variables on computer IT-14 and append them with all exsiting variables on computers in C:\TargetComputers.txt
 
.NOTES
    Cmdlet name:      Copy-MachineVariables
    Author:           Mikael Blomqvist
    DateCreated:      2017-05-26
 
#>


[CmdletBinding(DefaultParameterSetName="String")] 
Param(
 [Parameter(Mandatory=$True, Position=0, HelpMessage="Supply Site Code")] 
            [string]$SiteCode,
 [Parameter(Mandatory=$True, Position=1, HelpMessage="Computer name(s) of source computer(s)")] 
            [string]$Source,
 [Parameter(Mandatory=$True, Position=2, ParameterSetName="String", HelpMessage="Computer name(s) of target computer(s)")] 
            [string[]]$Target,
 [Parameter(Mandatory=$True, Position=2, ParameterSetName="File", HelpMessage="File containing Computer name(s) of target computer(s)")] 
            [string]$TargetFile,
 [Parameter(Mandatory=$False, ParameterSetName="String",HelpMessage="Replace current machine variables on target computers - if false then variables will be appended")] 
 [Parameter(Mandatory=$False, ParameterSetName="File",HelpMessage="Replace current machine variables on target computers - if false then variables will be appended")] 
            [boolean]$Replace=$False
 
)



Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" # Import the ConfigurationManager.psd1 module 
Set-Location $SiteCode':' # Set the current location to be the site code.

$provider = Get-PSDrive -PSProvider CMSITE
$siteServer = $provider.Root

#Getting Machine Variables from Source Computer
Write-Host "Gathering machine variables from $Source"
$objSourceSettings = Get-WmiObject -Namespace "Root\SMS\Site_$SiteCode" -Class "SMS_MachineSettings" -ComputerName $siteServer | Where-Object {$_.ResourceID -eq (Get-CMDevice -Name $Source).ResourceID}
$objSourceSettings.get()
$variablesSource = $objSourceSettings.MachineVariables

try{
    If($TargetFile -ne $null){
    #Reading all computers from file
    $Target = Get-Content($TargetFile)
    }
}
catch{
  #No file supplied
}
#Writing Machine Variables to Target Computers
Foreach($t in $Target){
   
    $objTargetSettings = Get-WmiObject -Namespace "Root\SMS\Site_$SiteCode" -Class "SMS_MachineSettings" -ComputerName $siteServer | Where-Object {$_.ResourceID -eq (Get-CMDevice -Name $t).ResourceID}
   

    If($Append -eq $False){
    Write-Host "Appending variables to $t"    
        $objTargetSettings.Get()
        $variablesTarget = $objTargetSettings.MachineVariables
    }
    Else{
    Write-Host "Overwriting existing variables to $t"

    }

    #$variablesTarget

    foreach($variable in $variablesSource)
    {
       $newVar = $([wmiclass]"\\$siteServer\Root\SMS\Site_$($SiteCode):SMS_MachineVariable").CreateInstance()
       $newVar.Name = $variable.Name
       $newVar.Value = $variable.Value
       [System.Management.ManagementBaseObject[]]$variablesTarget += ($newVar)
    }

    $objTargetSettings.MachineVariables = $variablesTarget
    $objTargetSettings.Put()
}

Write-Host "Done"