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.

36_1

4. Choose Do not create a program and click Next.

1_36_2

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.)

36_4

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.

36_3

That’s all! Run your Task Sequence on a lab client and check out the results.

Nickolaj Andersen
Principal Consultant and Enterprise Mobility MVP. Nickolaj has been in the IT industry for the past 10 years specializing in Enterprise Mobility and Security, Windows deployments and Automation. In 2015 Nickolaj was awarded as PowerShell Hero by the community for his script and tools contributions. Author of ConfigMgr Prerequisites Tool, ConfigMgr OSD FrontEnd, ConfigMgr WebService and a frequent speaker at user groups.

(4765)

comments
  • Usman
    Posted at 09:40 July 12, 2013
    Usman
    Reply
    Author

    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

    • Nickolaj
      Posted at 05:58 July 15, 2013
      Nickolaj
      Reply
      Author

      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

  • Baard Hermansen
    Posted at 19:24 October 22, 2013
    Baard Hermansen
    Reply
    Author

    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?

  • Baard Hermansen
    Posted at 19:35 October 22, 2013
    Baard Hermansen
    Reply
    Author

    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?

  • Baard Hermansen
    Posted at 20:11 October 22, 2013
    Baard Hermansen
    Reply
    Author

    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?

    • Nickolaj
      Posted at 21:17 October 22, 2013
      Nickolaj
      Reply
      Author

      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

      • Baard Hermansen
        Posted at 12:14 October 23, 2013
        Baard Hermansen
        Reply
        Author

        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.

      • Aussupport
        Posted at 06:01 October 21, 2015
        Aussupport
        Reply
        Author

        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

  • Manuel Pena
    Posted at 05:47 December 14, 2013
    Manuel Pena
    Reply
    Author

    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”

    • Nickolaj
      Posted at 09:16 December 15, 2013
      Nickolaj
      Reply
      Author

      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

    • Anthony Sharpe
      Posted at 15:32 November 9, 2016
      Anthony Sharpe
      Reply
      Author

      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?

      • Nickolaj
        Posted at 09:00 November 25, 2016
        Nickolaj
        Reply
        Author

        Hi Anthony,

        Have a look at the “SubString” method for strings in PowerShell.

        Regards,
        Nickolaj

  • Cem
    Posted at 15:40 January 15, 2014
    Cem
    Reply
    Author

    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!

    • Nickolaj
      Posted at 16:15 January 15, 2014
      Nickolaj
      Reply
      Author

      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

  • Sven
    Posted at 16:33 February 11, 2014
    Sven
    Reply
    Author

    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

    • Nickolaj
      Posted at 17:37 February 11, 2014
      Nickolaj
      Reply
      Author

      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 http://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

  • Sergio
    Posted at 10:25 February 21, 2014
    Sergio
    Reply
    Author

    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

    • Nickolaj
      Posted at 08:49 February 23, 2014
      Nickolaj
      Reply
      Author

      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

  • Chris
    Posted at 19:39 March 6, 2014
    Chris
    Reply
    Author

    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

    • Nickolaj
      Posted at 08:22 March 7, 2014
      Nickolaj
      Reply
      Author

      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

  • Filipe Costa
    Posted at 21:59 March 20, 2014
    Filipe Costa
    Reply
    Author

    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

    • Nickolaj
      Posted at 02:17 March 23, 2014
      Nickolaj
      Reply
      Author

      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

  • Filipe Costa
    Posted at 20:52 March 27, 2014
    Filipe Costa
    Reply
    Author

    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

    • Nickolaj
      Posted at 14:43 March 28, 2014
      Nickolaj
      Reply
      Author

      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

  • Ram
    Posted at 16:47 May 1, 2014
    Ram
    Reply
    Author

    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

  • Nickolaj
    Posted at 21:26 May 1, 2014
    Nickolaj
    Reply
    Author

    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

  • Ram
    Posted at 15:18 May 2, 2014
    Ram
    Reply
    Author

    Thank you Nickolaj. I will carry out the test during this weekend and post the result.

    Ram

    • Nickolaj
      Posted at 19:17 May 2, 2014
      Nickolaj
      Reply
      Author

      You’re welcome. Looking forward to hear about the results 🙂

      Regards,
      Nickolaj

  • Ram
    Posted at 13:43 May 16, 2014
    Ram
    Reply
    Author

    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

    • Nickolaj
      Posted at 20:46 May 16, 2014
      Nickolaj
      Reply
      Author

      Thanks for the feedback, and I’m glad that it worked out for you!

      Regards,
      Nickolaj

  • Tom Wardrop
    Posted at 01:35 June 27, 2014
    Tom Wardrop
    Reply
    Author

    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.

    • Tom Wardrop
      Posted at 07:22 June 27, 2014
      Tom Wardrop
      Reply
      Author

      Worked it out. The variable “_SMSTSMachineName” contacts the old computer name.

      $TSEnv = New-Object -COMObject Microsoft.SMS.TSEnvironment
      $OldComputerName = $TSEnv.Value(“_SMSTSMachineName”)

      • Nickolaj
        Posted at 20:30 June 27, 2014
        Nickolaj
        Reply
        Author

        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

  • Tom Wardrop
    Posted at 23:40 June 29, 2014
    Tom Wardrop
    Reply
    Author

    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 🙂

  • Ed
    Posted at 03:33 July 6, 2014
    Ed
    Reply
    Author

    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

    • Nickolaj
      Posted at 09:33 July 10, 2014
      Nickolaj
      Reply
      Author

      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

  • Jay
    Posted at 10:12 July 18, 2014
    Jay
    Reply
    Author

    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

  • Jim
    Posted at 00:23 August 29, 2014
    Jim
    Reply
    Author

    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

  • Andrue
    Posted at 14:21 September 5, 2014
    Andrue
    Reply
    Author

    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

    • Nickolaj
      Posted at 16:02 September 8, 2014
      Nickolaj
      Reply
      Author

      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

  • John
    Posted at 19:22 September 11, 2014
    John
    Reply
    Author

    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.

    • Nickolaj
      Posted at 13:02 September 21, 2014
      Nickolaj
      Reply
      Author

      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

  • Andrue
    Posted at 17:21 September 12, 2014
    Andrue
    Reply
    Author

    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.

  • Andrue
    Posted at 20:20 September 12, 2014
    Andrue
    Reply
    Author

    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?

    • Nickolaj
      Posted at 13:10 September 21, 2014
      Nickolaj
      Reply
      Author

      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:

      http://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

  • Mike Givens
    Posted at 18:13 April 2, 2015
    Mike Givens
    Reply
    Author

    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.

  • Abdu
    Posted at 14:54 August 15, 2016
    Abdu
    Reply
    Author

    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.

  • cms
    Posted at 17:24 February 13, 2017
    cms
    Reply
    Author

    Thank you 🙂

    Works great, I run it as a “Run PowerShell Script” in TS with bypass as executionpolicy.

  • Gol
    Posted at 14:10 March 24, 2017
    Gol
    Reply
    Author

    Silly question here: how would you make the script work without any “If” statement?

    I.E always pull serial regardless of machine model.

  • Guybee
    Posted at 03:43 April 12, 2017
    Guybee
    Reply
    Author

    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 🙂

  • Qaiss Aria
    Posted at 22:18 May 30, 2017
    Qaiss Aria
    Reply
    Author

    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”

  • John
    Posted at 09:50 July 11, 2017
    John
    Reply
    Author

    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?

    • Maurice Daly
      Posted at 13:36 July 11, 2017
      Maurice Daly
      Reply
      Author

      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

      • John
        Posted at 17:49 July 11, 2017
        John
        Reply
        Author

        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?

        • Maurice Daly
          Posted at 10:21 July 12, 2017
          Maurice Daly
          Reply
          Author

          I’ve just sent you over an email on this.

          Maurice

  • Leave a Reply