I read a post on the TechNet forums the other day where a member asked for help regarding to choose the location of where the computer object would be created in Active Directory depending on region and computer system (you’ll find the thread here). I figured that I would help out and re-use part of the code that I wrote for how to prompt for the computer name during OSD.

Overview

  • Download the script
  • Create the script package
  • Update your boot image to support PowerShell
  • Implement the script in a Task Sequence

Download the script

Save the script below and call it Set-OULocationPrompt.ps1, or something familiar, and put it in your Content Library. In my lab environment I’ve saved it at the following location:

\\CAS01.contoso.com\Source$\Pkgs\OSDOULocation

The script accepts a number of parameters that it needs to function properly (they’re mandatory). First off we have the two parameters that controls the text of the Radio Buttons. These two are named RBOptionFirst and RBOptionSecond. What you enter here will also be added to the final LDAP string that will be populated in the OSDDomainOUName variable, which essentially will be where the computer object is stored in Active Directory. Secondly, we also need to specify the DomainName (NetBIOS name of your domain) and DomainSuffix (domain suffix, e.g. com or local). The last parameter called LocationList should be specified as a string array, e.g @(“Stockholm”,”Sumpan”,”Bromma”). The locations entered in here, will be populated into the drop down box, making it possible to choose any of them.

Here’s a screenshot from how it looks when I’m running this script inside a task sequence environment:

98_3

As shown in the picture, you can see what parameters I’ve fed the script with, and how it will construct the LDAP string. This popup where it shows the LDAP string is not part of the script, it’s just something extra I added for you to see how it would look like.

param(
[parameter(Mandatory=$true)]
[string]$RBOptionFirst,
[parameter(Mandatory=$true)]
[string]$RBOptionSecond,
[parameter(Mandatory=$true)]
[string]$DomainName,
[parameter(Mandatory=$true)]
[string]$DomainSuffix,
[parameter(Mandatory=$true)]
[string[]]$LocationList
)

function Load-Form {
    $Form.Controls.AddRange(@($RBOption1, $RBOption2, $ComboBox, $Button, $GBSystem, $GBLocation))
    $ComboBox.Items.AddRange($LocationList)
	$Form.Add_Shown({$Form.Activate()})
	[void]$Form.ShowDialog()
}

function Set-OULocation {
    param(
    [parameter(Mandatory=$true)]
    $Location
    )
    if ($RBOption1.Checked -eq $true) {
        $OULocation = "LDAP://OU=$($RBOptionFirst),OU=$($Location),DC=$($DomainName),DC=$($DomainSuffix)"
    }
    if ($RBOption2.Checked -eq $true) {
        $OULocation = "LDAP://OU=$($RBOptionSecond),OU=$($Location),DC=$($DomainName),DC=$($DomainSuffix)"
    }
    $TSEnvironment = New-Object -COMObject Microsoft.SMS.TSEnvironment 
    $TSEnvironment.Value("OSDDomainOUName") = "$($OULocation)"
    $Form.Close()
}

# Assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") 

# Form
$Form = New-Object System.Windows.Forms.Form    
$Form.Size = New-Object System.Drawing.Size(260,220)  
$Form.MinimumSize = New-Object System.Drawing.Size(260,220)
$Form.MaximumSize = New-Object System.Drawing.Size(260,220)
$Form.SizeGripStyle = "Hide"
$Form.StartPosition = "CenterScreen"
$Form.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($PSHome + "\powershell.exe")
$Form.Text = "Choose a location"
$Form.ControlBox = $false
$Form.TopMost = $true

# Group boxes
$GBSystem = New-Object System.Windows.Forms.GroupBox
$GBSystem.Location = New-Object System.Drawing.Size(10,10)
$GBSystem.Size = New-Object System.Drawing.Size(220,60)
$GBSystem.Text = "Select system"
$GBLocation = New-Object System.Windows.Forms.GroupBox
$GBLocation.Location = New-Object System.Drawing.Size(10,80)
$GBLocation.Size = New-Object System.Drawing.Size(220,60)
$GBLocation.Text = "Select location"

