Last active
May 30, 2023 22:35
-
-
Save ocelotsloth/18186406f10ba6d7381abae3f3825052 to your computer and use it in GitHub Desktop.
MDT Dropdown OU Selector Modifications
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
' // *************************************************************************** | |
' // | |
' // Copyright (c) Microsoft Corporation. All rights reserved. | |
' // | |
' // Microsoft Deployment Toolkit Solution Accelerator | |
' // | |
' // File: DeployWiz_Initialization.vbs | |
' // | |
' // Version: 6.3.8450.1000-ocelotsloth-1.0 | |
' // | |
' // Purpose: Main Client Deployment Wizard Initialization routines | |
' // | |
' // *************************************************************************** | |
' // | |
' // Modified by: Mark Stenglein <mark@stengle.in> | |
' // | |
' // Purpose: Added support for human-readable drop-down selection of OUs. | |
' // | |
' // | |
' // Notes: Domain OUs must be added to a file called `DomainOUList.xml` | |
' // in this same deployment scripts directory. Format this file | |
' // as follows (this file can be dynamically generated by the | |
' // included powershell file): | |
' // | |
' // ```xml | |
' // <DomainOUs> | |
' // <DomainOU value="OU=Staff,DC=someschool,DC=org"> | |
' // Staff Comps | |
' // </DomainOU> | |
' // <DomainOU value="OU=Faculty,DC=someschool,DC=org"> | |
' // Faculty Comps | |
' // </DomainOU> | |
' // <DomainOU value="OU=Students,DC=someschool,DC=org"> | |
' // Student Comps | |
' // </DomainOU> | |
' // </DomainOUs> | |
' // ``` | |
' // | |
' // Be sure to clear any existing OU entries in the other config | |
' // areas, as they are likely to conflict with this script. Also | |
' // do not skip the domain configuration options. | |
' // | |
' // If you feel creative, you can emulate a tree'ed menu by | |
' // prefixing the human readable names as follows: | |
' // | |
' // |-- Staff Computers | |
' // | |-- Business Department | |
' // |-- Faculty Computers | |
' // |-- Science Department | |
' // |-- Math Department | |
' // | |
' // The modifications to this script do not change any core | |
' // functionality, and actually restores functionality that was | |
' // once present in an older version of this script released by | |
' // Microsoft. | |
' // | |
' // If this script ceases to work in the future when I do not work | |
' // here anymore, send me an email with your error and I'll see if | |
' // I can help. Alternatively, just create a new deployment share | |
' // for a reference of the old script. | |
' // | |
' // BACK THIS FILE UP BEFORE UPGRADING THE DEPLOYMENT SHARE | |
' // | |
' // Every time you install a new ADK or update MDT and then | |
' // need to upgrade the deployment share this file is | |
' // overwritten. They do actually make changes so please do not | |
' // simply overwrite the new file with the old one. You will | |
' // want to analyze the new file by diffing it with this one to | |
' // see what changes need to be applied to the new version. | |
' // | |
' // If you have trouble with this and want help feel free to | |
' // send me an email. | |
' // | |
' // *************************************************************************** | |
Option Explicit | |
Function InitializeComputerName | |
If oProperties("OSDComputerName") = "" then | |
OSDComputerName.Value = oUtility.ComputerName | |
End if | |
If UCase(oEnvironment.Item("SkipComputerName")) = "YES" then | |
OSDComputerName.disabled = true | |
End if | |
End Function | |
Function ValidateComputerName | |
' Check Warnings | |
ParseAllWarningLabels | |
If Len(OSDComputerName.value) > 15 then | |
InvalidChar.style.display = "none" | |
TooLong.style.display = "inline" | |
ValidateComputerName = false | |
ButtonNext.disabled = true | |
ElseIf IsValidComputerName ( OSDComputerName.Value ) then | |
ValidateComputerName = TRUE | |
InvalidChar.style.display = "none" | |
TooLong.style.display = "none" | |
Else | |
InvalidChar.style.display = "inline" | |
TooLong.style.display = "none" | |
ValidateComputerName = false | |
ButtonNext.disabled = true | |
End if | |
End function | |
'''''''''''''''''''''''''''' | |
Function AddItemToMachineObjectOUOpt(item,value) | |
Dim oOption | |
set oOption = document.createElement("OPTION") | |
oOption.Value = value | |
oOption.Text = item | |
oOption.Title = item | |
MachineObjectOUOptional.Add oOption | |
MachineObjectOUOptionalBtn.style.display = "inline" | |
End function | |
Function InitializeDomainMembership | |
Dim oLDAP, oOptOU, oItem | |
Dim sFoundFile | |
Dim iRetVal | |
' Prepopulate the join account details if they are presently blank | |
If Property("DomainAdmin") = "" and Property("DomainAdminDomain") = "" and Property("DomainAdminPassword") = "" then | |
If Property("UserID") <> "" and Property("UserDomain") <> "" and Property("UserPassword") <> "" Then | |
DomainAdmin.value = Property("UserID") | |
DomainAdminDomain.value = Property("UserDomain") | |
DomainAdminPassword.value = Property("UserPassword") | |
End if | |
End if | |
If JoinWorkgroup.value <> "" then | |
JDRadio2.checked = TRUE | |
ElseIf JoinDomain.Value = "" then | |
On Error Resume Next | |
JoinDomain.value = CreateObject("ADSystemInfo").DomainDNSName | |
On Error Goto 0 | |
If JoinDomain.Value = "" then | |
JoinWorkgroup.value = "WORKGROUP" | |
JDRadio2.checked = TRUE | |
Else | |
JDRadio1.checked = TRUE | |
' Domain.value = JoinDomain.Value | |
On error resume next | |
' Will extract out the existing OU (if any) for the current machine. | |
set oLDAP = GetObject("LDAP://" & CreateObject("ADSystemInfo").ComputerName) | |
MachineObjectOU.Value = oLDAP.Get("Organizational-Unit-Name") | |
On error goto 0 | |
End if | |
End if | |
'''''''''''''''''''''''''''''''' | |
' | |
' Populate OU method #1 - Query ADSI | |
' | |
MachineObjectOUOptionalBtn.style.display = "none" | |
'''''''''''''''''''''''''''''''' | |
' | |
' Populate OU method #2 - Read MachineObjectOUOptional[1...n] property | |
' | |
If MachineObjectOUOptionalBtn.style.display <> "inline" then | |
oOptOU = Property("DomainOUs") | |
If isarray(oOptOU) then | |
For each oItem in oOptOU | |
AddItemToMachineObjectOUOpt oItem | |
Next | |
MachineObjectOUOptionalBtn.style.display = "inline" | |
ElseIf oOptOU <> "" then | |
AddItemToMachineObjectOUOpt oOptOU | |
End if | |
End if | |
'''''''''''''''''''''''''''''''' | |
' | |
' Populate OU method #3 - Read ...\control\DomainOUList.xml | |
' | |
' Example: | |
' <?xml version="1.0" encoding="utf-8"?> | |
' <DomainOUs> | |
' <DomainOU>OU=Test1</DomainOU> | |
' <DomainOU>OU=Test2</DomainOU> | |
' </DomainOUs> | |
' | |
If MachineObjectOUOptionalBtn.style.display <> "inline" then | |
iRetVal = oUtility.FindFile( "DomainOUList.xml" , sFoundFile) | |
if iRetVal = SUCCESS then | |
For each oItem in oUtility.CreateXMLDOMObjectEx( sFoundFile ).selectNodes("//DomainOUs/DomainOU") | |
AddItemToMachineObjectOUOpt oItem.text, oItem.Attributes.getNamedItem("value").value | |
Next | |
End if | |
End if | |
If MachineObjectOUOptionalBtn.style.display = "inline" then | |
document.body.onMouseDown = getRef("DomainMouseDown") | |
document.body.onKeyDown = getRef("MachineObjectOUOptionalKeyPress") | |
End if | |
ValidateDomainMembership | |
End Function | |
Function MachineObjectOUOptionalKeyPress | |
dim OUOpt | |
on error resume next | |
set OUOpt = MachineObjectOUOptional | |
on error goto 0 | |
If isempty(OUOpt) then | |
KeyHandler | |
ElseIf window.event.srcElement is MachineObjectOUOptional then | |
If window.event.keycode = 13 then | |
' Enter | |
MachineObjectOU.value = MachineObjectOUOptional.value | |
PopupBox.style.display = "none" | |
ElseIf window.event.keycode = 27 then | |
' escape | |
PopupBox.style.display = "none" | |
End if | |
Else | |
KeyHandler | |
End if | |
End function | |
Function DomainMouseDown | |
If not window.event.srcElement is MachineObjectOUOptional and not window.event.srcElement is MachineObjectOUOptionalBtn then | |
PopupBox.style.display = "none" | |
End if | |
End function | |
Function HideUnHideComboBox | |
If UCase(PopupBox.style.display) <> "NONE" then | |
HideUnhide PopupBox, FALSE | |
document.body.onMouseDown = "" | |
document.body.onKeyDown = getRef("KeyHandler") | |
Else | |
HideUnhide PopupBox, TRUE | |
MachineObjectOUOptional.focus | |
document.body.onMouseDown = getRef("DomainMouseDown") | |
document.body.onKeyDown = getRef("MachineObjectOUOptionalKeyPress") | |
End if | |
End function | |
Function ValidateDomainMembership_Final | |
If JDRadio1.checked then | |
RMPropIfFound("JoinWorkgroup") | |
JoinWOrkgroup.Value = "" | |
Else | |
RMPropIfFound("JoinDomain") | |
JoinDomain.Value = "" | |
End if | |
ValidateDomainMembership_Final = true | |
End function | |
''''''''''''''''''''''''''''''''''''' | |
' Validate Domain Membership | |
' | |
Function ValidateDomainMembership | |
Dim IsDomain | |
Dim r | |
MissingCredentials.style.display = "none" | |
InvalidCredentials.style.display = "none" | |
InvalidOU.style.display = "none" | |
isDomain = JDRadio1.checked | |
If not isDomain then | |
RMPropIfFound("BdeInstall") | |
RMPropIfFound("BdeInstallSuppress") | |
RMPropIfFound("DoCapture") | |
RMPropIfFound("BackupFile") | |
If Property("DeploymentType") <> "REFRESH" and Property("DeploymentType") <> "REPLACE" then | |
RMPropIfFound("ComputerBackupLocation") | |
End if | |
End if | |
If UCase(oEnvironment.Item("SkipDomainMembership")) = "YES" then | |
' Hide all the domain/workgroup settings | |
DomainSection.style.display = "none" | |
JDRadio1.disabled = true | |
JDRadio2.disabled = true | |
JoinDomain.disabled = true | |
DomainAdmin.disabled = true | |
DomainAdminDomain.disabled = true | |
DomainAdminPassword.disabled = true | |
MachineObjectOU.disabled = true | |
MachineObjectOUOptionalBtn.disabled = true | |
MachineObjectOUOptional.disabled = true | |
JoinWorkgroup.disabled = true | |
ValidateDomainMembership = true | |
' Don't do any more validation because this has been disabled | |
Exit Function | |
Else | |
JoinDomain.disabled = not isDomain | |
DomainAdmin.disabled = not isDomain | |
DomainAdminDomain.disabled = not isDomain | |
DomainAdminPassword.disabled = not isDomain | |
MachineObjectOU.disabled = not isDomain | |
MachineObjectOUOptionalBtn.disabled = not isDomain | |
MachineObjectOUOptional.disabled = not isDomain | |
JoinWorkgroup.disabled = isDomain | |
End if | |
' Check Warnings | |
ValidateDomainMembership = ParseAllWarningLabels | |
' Check domain settings (without validation of credentials) | |
If IsDomain then | |
' Make sure the join account details are specified | |
If Trim(DomainAdmin.value) = "" or Trim(DomainAdminPassword.value) = "" or (Instr(DomainAdmin.Value, "@") = 0 and Trim(DomainAdminDomain.Value) = "") then | |
MissingCredentials.style.display = "inline" | |
ValidateDomainMembership = false | |
End if | |
' Check OU to make sure it is a valid format | |
If MachineObjectOU.Value <> "" then | |
' Make sure it starts with "OU=" or "OU " (equal could be preceeded by spaces) | |
If Left(UCase(Trim(MachineObjectOU.Value)), 3) <> "OU=" and Left(UCase(Trim(MachineObjectOU.Value)), 3) <> "OU " then | |
InvalidOU.style.display = "inline" | |
ValidateDomainMembership = false | |
End if | |
End if | |
End if | |
' Check credentials | |
If IsDomain and ValidateDomainMembership and (not window.event is Nothing) then | |
' Only check credentials when the next button is clicked | |
If window.event.srcElement is ButtonNext or window.event.KeyCode = 13 then | |
oLogging.CreateEntry "Validate Domain Credentials [" & DomainAdminDomain.value & "\" & DomainAdmin.value & "]", LogTypeInfo | |
If oEnvironment.Item("OSVersion") <> "WinPE" then | |
' Check using ADSI (not possible in Windows PE) | |
r = CheckCredentialsAD(DomainAdminDomain.value, DomainAdmin.value, DomainAdminDomain.value, DomainAdminPassword.value) | |
If r <> TRUE then | |
InvalidCredentials.innerText = "* Invalid credentials: " & r | |
InvalidCredentials.style.display = "inline" | |
ValidateDomainMembership = false | |
End if | |
ElseIf oEnvironment.Item("ValidateDomainCredentialsUNC") <> "" then | |
' Check using ADSI (not possible in Windows PE) | |
oLogging.CreateEntry "Validate Domain Credentials against UNC: " & oEnvironment.Item("ValidateDomainCredentialsUNC") , LogTypeInfo | |
r = CheckCredentials( oEnvironment.Item("ValidateDomainCredentialsUNC") , DomainAdmin.value, DomainAdminDomain.value, DomainAdminPassword.value) | |
oLogging.CreateEntry "Validate Domain Credentials against UNC: result = " & r , LogTypeInfo | |
If r <> TRUE then | |
InvalidCredentials.innerText = "* Invalid credentials: " & r | |
InvalidCredentials.style.display = "inline" | |
ValidateDomainMembership = false | |
End if | |
End if | |
End if | |
End if | |
' We need to clean up the keyboard hook | |
If ValidateDomainMembership then | |
document.body.onMouseDown = "" | |
End if | |
End Function |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Filename: generateDomainOUList.ps1 | |
# | |
# Adapted from https://social.technet.microsoft.com/Forums/en-US/b9dc1d73-c94b-404d-afeb-b8576fc0ab70/populate-ou-method-in-mdt-2012?forum=mdt | |
# by Mark Stenglein <mark@stengle.in> | |
# | |
# Before running this script be sure to modify the variables below to suit your | |
# environment. Additionally, under the "ForEach ($Item In $OUs)" loop around | |
# line 49 you may want to add your own OU Name substitutions. If you have long | |
# OU Names the dropdown menu in LiteTouch can be very long. Substitutions allow | |
# that menu to be far more useful. | |
# | |
# This file should be placed in and run from the Scripts directory in your MDT | |
# Share. | |
#Define Variables | |
# Put your Windows Domain Name | |
$Server = 'int.contoso.com' | |
# Put the root OU for your Computers | |
$SearchBase = "OU=CONTOSO COMPS,DC=int,DC=CONTOSO,DC=com" | |
# Leave as default if you want this to work properly with the MDT integration | |
$ExportPath = ".\DomainOUList.xml" | |
# Leave as default or change. This is where your backup goes. | |
$BackupPath = (Split-Path -Path $ExportPath -Parent) + "\DomainOUList_PreviousVersion.xml" | |
#Define ASCII Characters | |
$NewLine = "`r`n" | |
$Tab = "`t" | |
#Create Secure Credential Object | |
$Credentials = (Get-Credential -Message "Please enter the appropriate credentials to allow this script to query active directory (read only access is all that is required)." -UserName "$ExecutingUser_Domain\$ExecutingUser_UserName") | |
#Define Functions | |
#Determine The Parent Of An Active Directory Object | |
Function Get-ADObjectParent ($DistinguishedName) | |
{ | |
$Parts = $DistinguishedName -Split "(?<![\\])," | |
Return $Parts[1..$($Parts.Count - 1)] -Join "," | |
} | |
#Make A Backup Copy Of "DomainOUList.xml" | |
If (Test-Path -Path "$ExportPath") {Copy-Item -Path "$ExportPath" -Destination "$BackupPath" -Force | Out-Null} | |
#Create "DomainOUList.xml" | |
$DomainOUList_Create = (New-Item -ItemType File -Path "$ExportPath" -Force).FullName | |
#Retrieve Organizational Units From Active Directory And Sort The Results Based On CanonicalName | |
$OUs = Get-ADOrganizationalUnit -Filter * -Credential $Credentials -Properties * -SearchBase $SearchBase -SearchScope Subtree -Server $Server | Select *, @{Name="FriendlyName";Expression={($_.CanonicalName).Split("/")}}, @{Name="Parent";Expression={Get-ADObjectParent -DistinguishedName $_.DistinguishedName}} | Sort-Object CanonicalName | |
#Export To "DomainOUList.xml" for use with Microsoft Deployment Toolkit | |
If ($OUs.Count -gt 0) | |
{ | |
$Output = ("<?xml version=`"1.0`" encoding=`"utf-8`"?>" + $NewLine + $NewLine) | |
$Output += ("<DomainOUs>" + $NewLine + $NewLine) | |
ForEach ($Item In $OUs) | |
{ | |
#If You Want To Remove Portions Of The "$Item.FriendlyName" Property, Experiment With The "+ 4" Value. Example - Change It To + 3, etc... This May Make It Easier To See The Names When Selecting Them During Deployment. | |
$Item.FriendlyName = (($Item.FriendlyName)[($Item.FriendlyName.GetLowerBound(0) + 3)..($Item.FriendlyName.GetUpperBound(0))] -Join " \ ") | |
$Item.FriendlyName = $Item.FriendlyName -replace ' Comps','' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'Student Labs','Labs' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'Student Wireless','Wireless' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'Science Laptops','Sci Lap' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'Lab ','' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'ENGINEERING LAB','ENGLAB' | |
$Item.FriendlyName = $Item.FriendlyName -replace 'Art Lab Computers','Art' | |
#Write Each Result To The Console Host | |
Write-Host "Now Exporting `"$($Item.FriendlyName)`" to `"$($ExportPath)`"" -BackgroundColor Black -ForegroundColor Yellow | |
#Comment/Uncomment The Follwing Line If You Want To Make Use Of FriendlyNames, Only One Value May Be Used At A Time! | |
$Output += ($Tab + "<DomainOU value=`"$($Item.DistinguishedName)`">" + $NewLine + $Tab + $Tab + $($Item.FriendlyName) + $NewLine + $Tab + "</DomainOU>" + $NewLine + $NewLine) | |
#Comment/Uncomment The Follwing Line If You Want To Make Use Of DistinguishedNames, Only One Value May Be Used At A Time! | |
#$Output += ($Tab + "<DomainOU>" + $NewLine + $Tab + $Tab + $($Item.DistinguishedName) + $NewLine + $Tab + "</DomainOU>" + $NewLine + $NewLine) | |
} | |
$Output += ("</DomainOUs>") | |
#Export Data To "DomainOUList.xml" | |
$Output | Out-File "$ExportPath" -Append -Encoding utf8 | |
} | |
#Write The Results To The Console Host (Uncomment If You Would Like) | |
#@" | |
# $Output | |
#"@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment