SCCM/MECM How to set computer name automatically during Task Sequence

Our Score
Click to rate this post!
[Total: 0 Average: 0]

I know it is possible to set the computer name before you start the task sequence by adding the OSDComputerName variable to a collection – usually used in the Unknown Computers collection. I know as well how to generate it based on the serial number of the workstation or laptop. Well, this was not enough for me and I decided that it should be possible to auto-assign computer names during Task Sequence based on the current active directory names. To make it even more fun I was determined to get the next available computer name based on domain naming convention (will shorten this to DNC), but only for computers above 1000. Please, do not ask me why I did this to myself. So let’s start. With the drawbacks and how to deal with them.

Drawback Number One – Active Directory Modules are missing in Windows PE and there is no easy way to add them.
Drawback Number 2 – I want to take the name with PowerShell because I know PowerShell and it is so convenient to use it. I know, I know it is easier with LDAP, but I said PowerShell and that’s it. To be honest, I am considering changing it to LDAP, but more on this later.

Infrastructure Involved – MECM version 2207 installed on Server 2016. MDT installed as well.

With all that said I pulled my sleeves and started. The easy part – get the name.

#Get List Of All Computer Names with filtering to exclude some computers
$worstations = Get-ADComputer -Filter {name -like "whatever*" -and name -notlike "*morewhatever*" }  | sort name | select -ExpandProperty name

#Create empty array for computer numbers
$numbers = @()
#Loop computers and get last four only, that's what I need. Little logic for numbers above 1000 implemented #as well
foreach ($w in $worstations ){
    $getnum = $w.substring($w.length - 4, 4)
    if($getnum -gt 1000){
    $numbers +=$getnum
    }
}
#Make the strings numbers again
$a = [int[]]$numbers
#Loop again and break if the diffidence between two numbers is greater than 1 
#[int[]]$numbers = $workstations-replace '\D+'
for ($i = 0; $i -lt $a.Count; $i++) {

    if($a[$i + 1] - $a[$i] -gt 1) {
        $OSDComputerName= 'DNC{0:00}' -f ($a[$i]+1); break
    }
  
}
#Line 1 goes here
#Print the name so we can see it in task Sequence Monitor and know that it works.
$OSDComputerName

The above script works perfectly fine in PowerShell, however, not so perfectly in a Task Sequence. To make it work there this line (let’s name it Line 1) should be added, before printing Computer Name is good.

(New-Object -COMObject Microsoft.SMS.TSEnvironment).Value('OSDComputerName') = $OSDComputerName

With that done I moved to Drawback Number 1. To make a long story short I’ll skip the 100 boring tests I did and jump right to the solution. The only reasonable and stable way to do this was to create a package containing AD modules and copy it during the task sequence. In this way, they will stay persistent as long as you are in WinPE. I’ll attach the modules to this post if you want to create one yourself keep the directories structure, it is way easier to copy the modules this way. Thanks to this guy for pointing me in the right direction. Copy command is:

xcopy "ADModules\*.*" "X:\Windows" /D /E /C /I /Q /H /R /Y /S

It was time to test, so I set up a task sequence and happily watched how it….. fails. It failed because you cannot browse Active Directory anonymously, you need a user for that. Since we are in WinPe we cannot use “Run this step as the following account” the only way I could figure out was to put the username and password inside the PowerShell script, but this is not the best security approach because the password is exposed in clear text. You know that you have to switch off F8 in your production boot images, right? That’s why I’m considering changing everything to LDAP, but this is a story for another day. Clear text passwords are a big no-no. To remove it from the script I did the following:

  1. Created a collection variable for the collection in question – All Unknown Computers
  2. When creating the variable choose name that fits you (mine is named NAPWD) and select “Do not Display this value in Configuration Manager” – this will hide the password. This variable cannot be read-only (the ones starting with underscore _) if you use complex passwords
  3. In the script add

$tspass = New-Object -ComObject Microsoft.SMS.TSEnvironment
$username = "domain\domainjoinaccount"
$pass = $tspass.Value("NAPWD")
$password = ConvertTo-SecureString -AsPlainText $pass -Force
$Cred = New-Object System.Management.Automation.PSCredential $psername,$password
$worstations = Get-ADComputer -Filter {name -like "whatever*" -and name -notlike "*morewhatever*" } -Server yourdomaincontroller -Credential $Cred | sort name | select -ExpandProperty name  | Sort-Object name | Select-Object -ExpandProperty name

This works, however, it leads to a new Drawback – how to ensure that computer names are not overwritten if you are imaging multiple workstations at once? The only solution I see is to add the computer to the active directory immediately after the name is calculated. With this, our final script looks like that:

Import-Module activedirectory | Out-Null
$tspass = New-Object -ComObject Microsoft.SMS.TSEnvironment
$username = "domain\username"
$pass = $tspass.Value("NAPWD")
$password = ConvertTo-SecureString -AsPlainText $pass -Force
$Cred = New-Object System.Management.Automation.PSCredential $Username,$Password
$wst = Get-ADComputer -Filter {name -like "whatever*" -and name -notlike "*morewhatever*"} -Server domaincontroller -Credential $Cred  | Sort-Object name | Select-Object -ExpandProperty name

$numbers = @()
foreach ($w in $wst){
    $getnum = $w.substring($w.length - 4, 4)
    if($getnum -gt 1000){
    $numbers +=$getnum
    }
}
$a = [int[]]$numbers
#[int[]]$numbers = $wst -replace '\D+'
for ($i = 0; $i -lt $a.Count; $i++) {

    if($a[$i + 1] - $a[$i] -gt 1) {
       $OSDComputerName = 'DNC{0:00}' -f ($a[$i]+1); break
    }
}
(New-Object -COMObject Microsoft.SMS.TSEnvironment).Value('OSDComputerName') = $OSDComputerName
New-ADComputer -Name $OSDComputerName -SamAccountName $OSDComputerName -Path "OU=Windows 10,OU=Workstations,OU=CONTOSO,DC=DOMAIN,DC=COM" `
 -Enabled $True -DOMAINCONTROLLER -Credential $Cred
$OSDComputerName

Don’t forget to change the username, domain name, and OU PATH also adapt filters to your needs. AD modules are here. I copy them in the beginning of the task sequence. Set Computer name step I put between Apply Windows Setting and Apply Network Settings, seems the best location.

Hope it helps someone, if you have any questions leave me a comment.

Our Score
Click to rate this post!
[Total: 0 Average: 0]

Comments

2 responses to “SCCM/MECM How to set computer name automatically during Task Sequence”

  1. Hi Thanks for sharing this, regarding the ADModule, where should i add the zip file? I’m confused a little bit

  2. Hello Ahmed,

    First, apologies for the significantly delayed reply. To make this work, you must unzip the files and create a package with source files. Then, in the task sequence, you add the run command line step with the copy command and your newly created package. After that, run the script to name it in the “Run PowerShell Script” step. I do this before the “Apply Operating System” step. If you still need help with something, leave me another comment; I will try to be faster this time 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.