# Radio buttons
$RBOption1 = New-Object System.Windows.Forms.RadioButton
$RBOption1.Location = New-Object System.Drawing.Size(20,33)
$RBOption1.Size = New-Object System.Drawing.Size(100,20)
$RBOption1.Text = "$($RBOptionFirst)"
$RBOption1.Add_MouseClick({$ComboBox.Enabled = $true})
$RBOption2 = New-Object System.Windows.Forms.RadioButton
$RBOption2.Location = New-Object System.Drawing.Size(120,33)
$RBOption2.Size = New-Object System.Drawing.Size(100,20)
$RBOption2.Text = "$($RBOptionSecond)"
$RBOption2.Add_MouseClick({$ComboBox.Enabled = $true})

# Combo Boxes
$ComboBox = New-Object System.Windows.Forms.ComboBox
$ComboBox.Location = New-Object System.Drawing.Size(20,105)
$ComboBox.Size = New-Object System.Drawing.Size(200,30)
$ComboBox.DropDownStyle = "DropDownList"
$ComboBox.Add_SelectedValueChanged({$Button.Enabled = $true})
$ComboBox.Enabled = $false

# Buttons
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(140,145)
$Button.Size = New-Object System.Drawing.Size(80,25)
$Button.Text = "OK"
$Button.Enabled = $false
$Button.Add_Click({Set-OULocation -Location $ComboBox.SelectedItem.ToString()})

# Load Form
Load-Form

Create the script package

In order for the PowerShell script to be visible during a Task Sequence, we need to launch it with the help of a file called serviceUI.exe. That binary is available with MDT 2013 (you’d need to install MDT first, it’s also available in previous version of MDT). The file is located in these locations, depending on the architecture:

C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64
C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x86

Depending on your boot image architecture, be sure to grab the correct version of serviceUI.exe (a x64 boot image only works with the x64 version of serviceUI.exe). Copy the serviceUI.exe to the same folder you stored the Set-OULocationPrompt.ps1 file (in my case \\CAS01.contoso.com\Source$\Pkgs\OSDOULocation).

98_1

Create a package in ConfigMgr and call it Prompt for OU Location (or something else). The package does not need to have any program, but specify the content source folder where you stored serviceUI.exe and Set-OULocationPrompt.ps1. Remember to distribute your package.

Update your boot image to support PowerShell

If you havn’t already updated your boot images with PowerShell support, follow these instructions.

1. Right-click on your boot image and select Properties.
2. Select the Optional Components tab.
3. Click on the yellow star and select the following components:

  • Microsoft .NET (WinPE-NetFx4)
  • Windows PowerShell (WinPE-PowerShell3)

Note! In ConfigMgr 2012 R2 the names of the optional components differ a bit. Add the following:

  • Microsoft .NET (WinPE-NetFx)
  • Windows PowerShell (WinPE-PowerShell)

4. Click OK and then OK again. Let the wizard update your Distribution Points.

Implement the script in a Task Sequence

1. Edit the Task Sequence that you wish to add this functionality to.
2. Add a Run Command Line step in between the Apply Windows Settings and Apply Network Settings steps.
3. Rename the Run Command Line step to Prompt for OU Location.
4. Edit the Command Line so that it looks like this:

ServiceUI.exe -process:TSProgressUI.exe %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File Set-OULocationPrompt.ps1 -RBOptionFirst Workstation -RBOptionSecond Server -DomainName Contoso -DomainSuffix com -LocationList @("Stockholm","Sumpan")

5. Put a check mark in the Package box, click Browse and select your newly created package (Prompt for OU Location).
6. It’s important that the Domain OU field in the Apply Network Settings step is empty.

98_4

7. Start off a deployment of a new client. At the stage where it’s gonna execute the script, you’ll be presented with the following window:

98_0

I understand that this may not suite every environment, because the OU layout differs from environment to environment. But at least you’ve been given the tools to modify it to work in your environment.

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.

(1466)

