There are various of methods out there today on how you can automate the process of naming computers during OSD. I’ve previously blogged about how to do it with VB script, you can find that blog here. In this blog post we’ll be renaming the computer based upon two critera. First we need to determine what computer model the OS is being deployed on. Secondly we want to name the computer by using the serial number and a suffix, e.g if it’s a workstation or laptop. In this blog post I’m performing OSD on Dell systems, but the script can easily be modified to support other vendors.
The script
We begin with populating two variables, $ComputerModel and $SerialNumber data from WMI. Then we create two if conditions depending on the computer model (in this case laptop or workstation). In each if condition we combine $SerialNumber with a dash and at the end a suffix for either a workstation or laptop. We’ll then get something like 1234567-WS or 1234567-LAP in the $OSDComputerName variable. Next we create a new COM object from the Microsoft.SMS.TSEnvironment class. The value of $OSDComputerName will then be put into the newly created COM object.
$ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object Model).Model $SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber # Workstations if (($ComputerModel -match "Precision") -OR ($ComputerModel -match "Optiplex")) { $OSDComputerName = $SerialNumber + "-" + "WS" $TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment $TSEnv.Value("OSDComputerName") = "$OSDComputerName" } # Laptops if ($ComputerModel -match "Latitude") { $OSDComputerName = $SerialNumber + "-" + "LAP" $TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment $TSEnv.Value("OSDComputerName") = "$OSDComputerName" }
Create a Package with the script
1. Save the above script to a .ps1 file, name it OSDComputerName.ps1 and store it in your folder structure for packages and applications.
2. Go to Software Library, Packages and create a new package.
3. Give the Package a name, e.g. OSDComputerName. Check This package contains source files and enter the location where you saved the script. Remember that it has to be an UNC path. Click Next.
4. Choose Do not create a program and click Next.
5. Click Next to confirm the settings.
6. Click Close when the wizard is complete.
7. Distribute the Package to your DP’s.
Using the script in a Task Sequence
1. Edit your OSD Task Sequence and add a New group after the Apply Drivers step. It’s important that you add the new group before the Apply Windows Settings and Apply Windows Network Settings steps.
2. Name the new group like OSDComputerName.
3. In the new group, create a new Run Command Line step and call it Set PowerShell Execution Policy. Enter the following in the Command line field:
powershell.exe -noprofile -command "Set-ExecutionPolicy Bypass LocalMachine" -force
4. In the new group, create a new Run Command Line step and call it OSDComputerName.ps1. Enter the following in the Command line field:
powershell.exe -noprofile -file OSDComputerName.ps1
5. Check Package and select your newly create package OSDComputerName. (Picture below says OSDChangeName, taken from an old package.)
6. In the new group, create a new Run Command Line step and call it Revert PowerShell Execution Policy. Enter the following in the Command line field:
powershell.exe -noprofile -command "Set-ExecutionPolicy RemoteSigned LocalMachine" -force
7. You should now have a new group with three steps. Make sure they’re arranged like below.
That’s all! Run your Task Sequence on a lab client and check out the results.
@brandon, i have the same issue. OSDComputername is set and even used to join the domain. But after a reboot it defaults to the serialnumber (value in SCCM asset database). Windows 10 1809, sccm 2016 and no MDT installed, no unattend file. Does the sccm manager overwrite the settings? Any ideas?
Hi Nikolaj,
I was able to follow your instructions and was able to get the OSDComputerName to change and apply the name to clients OS.
The issue I am running into, is after the machine reboots into the Operating System during the Task Sequence, I have a step that evaluates the OSDComputerName Variable and it appears that the variable is overwritten when the machine reboots in between tasks. I was wondering if there is a way to set this variable globally for the duration of the TS or do I need to run my script again to overwrite the TS Variable?
Hi Brandon,
You probably have other methods defined that is setting the computer name. Check collection variables, MDT customsettings.ini (if MDT is being used) or if defined in the unattend.xml file.
Regards,
Nickolaj
Can I user nslookup when run tasksequence?
Here my script:
$nametemp=”WS-”
$realname=””
For ($i=100;$i -lt 999;$i++) {
$namelookup = $nametemp+$i
$error.clear()
try{
$a = nslookup $namelookup
} catch {
“Error occured”
}
if($error){
$realname = $namelookup
break
}
}
$OSDComputerName = $realname
write-output $OSDComputerName
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
If you are trying to get your name dynamically set from DNS, then here is what I did.
foreach($ip in $(Get-NetIPConfiguration | Where-Object {$_.NetAdapter.Status -ne “Disconnected”} | Select-Object -ExpandProperty IPv4Address | Select-Object -ExpandProperty IPAddress)){
if($(Resolve-DnsName $ip -Server $(ip of dns server) -ErrorAction SilentlyContinue)){
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = $(Resolve-DnsName $ip -Server $(ip of dns server) -ErrorAction SilentlyContinue | Select-Object -ExpandProperty NameHost).Split(“.”)[0]
}
}
can I user command nslookup when run task sequence ?.My script:
$nametemp=”Computer-”
$realname=””
For ($i=100;$i -lt 999;$i++) {
$namelookup = $nametemp+$i
$error.clear()
try{
$a = nslookup $namelookup
} catch {
“Error occured”
}
if($error){
$realname = $namelookup
break
}
}
$OSDComputerName = $realname
write-output $OSDComputerName
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
Hi Nick,
The following command only shows numbers when ran on a Lenovo Machine:
$ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object Model).Model
Is there any command which can show the model for Lenovos as well instead of the Numbers only.
The following WMIC command shows the Model Number for Lenovo as well:
wmic csproduct get vendor, version
Vendor Version
LENOVO ThinkPad T450
Can you please help.
Thanks
Does this PowerShell script need to run during WinPE phase or once it has exited WinPE and has gone into Windows?
Hi Nickolaj,
We just setup SCCM 1710. I am trying to use your method to name the computers but when the script run to following line
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
I get the following error
New-Object : Retrieving the COM class factory for component with CLSID {00000000-0000-0000-0000-000000000000} failed due to the following error: 80040154 Class not registered (Exception from HRESULT:
0x80040154 (REGDB_E_CLASSNOTREG)).
At line:1 char:10
+ $TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [New-Object], COMException
+ FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand
What could be the issue?
Thanks,
Henry
NVM I figured out. Microsoft.sms.TSenvirnment class only exist when OSD is running. And the reason I got error was I made a typo LOL.
Thanks!
Hi, when this ps script runs, it does not show the box to input computer name during the TS. running out of the TS, the box appears. what have i missed?
Toby
Hi Toby,
I’m not sure what you’re getting at, since it’s not supposed to prompt for anything 🙂
Regards,
Nickolaj
Hi Nickolaj,
I am trying to implement the above Script. But I am unable to get it to Work. My TS Steps are:
1. Restart in WinPE (Boot image assigned to the TS)
2. Partition Disk
3. Apply Operating System
4. Apply Drivers
5. OSDComputerName (Group) //contains all three steps like you mentioned
6. Setup Windows and Config Mgr
7. Install Software
8. Install Updates
9. Final reboot
The weird thing is there is another powershell script, that runs perfectly in the task sequence
Any help would be greatly appreciated
Many thanks,
Ace.
Hi Ace,
Since this is an old post, the solution in here may not be optimal. I’d suggest that you try to add a new Run PowerShell Script step, pointing to the package containing OSDComputerName.ps1 and then set the script name in the step without any parameters. Remember to set the execution policy to Bypass.
Monitor your smsts.log file for any error output from the script. The placement of the script in your task sequence should be the same.
Regards,
Nickolaj
This is great. I reworked it a bit for my situation. I run it as a “Run PowerShell Script” in the TS, between Apply Operating system and apply windows settings. The Computer Names get built as per the script, but I still end up with a MININT-XXXX computer object in AD, as well as the correctly named Computer.
Could you explain how to stop this?
It seems that the MININT-XXXXXX is being picked up at the time of the DHCP lease during PXE boot
Hi there,
I am trying to implement this solution but it keeps failing on the PS section with error “The argument ‘OSDComputerName.ps1’ to the -File parameter does not exist. Provide the path to an existing ‘.ps1’ file as an argument to the -File parameter.” The only difference I have here, is that I am using a standalone media. I don’t think this should be an issue. Any ideas why it is failing?
Hi guys,
It was my mistake. I renamed the script without specifying the new name in the command line. It’s now working. Thank you for a wonderful tutorial
Hi Michael,
I’m glad that you managed to get it working!
Regards,
Nickolaj
Hi there,
Just trying out this methodology. Looks good. How does the TS know how to use OSDComputerName? Do you have to put this on a collection variable?
Hi John,
The OSDComputerName variable is a built-in override variable used where populated for the process of naming the computer, so no need to do anything with collections. For a full list of built-in ConfigMgr variables check this URL out – https://technet.microsoft.com/en-us/library/hh273375.aspx?f=255&MSPPError=-2147217396.
Maurice
Thank you for the prompt response. Just having a bit of a nightmare getting this to work. It’s failing on the PS command section. I was think that this post is a bit old and does not account for deploying PS commands actually in CM as supposed to running a command. Should the errors appear in the smsts.log?
I’ve just sent you over an email on this.
Maurice
Worked like a charm as described, I simple don’t care about workstation or laptop, so I went ahead and modified the script as below.
Thank you
$SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber
$OSDComputerName = $SerialNumber
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
Thank you Nickolaj 🙂
I finally had this working, for some reason the package created does not work (different topic for troubleshooting). So I tried adding a steps of command lines to mount a drive and run the script with the lines:
1. net use y: \\(server)\(sharedfolder where the script is located) password /user: domain\(user)
2. powershell.exe -noprofile -command “Set-ExecutionPolicy Unrestricted” -force
3. powershell.exe -noprofile -file y:\OSDComputername.ps1
4.powershell.exe -noprofile -command “Set-ExecutionPolicy RemoteSigned LocalMachine” -force
Initially I tried to run the package as a powershell script to no avail but the lines above worked for me. And I am compelled to share.
Happy deploying 🙂
Silly question here: how would you make the script work without any “If” statement?
I.E always pull serial regardless of machine model.
Thank you 🙂
Works great, I run it as a “Run PowerShell Script” in TS with bypass as executionpolicy.
Nickolaj:
Your program works wonders. After strugging for three days on my own, I came across this website. And I tried your solution and saved my butt at work. People like you should go to paradise. Thank you immensely.
I am getting this error when I try to run the script in a TS:
The argument ‘OSDComputerName.ps1’ to the -File parameter does not exist. Provide the path to an existing ‘.ps1’ file as an argument to the -File parameter.
I’ve been struggling with this in a different way and I know this doesn’t pertain exactly to naming your PC during OSD (as I have gotten that part working now), but it does use the same concepts you’ve shown above. I am looking to adjust the PC’s Description and Location fields in AD during the OSD based on various things. I will share what I have so far since I am sure others are looking to do the same thing and perhaps there is a better method than what I am doing.
1. Chance the Description in AD to Unassigned and include the serial#
—————————————
Import-Module ActiveDirectory
$Computer = “$env:computername”
$SysSerial = (Get-WmiObject Win32_BIOS -Computername $computer).SerialNumber
$Desc = “OSD-Unassigned – $SysSerial”
Set-ADComputer $Computer -Description $Desc
—————————————
2. Change the Location field in AD based on the IP for the site it is being imaged at.
—————————————
Import-Module ActiveDirectory
$Computer = “$env:computername”
$NiCOSD = (Get-WmiObject -class “Win32_NetworkAdapterConfiguration” -computername $Computer | Where {$_.IPEnabled -Match “True”}).IPAddress | Select -First 1
If ($NiCOSD -like ‘*IP1*’) {$ADLocation = “Location 1”}
If ($NiCOSD -like ‘*IP2*’) {$ADLocation = “Location 2”}
If ($NiCOSD -like ‘*IP3*’) {$ADLocation = “Location 3”}
If ($NiCOSD -like ‘*IP4*’) {$ADLocation = “Location 4”}
If ($ADLocation -eq $NULL) {$ADLocation = “OSD Unknown”}
Set-ADComputer $Computer -Location $ADLocation
—————————————
I am using the “Run Command Line” for these with the powershell.exe .ps1 file package, and have tried doing it right after the OSD name before the Revert Powershell as well as in different parts of the Sequence after booting into windows. In both of these instances I have also tried using the “Run As” option and specifying a Domain Admin account. I do not see any errors in the logs to aid me in where exactly this is failing, but I am suspecting it is either permissions to AD or that the AD Module may not be available?
Hi Andrue,
I’d also expect that it’s due to the fact that the ActiveDirectory module is not present. This is something that would have to be installed, but I’m unsure if it’s possible to do that in WinPE in a supported way. Anyhow, I found this post on how to add the module:
https://sysadmins.no/?p=218
If it doesn’t work, I’d suggest that you start looking into scripting your code with ADSI instead of the ActiveDirectory module.
Regards,
Nickolaj
I know this question I am about to ask, isn’t regarding the same thing with “naming” the PC during OSD, but I am trying to use the same method you’ve shown here to do something else but it isn’t working. I’ll share the code, as I’m sure others are looking to do the same thing and it would help them or they/you may have better solution.
1. I would like to update AD with the Computer’s Description with the following :
——————————-
Import-Module ActiveDirectory
$Computer = “$env:computername”
$SysSerial = (Get-WmiObject Win32_BIOS -Computername $computer).SerialNumber
$Desc = “OSD-Unassigned – $SysSerial”
Set-ADComputer $Computer -Description $Desc
——————————-
2. I would like to update AD with the Computer’s Location with the following Location based on the IP during OSD deployment since it will be used at various sites:
——————————-
Import-Module ActiveDirectory
$Computer = “$env:computername”
$NiCOSD = (Get-WmiObject -class “Win32_NetworkAdapterConfiguration” -computername $Computer | Where {$_.IPEnabled -Match “True”}).IPAddress | Select -First 1
If ($NiCOSD -like ‘*IP1*’) {$ADLocation = “Location 1”}
If ($NiCOSD -like ‘*IP2*’) {$ADLocation = “Location 2”}
If ($NiCOSD -like ‘*IP3*’) {$ADLocation = “Location 3”}
If ($NiCOSD -like ‘*IP4*’) {$ADLocation = “Location 4”}
If ($ADLocation -eq $NULL) {$ADLocation = “OSD Unknown”}
Set-ADComputer $Computer -Location $ADLocation
——————————-
I’ve tried running these as follow:
– right after the OSD name, before Revert Powershell with/without a “Run As Account” (Failed)
– Elsewhere in the Sequence after booting into Windows with/without a “Run As Account” (Failed)
In ALL attempts, I was using the Run Command Line with powershell.exe -noprofile -executionpolicy bypass
There were no error codes in any of the logs, but it did not perform the task. Any advise would be greatly appreciated.
Sorry but I’m having an issue. I added the Powershell component into the boot image, but I still can’t run the command after the Apply OS task/before Apply Windows Settings.
Is my task sequence in the right order?
Restart in Windows PE
Partition Disk
Apply OS
[GROUP OSD ComputerName]
– Run Command line (the powershell.exe one that sets execution policy
it fails at this step, 0x80070002.
I f8 to bring up command prompt and try powershell.exe there, it can’t find it.
Hi John,
Have you updated the boot image after you added the PowerShell and .NET Framework components?
You could try to use this command line to run the script:
%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File OSDComputerName.ps1
But I’d look into why you’re not even able to start powershell.exe from the F8 command prompt inside WinPE.
Regards,
Nickolaj
Excellent guide, however I am having an error (0xFFFD0000) during my OSDComputerName.ps1 Task.
Which I have set to name the PC using it’s MAC address (minus the :), this may also assist Jay’s question as well.
Script:
—————————————————————
$MacAddress = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “IpEnabled = true” | Select-Object MacAddress).MacAddress
$Escaped = $MacAddress.Replace(“:”, “”)
$OSDComputerName = “NA” + “-” + $Escaped
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
——————————————————————
Here are the logs
!——————————————————————————————–! TSManager 9/4/2014 3:59:56 PM 776 (0x0308)
Expand a string: WinPEandFullOS TSManager 9/4/2014 3:59:56 PM 776 (0x0308)
Executing command line: smsswd.exe /run: powershell.exe -noprofile -command “Set-ExecutionPolicy Bypass LocalMachine” -force TSManager 9/4/2014 3:59:56 PM 776 (0x0308)
[ smsswd.exe ] InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
PackageID = ” InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
BaseVar = ”, ContinueOnError=” InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
ProgramName = ‘powershell.exe -noprofile -command “Set-ExecutionPolicy Bypass LocalMachine” -force’ InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
SwdAction = ‘0001’ InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
Command line for extension .exe is “%1” %* InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
Set command line: Run command line InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
Working dir ‘not set’ InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
Executing command line: Run command line InstallSoftware 9/4/2014 3:59:56 PM 1388 (0x056C)
Process completed with exit code 0 InstallSoftware 9/4/2014 4:00:13 PM 1388 (0x056C)
Command line returned 0 InstallSoftware 9/4/2014 4:00:13 PM 1388 (0x056C)
Process completed with exit code 0 TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
!——————————————————————————————–! TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Successfully completed the action (Set PowerSell Execution Policy) with the exit win32 code 0 TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
MP server . Ports 80,443. CRL=false. TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Setting authenticator TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Set authenticator in transport TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Sending StatusMessage TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Setting message signatures. TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Setting the authenticator. TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
CLibSMSMessageWinHttpTransport::Send: URL: :443 CCM_POST /ccm_system_AltAuth/request TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
In SSL, but with no client cert TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Request was successful. TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Set a global environment variable _SMSTSLastActionRetCode=0 TSManager 9/4/2014 4:00:13 PM 776 (0x0308)
Set a global environment variable _SMSTSLastActionSucceeded=true TSManager 9/4/2014 4:00:14 PM 776 (0x0308)
Expand a string: %_SMSTSMDataPath%\Logs TSManager 9/4/2014 4:00:14 PM 776 (0x0308)
I have tried using this with the “Run command line” as well as “Run Powershell Script” sequences, however both fail. I have also tried using your New Group guide and placing the Task Sequence BEFORE the “Apply OS” sequence as suggested from other sites, but that also fails. Perhaps you’ve seen this before and can point me in the right direction?
Thank you
Hi Andreu,
You’re script looks good to me, but perhaps you should try it this way:
$MacAddress = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter “IpEnabled = true” | Select-Object -ExpandProperty MacAddress
$Escaped = $MacAddress.Replace(“:”, “”)
$OSDComputerName = “NA” + “-” + “$($Escaped)”
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$($OSDComputerName)”
This should be run as a Run Command Line step pointing to a Package where the ps1 script file can be located. From the log you’ve pasted I can’t really see anything other than you’ve successfully executed a powershell command to set the execution policy. Instead, use the following to launch you script in the Run Command line step:
powershell.exe -noprofile -executionpolicy bypass -file script.ps1
Regards,
Nickolaj
Hi Nickolaj,
Thanks for the example to run powershell in OSD. I’ve tried running a powershell script in both SCCM 2012 SP1 and SCCM 2012 R2 without much luck. I’ve placed the script in between Apply Operating System and Apply Windows Settings. Have tried the script as a package and running it from a shared but no luck.
Tried to set executionpolicy to bypass via OSD but never got applied. Tried registry as well. Tried creating custom Task Sequence and just running the executionpolicy via registry file and run the script. The registry set the executionpolicy to bypass but the powershell never ran. Don’t know what else to try.
Can you please help? thanks in advance.
Jim
Hi
Your script is almost what I was looking for but I need some help as the naming convention that I need to use is “WS + last 4 charters of the computers MAC address.
Could you please help me with this as I’m not experienced when it comes to PowerShell.
Thanks
Hi Nickolaj,
Thanks for posting this, it is very useful on OSD. May I also ask if you can give an insight if I were to use the last 6 digit of the serial number instead of the whole number. It would helped a lot.
Thanks again.
Ed
Hi Ed,
Here’s an example of how you can use PowerShell to get the last 6 characters of a string:
$x = “123456789”
$x.SubString(($x.Length)-6)
If you’d to apply that method to the script, this would be the results:
$ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object Model).Model
$SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber
$SerialNumberTrim = $SerialNumber.Substring(($SerialNumber.Length)-6)
# Workstations
if (($ComputerModel -match “Precision”) -OR ($ComputerModel -match “Optiplex”)) {
$OSDComputerName = $SerialNumberTrim + “-” + “WS”
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
}
# Laptops
if ($ComputerModel -match “Latitude”) {
$OSDComputerName = $SerialNumberTrim + “-” + “LAP”
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
}
I’ve not had a chance to test it out, but please let me know if it doesn’t work.
Regards,
Nickolaj
We’re upgrading to Windows 7 from XP. At the same time, we’re also changing domains after a recent organisation split. Our computer names at the moment are in the format: C0xxx. I wanted to add a script to the task sequence that changes it to Mxxx, truncating the first two characters of the old computer name, and adding an M. This allows us to easily identify computer objects that have already been re-imaged, while also allowing us to easily map the computer back to it’s old name and it’s old computer object in the other domain.
Anyway, it’s working a charm. Thanks for the blog post, and I’m glad I could contribute something to it 🙂
Does anyone know how to retrieve the old computer name? I’m redeploying computers already known to SCCM, so there must be a way to get the old computer name. I thought checking “$TSEnv.Value(“OSDComputerName”)” would work, but it’s always empty unless you manually set it to override the old computer name.
Worked it out. The variable “_SMSTSMachineName” contacts the old computer name.
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$OldComputerName = $TSEnv.Value(“_SMSTSMachineName”)
Hi Tom,
When you’re talking about the old computername, what exactly are you doing then? A refresh scenario or replace? Cool that you managed to find that variable.
Regards,
Nickolaj
Sorry for late response. Your script worked out the way, I wanted. Now, I can confidently deploy to production. Thanks for the help.
Now, I will have to find a way on how to update DELL bios for all Laptops with the TS. Have found few interesting materials on the NET. Will read through and see how, I can make it work.
Ram
Thanks for the feedback, and I’m glad that it worked out for you!
Regards,
Nickolaj
Thank you Nickolaj. I will carry out the test during this weekend and post the result.
Ram
You’re welcome. Looking forward to hear about the results 🙂
Regards,
Nickolaj
Hi Ram,
You could simply just rearrange the parts that create the OSDComputerName string variable, check this out:
$ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object Model).Model
$SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber
# Workstations
if (($ComputerModel -match “Precision”) -OR ($ComputerModel -match “Optiplex”)) {
$OSDComputerName = “MLIW” + $SerialNumber
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
}
# Laptops
if ($ComputerModel -match “Latitude”) {
$OSDComputerName = “MLIW” + $SerialNumber
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
}
If you’d like to have separate names based upon laptop or workstation, just change the $OSDComputerName row in the specific section.
Due to the formatting on this comment section, I’d recommend that you copy that script into e.g. Notepad or PowerShell ISE and replace all quotations with new ones.
Regards,
Nickolaj
For my lab test – I would like to have computer name as follows:
MLIW + SerianNumber
What exactly, I need to change from your above script to include MLIW as the prefix instead of WS or LAP at the end?
All my hardware are DELL.
Thanks
Hi,
Thanks for the tip 🙂
The problem was with ADSI. In OSD you cant connect with A.D this way (or i’m not doing it right) i changed the script to go with a WMI query and now it works. I also unchecked the “Migrate Computer Name” flag on Capture Windows Settings.
I added another command to change the workstation name just in case 🙂
the weird part is that i don’t have the option “Continue on error” checked on the script but before the change it was failing on the
Active Directory connection.
Script:
$NewComputerName = Get-WmiObject Win32_ComputerSystem
$query = “SELECT * FROM ds_computer where ds_Name like ‘Workstation Name%’ and ADSIPath Like ‘%OU=XPTO_Child,OU=XPTO_Father,OU=XPTO_Granpa,DC=XPTODomain,DC=Com'”
$secure_string_pwd = convertto-securestring “Password” -asplaintext -force
$Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ‘domain\user’ , $secure_string_pwd
$WS = Get-WmiObject -Query $query -Namespace “root\Directory\LDAP” -ComputerNAme x.x.x.x -Credential $Credential
$Accounts = $WS | Select-Object -Property ds_name
$Results = @()
ForEach ($Account in $Accounts)
{
$Result = “” | Select-Object “Name”
$Result.Name = [String]$Account.ds_name
$Results = $Results + $Result
}
$computername = $Results | Sort-Object “Name” -Descending | Select-Object “Name” -First 1
[int]$computernamenum = ($computername.Name.Substring(8,3))
$computernamenum = $computernamenum + 1
[string]$ADWorkstation = $computername.Name.Replace($computername.Name.Substring(8,3),$computernamenum)
$OSDComputerName = $ADWorkstation
$NewComputerName.rename($OSDComputerName)
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
#Restart-Computer
Cheers,
Filipe
Hi Filipe,
Thanks for sharing your findings! I’m glad that you were able to find a solution to your problem 🙂
Have a great weekend.
Regards,
Nickolaj
Hi Nickolaj,
I made some modifications on the script to get a new name against Active Directory. It works fine out of TS with a modification (using Win32_ComputerSystem) but on TS it does nothing, i already tried with the “Microsoft.SMS.TSEnviromnent” like you said and with Win32_ComputerSystem as the last step on the TS and the computer name stays the one who came with the image.
I tried too to uncheck the option “Migrate Computer Name” and i got the same result.
If i run the script after the login it runs and changes the Workstation name.
Am i missing any step on the TS configuration?
Any idea?
Script:
(this works with a 11 digit computername where the last 3 are numbers you can change it in this line: $computername.Name.Replace($computername.Name.Substring(8,3),$computernamenum)
and this line:
[int]$computernamenum = ($computername.Name.Substring(8,3))
)
#$NewComputerName = Get-WmiObject Win32_ComputerSystem -> Last TS Step
$DomainRootPath=(‘LDAP://[Active Directory Server IP]/OU=XPTO_Child,OU=XPTO_Father,OU=XPTO_Granpa,DC=XPTODomain,DC=Com’)
$DomainRootPath=new-object DirectoryServices.DirectoryEntry($DomainRootPath,'[Some AD User]’,'[Password]’)
$LDAPFilter = “(&(objectCategory=Computer)(!userAccountControl:1.2.840.113556.1.4.803:=2))”
$Searcher = new-object DirectoryServices.DirectorySearcher([ADSI] $DomainRootPath)
$Searcher.filter = $LDAPFilter
$Accounts = $Searcher.FindAll()
If ($Accounts.Count –gt 0)
{
$Results = @()
ForEach ($Account in $Accounts)
{
$Result = “” | Select-Object “Name”
$Result.Name = [String]$Account.Properties.name
$Results = $Results + $Result
}
}
$computername = $Results | Sort-Object “Name” -Descending | Select-Object “Name” -First 1
[int]$computernamenum = ($computername.Name.Substring(8,3))
$computernamenum = $computernamenum + 1
[string]$ADWorkstation = $computername.Name.Replace($computername.Name.Substring(8,3),$computernamenum)
$OSDComputerName = $ADWorkstation
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
#$NewComputerName.rename($OSDComputerName)-> Last TS Step
#Restart-Computer -> Last TS Step
Hi Filipe,
The first thing I’d try is to put a “Suspend” or “Pause” step into the task sequence, directly after where you’re executing your script. Hit F8 to get a command prompt (boot image needs debugging enabled) and enter ‘powershell.exe’. From there run the script (obviously browse to the location where the script was downloaded, should be in X:\_SMSTaskSequence\Packages\XXX or something if it’s running in WinPE).
Also, I see that you’re script is executing with certain credentials, perhaps that’s where it goes wrong. Maybe you should move that part to the actual ‘Run Command Line’ step in the TS instead. This is just a wild guess, since I’m not able to try it out myself.
Regards,
Nickolaj
Nickolaj, is there a reason that you use the Run Command Line step instead of the Run PowerShell Script step? It looks like you can do it all in one step instead of 3. I am new to this so I thought I would see if I am interpreting this correctly.
Thanks in advance,
Chris
Hi Chris,
No, there’s not a reason really. I’m used to do it this way with Run Command line and it has proved to work flawlessly in the past. Instead of doing the 3 steps, you could combine them all into a single Run Command line step:
powershell.exe -noprofile -executionpolicy bypass -command ‘Get-Process’
or
powershell.exe -noprofile -executionpolicy bypass -file ‘C:\Temp\Get-Script.ps1’
Regards,
Nickolaj
Hi Nikolaj,
I’m a collegue from Sven
We entered all like described in tutorial, also in the exact same spot. We also use x64 bootimage (new laptop’s with 8gb ram). Also powershell is enabled on bootimage.
We see in the tasksequence that the powershell is opening, but nothing happens. Name still on Minint.
Any idea’s?
Regards and thanks for all your help
Sergio
Hi Sergio,
On what models are you running the script? HP/Dell? I’d try to put a Pause/Suspend step into the task sequence and when it’s paused, press F8 and enter ‘powershell.exe’ into the cmd-prompt. Run the script now and wait for it to finish, then run the following:
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”)
What’s the value of OSDComputerName?
Regards,
Nickolaj
Hi Nickolaj,
When we include this script, the name is unchanged.
When we check the logs and try to run it locally, we get the following error: New-Object : Retrieving the COM class factory for component with CLSID {XXXX} failed due to the following error: 80040154 Class not regist
ered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))
If I look this up, I come by many people who say it has to to with 64-bit vs 32-bit processes but if run the script in powershell x86 it gives the same error. Do you have any idea why we get this error? Thanks in advance!
Sven
Hi Sven,
Do you still get a name like MININT-XXXXX? Where in the task sequence have you placed this step?
I’m using this script in production at my current work, where we’ve placed it in between ‘Apply Operating System’ and ‘Apply Windows Settings’. We’re using a x64 boot-image.
Running the script outside of an Task Sequence will not work (e.g. locally on your workstation/server), since the Microsoft.SMS.TSEnvironment assembly is not loaded. Make sure that you’re boot image have the PowerShell and .NET Framework components added.
I’d put in a Pause/Suspend step (check out https://deploymentbunny.com/2011/05/10/ltipause-vbs-take-a-break-in-deployment/ ) in the task sequence, press F8 when the task sequence is paused (assuming that debugging is enabled in the boot image) and then execute ‘powershell.exe’. From there run script to see if it executes successfully.
Best regards,
Nickolaj
Is there a way to add the possibility to first check if a computername exists based on the UUID? I am new to Pwershell and wondered if someone could guide me.
But the script is rocksolid and works good!
Hi Cem,
Everything is possible with PowerShell! As of now this script doesn’t have that functionality that you’re asking for. But perhaps I could update it in the future. But to guide in the right direction, you’d have to find a way to access the SMS Provider and enumerate instances in the SMS_R_Devices class from the “root\sms\site_yoursitecode” namespace. I’d run the check against the Name property, since the UUID is just that, an universal unique identifier.
Regards,
Nickolaj
Hello Nickolaj,
This solution helped me since I had not yet installed MDT but it worked like a charm, but I made a little change to the script. Since I dont really care if its a laptop or desktop.
Thanks again
$SerialNumber = (Get-WmiObject -Class Win32_BIOS | Select-Object SerialNumber).SerialNumber
$OSDComputerName = “WS-” + $SerialNumber
$TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
$TSEnv.Value(“OSDComputerName”) = “$OSDComputerName”
Hi Manuel,
I’m glad that it helped you! Thanks for sharing your modified script so that others looking for the same solution can use it. If you at any time have any questions, just drop me an email!
Regards,
Nickolaj
Nice script. If I wanted to modify the script to get only a portion (substring) of the serial number, how would I go about doing so?
Hi Anthony,
Have a look at the “SubString” method for strings in PowerShell.
Regards,
Nickolaj
Oopps, got a double posting since i got an error message when i posten the first time… 🙁
Anyway, i’ve found the correct logfile (x:\windows\temp\smstslog\smstslog.log), and the error message 80070002 translates to File not found.
It turns out the the catalog x:\windows\system32\WindowsPowerShell\v1.0\ is empty, no exe-files!
Any idea as to where powershell is supposed to reside?
Or do i have to modify my image to include Powershell?
Hi Baard,
I’d guess that your boot image does not have the PowerShell component installed. I’m assuming that you’re running ConfigMgr 2012 SP1 (CU not relevant), and therefor has Windows ADK 8.0 installed. To install the PowerShell component, perform the following steps:
1. Right click on your boot image and choose Properties.
2. Go to the Optional Components tab and click on the yellow star.
3. Add the following components:
– Microsoft .NET (WinPE-NetFx)
– Windows PowerShell (WinPE-PowerShell)
4. Click OK and update your distribution points.
Once they’re updated, rerun the task sequence and the script should run perfectly fine!
Let me know how it goes 🙂
Regards,
Nickolaj
Hi!
Thanks for a speedy reply 🙂
I added the components you mentioned.
Just for the record, in my environment they are called
Microsoft .NET (WinPE-NetFx4)
and
Windows PowerShell (WinPE-PowerShell3).
When i clicked the latter, SCCM popped up with:
“Add components that are required by Setup (WinPE-Setup-Server)?
If you enable Setup (WinPE-Setup-Server), the following dependent components will also be enabled:
-Setup (WinPE-Setup)”
I’m suspecting there is a bug there, since “Setup (WinPE-Setup-Server)” is named, while “Windows PowerShell (WinPE-PowerShell3)” is what is being checked.
Anyway, “Setup (WinPE-Setup)” is what was added in addition.
The TA now accepted the steps without complaining, thanks for the help 😀
Alas, the naming did not work, will have to look into CustomSettings.ini and other stuff.
Hi,
I got SCCM 2012 R2 and none of the component were installed
so when i try to run this steps got the error in Set Powershell Execution Policy stage?
As
Hey,
I’ve been trying to implement your solution, but i end up with error code 80070002, on all the three steps.
I’m none the wiser reading the logsfiles on the client, do you have any tips as to what’s wrong?
Hey,
I’ve tried this solution now, but i constantly get 80070002 error on the “Set powershell…” command.
Marked it with “Continue on error”, but i get the same error code on OSDComputerName step.
Any ideas as to what’s wrong?
Hi, very informative blog. I tried out this power-shell script of yours’ yesterday without any luck.
I have created a task sequence using the MDT and have created the group OSDComputerName right after “Apply Operating System Image”. Once the image is applied and the PC boots up to ready devices it throws an “Windows could not parse or process the unattend answer file …” and the PC keeps rebooting.
Created a clean task sequence via CM and this time there is no error parse error but it does not accept the default password set for administrator at log-in! In fact it does not accept any password. Have you experienced this yourself?
Kind regards,
Usman
Hi Usman,
Make sure that you’re not setting the OSDComputerName variable in your CustomSettings.ini file aswell, the powershell script should be the only part in your task sequence actually setting that variable. Have you looked at your smsts.log file regarding what goes wrong during your ConfigMgr task sequence? These are the locations of the smsts.log file during the different OSD steps:
– Windows PE before HDD format: x:\windows\temp\smstslog\smsts.log
– Windows PE after HDD format: x:\smstslog\smsts.log and copied to c:\_SMSTaskSequence\Logs\Smstslog\smsts.log
– Full version Windows before SCCM agent installed: c:\_SMSTaskSequence\Logs\Smstslog\smsts.log
– Full version Windows after SCCM agent installed: c:\windows\system32\ccm\logs\Smstslog\smsts.log
– Full version Windows (x64) after SCCM agent installed: c:\windows\sysWOW64\ccm\logs\Smstslog\smsts.log
– After Task Sequence has finished running: c:\windows\system32\ccm\logs\smsts.log
– After Task Sequence has finished running (x64): c:\windows\sysWOW64\ccm\logs\smsts.log
Remember to enable debugging on your boot image, so that you can press F8 prior to the failure. When you press F8 you’ll get a command prompt where you’re able to load up smsts.log in either CMtrace.exe or look at it with just notepad.exe. If you’re unsure how to enable debugging of your boot image, search for it on google, there are many blog posts describing how to accomplish that.
Regards,
Nickolaj