comments
  • Eden Oliveira
    Posted at 16:35 December 31, 2014
    Eden Oliveira
    Reply
    Author

    Hi Nickolaj, First, thank you for one more important tip for all of us, SCCM Admins.

    You have already mentioned at the end of your post that the script has to be changed in order to meet other OU structures, that is my case.

    I’m not a very good scripting guy, however I believe it will be easy to adapt your solution to meet my needs.

    For example, I have four levels deeper on my LDAP path, for instance (OU=Workstations,OU=%DEPARTMENT%,OU=Users-Computers,OU=%SITECODE%,OU=LOCATIONS,DC=contoso,DC=com).

    How I should Adapt your script to meet those four levels down before the Domain name?

    Thank you very much for your help in advance.

    • Nickolaj
      Posted at 11:03 January 2, 2015
      Nickolaj
      Reply
      Author

      Hi Eden,

      First of, thank you! Regarding your question about changing the script to meet your needs, I’d need to know what you’d like to make “selectable”. With that I mean, what is is that you’d like to be prompted about to choose? Is it only by department or also site code?

      Regards,
      Nickolaj

      • Eden
        Posted at 15:57 January 2, 2015
        Eden
        Reply
        Author

        Hi Nickolaj.

        For the moment, I dont need site code, however I will in the future test (Like BRA, USA, CHI, UK, RUS, SWD). Since for the moment I will deploy only to my Country (Canada), I was thinking about changing the dropdown list (Once I select workstation radio button, it will show me what Departments I have available with a workstation OU). The dropdown would show IT, HR, Accounting, per line.

        I believe I would have to change the “if” part, Im not good at powershell.

        Thank you again for being available to answer my questions.

        Have an amazing year!

        Eden

  • Eden
    Posted at 16:24 January 2, 2015
    Eden
    Reply
    Author

    Hi Nickolaj.

    Another option would be, hardcode all the OU Departments like I did for two LDAP below: (But I dont know how to add more departments on that “if” loop. Sounds simple, but I dont know.

    function Set-OULocation {
    param(
    [parameter(Mandatory=$true)]
    $Location
    )
    if ($RBOption1.Checked -eq $true) {
    $OULocation = “LDAP://OU=Workstations,OU=IT,OU=Computers,OU=MTL,OU=LOCATIONS,DC=contoso,DC=local”
    }
    if ($RBOption2.Checked -eq $true) {
    $OULocation = “LDAP://OU=Workstations,OU=HR,OU=Computers,OU=MTL,OU=LOCATIONS,DC=contoso,DC=local”
    }
    $TSEnvironment = New-Object -COMObject Microsoft.SMS.TSEnvironment
    $TSEnvironment.Value(“OSDDomainOUName”) = “$($OULocation)”
    $Form.Close()

    Take care and thank you in advance.

    Eden

    • Nickolaj
      Posted at 12:21 January 8, 2015
      Nickolaj
      Reply
      Author

      Hi Eden,

      Thank you very much, I hope you got a good start of 2015 as well.

      From what I can understand, it doesn’t seem to me that you need to be able to choose between a “server” or a “workstation”. Basically what you want initially is the option to have a drop down list with all of the locations in your company. If you’re to incorporate the Site Code part to the mix, you could replace the two radio buttons with another drop down list where you select the site code.

      Would you like me to create such a script for you? If so, send me an email (you’ll find my email on the About page).

      Regards,
      Nickolaj

      • Eden
        Posted at 14:50 January 8, 2015
        Eden
        Reply
        Author

        Good morning Nickolaj, that is very nice from you doing that for me. That’s exactly what I was thinking about.

        I wil be deploying only workstations, but my environment is full of OUs (For Sites and Depts).

        Ill be sending you and email today.

        Thanks a lot again for your support.

        Eden

      • Ettienne
        Posted at 13:52 August 27, 2015
        Ettienne
        Reply
        Author

        hi Nickolaj,i know this is an old thread,do you have an example of that script maybe whohc you created for eden?

        • David S
          Posted at 22:38 June 27, 2017
          David S
          Reply
          Author

          Nickolaj, to save reinventing the wheel I was wondering if I could have a copy of what you were talking about with the dropdown list that references the various locations as opposed to the workstation parameter.

  • Ryan Gutierrez
    Posted at 18:52 January 5, 2015
    Ryan Gutierrez
    Reply
    Author

    Thanks for the post, this will make my deployments easier as my helpdesk techs are too lazy to put the computer in the proper OU. I am trying to implement the script as you described, using SCCM 2012 R2 and I am receiving the following error:

    powershell.exe – Application Error

    The exception unknown software exception (0xe0434352) occurred in the application at location 0xe6fb8384.

    I made some modifications to the powershell script to reflect my OU/Domain structure and it runs fine on my machine, but when I deploy it through a task sequence I get the error. Do you have any ideas or thoughts as to what could be wrong?

    • Nickolaj
      Posted at 09:54 January 7, 2015
      Nickolaj
      Reply
      Author

      Hi Ryan,

      That doesn’t sound right, tough call though what could be the problem. Have you embedded .NET Framework and PowerShell in the boot image? Did you get that error from the smsts.log file? If not, could you please examine it more in detail and post the snippet containing the errors.

      Regards,
      Nickolaj

  • Rhys
    Posted at 00:02 September 1, 2015
    Rhys
    Reply
    Author

    Hi there,
    Thanks for this article. However I am having trouble in that the locations list won’t expand each array item when running it in the TS, for example it just displays @Sydney,Melbourne,Brisbane,Perth on one line however it works when just running it on my computer in the Powershell window.
    Any ideas?
    Thanks,
    Rhys

    • Clint
      Posted at 16:50 January 26, 2016
      Clint
      Reply
      Author

      I have the same problem and foud out that the problem is caused because the script is running from a dos-prompt first. But i can’t solve it.

    • Wendy
      Posted at 18:53 January 30, 2017
      Wendy
      Reply
      Author

      I also have this same problem. It displays @location1,location2,location3,location4 as a single choice in the dropdown box. Has anyone found a solution to this?

    • Tyler
      Posted at 04:31 June 27, 2017
      Tyler
      Reply
      Author

      Has anyone found a solution to this issue yet? The script would be incredibly useful, but I can’t get the different drop-down items to appears on separate lines 🙁

      • KW
        Posted at 12:08 July 4, 2017
        KW
        Reply
        Author

        I found a workaround for the issue everyone’s describing here. It results in a slightly less dynamic script, so if there are changes to the locationlist it would require editing the script itself. But it works in the environment I’m using.

        I edited the function Load-Form {} section like so:

        I changed the line:

        $ComboBox.Items.AddRange($LocationList)

        To:

        $ComboBox.Items.AddRange((“loc1″,”loc2″,”loc3″,”loc4”) # $LocationList
        )

        I prefer to comment out instead of deleting so that I still have a reference for what I was doing.

        That makes it use some static values instead of having them supplied through the command line. But it does make it a proper drop-down list and it does pass the variables through to the TS, and that’s what counts in the end. 🙂

        I made some other alterations as well, removing the radio buttons, adding a textbox, coding it so that it takes the location code and pre-fills it into the textbox for a technician to finish entering the rest of the computer name.

  • Phil
    Posted at 13:29 February 16, 2016
    Phil
    Reply
    Author

    Hi There, I have the same issue as client, the locations just displays next to each other in the drop down list, any ideas?

  • Jerry
    Posted at 18:21 May 24, 2016
    Jerry
    Reply
    Author

    I have multiple domains but i can’t get it to accept my second option

  • Steve
    Posted at 22:02 June 15, 2016
    Steve
    Reply
    Author

    I apologize I am pretty new with PowerShell and so these functions and stuff are really confusing me. Could you please put more screen shots on how I am supposed to actually configure the script for multiple OU’s? Where am I supposed to change these paramters? Where do I put what I want the text to say?

    This isn’t explained very well…..

  • Kenneth Jensen
    Posted at 13:19 March 20, 2017
    Kenneth Jensen
    Reply
    Author

    Hello,
    I am using the script in SCCM Current Branch (1610).
    The TS show action “Running powershell script”, but no form show, and the TS never progresses from that. No errors to be found in the smsts log
    The script works fine when running in a Win 10 Powershell.

    Can you help?

    • Kenneth Jensen
      Posted at 14:00 March 20, 2017
      Kenneth Jensen
      Reply
      Author

      Please forget my stupid question.

      I normally change 2012 “run command line” instructions to “run powershell script” in SCCM 2016, but of course that’s not possible when running the script via serviceUI.

      Thanks for a great script, that I have succesfully (somewhat at least :-)) extended with computername, and different content of combobox, depending on the chosen radiobutton.

      Rgs
      Kenneth

  • Leave a Reply