Advertisement
Guest User

Untitled

a guest
Jun 12th, 2025
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.11 KB | None | 0 0
  1. # --- Load Required Assemblies for UI ---
  2. Add-Type -AssemblyName System.Windows.Forms
  3. Add-Type -AssemblyName System.Drawing
  4.  
  5. #region --- UI Functions ---
  6. # --- Function to Show Desktop Naming Form ---
  7. function Show-DesktopNamingForm {
  8. param (
  9. [System.Collections.Generic.List[string]]$BuildingCodes,
  10. [string]$PrefillBuilding,
  11. [string]$PrefillRoom,
  12. [string]$PrefillAssetTag
  13. )
  14.  
  15. $form = New-Object System.Windows.Forms.Form
  16. $form.Text = 'Desktop Naming'
  17. $form.Size = New-Object System.Drawing.Size(320, 240)
  18. $form.StartPosition = 'CenterScreen'
  19. $form.FormBorderStyle = 'FixedDialog'
  20. $form.TopMost = $true
  21. $form.MaximizeBox = $false
  22. $form.MinimizeBox = $false
  23.  
  24. $labelBuilding = New-Object System.Windows.Forms.Label
  25. $labelBuilding.Location = New-Object System.Drawing.Point(20, 20)
  26. $labelBuilding.Size = New-Object System.Drawing.Size(100, 20)
  27. $labelBuilding.Text = 'Building Code:'
  28. $form.Controls.Add($labelBuilding)
  29.  
  30. $comboBuilding = New-Object System.Windows.Forms.ComboBox
  31. $comboBuilding.Location = New-Object System.Drawing.Point(130, 18)
  32. $comboBuilding.Size = New-Object System.Drawing.Size(150, 20)
  33. $comboBuilding.DropDownStyle = 'DropDownList'
  34. $BuildingCodes.ForEach({ [void]$comboBuilding.Items.Add($_) })
  35. $comboBuilding.SelectedItem = $PrefillBuilding
  36. $form.Controls.Add($comboBuilding)
  37.  
  38. $labelRoom = New-Object System.Windows.Forms.Label
  39. $labelRoom.Location = New-Object System.Drawing.Point(20, 60)
  40. $labelRoom.Size = New-Object System.Drawing.Size(100, 20)
  41. $labelRoom.Text = 'Room Number:'
  42. $form.Controls.Add($labelRoom)
  43.  
  44. $textRoom = New-Object System.Windows.Forms.TextBox
  45. $textRoom.Location = New-Object System.Drawing.Point(130, 58)
  46. $textRoom.Size = New-Object System.Drawing.Size(150, 20)
  47. $textRoom.Text = $PrefillRoom
  48. $form.Controls.Add($textRoom)
  49.  
  50. $labelAssetTag = New-Object System.Windows.Forms.Label
  51. $labelAssetTag.Location = New-Object System.Drawing.Point(20, 100)
  52. $labelAssetTag.Size = New-Object System.Drawing.Size(100, 20)
  53. $labelAssetTag.Text = 'Asset Tag:'
  54. $form.Controls.Add($labelAssetTag)
  55.  
  56. $textAssetTag = New-Object System.Windows.Forms.TextBox
  57. $textAssetTag.Location = New-Object System.Drawing.Point(130, 98)
  58. $textAssetTag.Size = New-Object System.Drawing.Size(150, 20)
  59. $textAssetTag.Text = $PrefillAssetTag
  60. $form.Controls.Add($textAssetTag)
  61.  
  62. $buttonOK = New-Object System.Windows.Forms.Button
  63. $buttonOK.Location = New-Object System.Drawing.Point(105, 150) # Centered the OK button
  64. $buttonOK.Size = New-Object System.Drawing.Size(90, 30)
  65. $buttonOK.Text = 'OK'
  66. $form.Controls.Add($buttonOK)
  67.  
  68. # Event handler for OK button to perform validation
  69. $buttonOK.Add_Click({
  70. if ([string]::IsNullOrWhiteSpace($comboBuilding.SelectedItem) -or [string]::IsNullOrWhiteSpace($textRoom.Text) -or [string]::IsNullOrWhiteSpace($textAssetTag.Text)) {
  71. [System.Windows.Forms.MessageBox]::Show('Building Code, Room Number, and Asset Tag cannot be empty.', 'Validation Error', 'OK', 'Error')
  72. $form.DialogResult = [System.Windows.Forms.DialogResult]::None # Prevent form from closing
  73. } else {
  74. $form.DialogResult = [System.Windows.Forms.DialogResult]::OK
  75. }
  76. })
  77.  
  78. # Loop until valid input is provided
  79. do {
  80. $dialogResult = $form.ShowDialog()
  81. } while ($dialogResult -eq [System.Windows.Forms.DialogResult]::None) # Keep showing if validation failed
  82.  
  83. if ($dialogResult -eq [System.Windows.Forms.DialogResult]::OK) {
  84. return [pscustomobject]@{
  85. BuildingCode = $comboBuilding.SelectedItem
  86. RoomNumber = $textRoom.Text
  87. AssetTag = $textAssetTag.Text
  88. }
  89. }
  90. # This block should technically not be reached if OK requires valid input
  91. return $null
  92. }
  93.  
  94. # --- Function to Show Laptop Asset Tag Prompt ---
  95. function Show-LaptopAssetTagPrompt {
  96. param(
  97. [string]$PrefillAssetTag = ""
  98. )
  99.  
  100. $form = New-Object System.Windows.Forms.Form
  101. $form.Text = 'Asset Tag Required'
  102. $form.Size = New-Object System.Drawing.Size(320, 180)
  103. $form.StartPosition = 'CenterScreen'
  104. $form.FormBorderStyle = 'FixedDialog'
  105. $form.TopMost = $true
  106. $form.MaximizeBox = $false
  107. $form.MinimizeBox = $false
  108.  
  109. $labelInfo = New-Object System.Windows.Forms.Label
  110. $labelInfo.Location = New-Object System.Drawing.Point(20, 20)
  111. $labelInfo.Size = New-Object System.Drawing.Size(280, 40)
  112. $labelInfo.Text = "No asset tag found please enter the device asset tag"
  113. $form.Controls.Add($labelInfo)
  114.  
  115. $textAssetTag = New-Object System.Windows.Forms.TextBox
  116. $textAssetTag.Location = New-Object System.Drawing.Point(20, 70)
  117. $textAssetTag.Size = New-Object System.Drawing.Size(260, 20)
  118. $textAssetTag.Text = $PrefillAssetTag
  119. $form.Controls.Add($textAssetTag)
  120.  
  121. $buttonOK = New-Object System.Windows.Forms.Button
  122. $buttonOK.Location = New-Object System.Drawing.Point(105, 110)
  123. $buttonOK.Size = New-Object System.Drawing.Size(90, 30)
  124. $buttonOK.Text = 'OK'
  125. $form.Controls.Add($buttonOK)
  126.  
  127. # Event handler for OK button to perform validation
  128. $buttonOK.Add_Click({
  129. if ([string]::IsNullOrWhiteSpace($textAssetTag.Text)) {
  130. [System.Windows.Forms.MessageBox]::Show('Asset Tag cannot be empty.', 'Validation Error', 'OK', 'Error')
  131. $form.DialogResult = [System.Windows.Forms.DialogResult]::None # Prevent form from closing
  132. } else {
  133. $form.DialogResult = [System.Windows.Forms.DialogResult]::OK
  134. }
  135. })
  136.  
  137. $form.ActiveControl = $textAssetTag
  138.  
  139. # Loop until valid input is provided
  140. do {
  141. $dialogResult = $form.ShowDialog()
  142. } while ($dialogResult -eq [System.Windows.Forms.DialogResult]::None) # Keep showing if validation failed
  143.  
  144. if ($dialogResult -eq [System.Windows.Forms.DialogResult]::OK) {
  145. return $textAssetTag.Text
  146. }
  147. # This block should technically not be reached if OK requires valid input
  148. return $null
  149. }
  150. #endregion
  151.  
  152. # --- Helper Function to Update AD Description ---
  153. function Update-ADComputerDescription {
  154. param (
  155. [Parameter(Mandatory=$true)]
  156. [ADComputer]$ADComputerObject,
  157. [Parameter(Mandatory=$true)]
  158. [string]$NewDescription
  159. )
  160. try {
  161. Set-ADComputer -Identity $ADComputerObject -Description $NewDescription -ErrorAction Stop
  162. Write-Output "Successfully updated AD object '$($ADComputerObject.Name)' description to '$NewDescription'."
  163. } catch {
  164. Write-Warning "Failed to update AD object description for '$($ADComputerObject.Name)'. Error: $($_.Exception.Message)"
  165. }
  166. }
  167.  
  168. ---
  169. ## Main Script Logic
  170. ---
  171.  
  172. try {
  173. # 1. Initialize SCCM Task Sequence Environment
  174. $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment
  175. Write-Output "Successfully connected to Task Sequence environment."
  176.  
  177. # 2. Gather Hardware Information
  178. $serialNumber = (Get-WmiObject -Class Win32_BIOS).SerialNumber.Trim()
  179. $chassisTypes = (Get-WmiObject -Class Win32_SystemEnclosure).ChassisTypes
  180. $smbiosGuid = (Get-WmiObject -Class Win32_ComputerSystemProduct).UUID
  181. $laptopChassisTypes = @(8, 9, 10, 11, 12, 14, 18, 21, 31, 32)
  182. $isLaptop = $chassisTypes | Where-Object { $laptopChassisTypes -contains $_ }
  183.  
  184. Write-Output "Serial Number: $serialNumber"
  185. Write-Output "Machine Type: $(if($isLaptop){'Laptop'} else {'Desktop'})"
  186.  
  187. # 3. Find existing AD Computer Object
  188. $adComputer = $null
  189. $existingAssetTag = $null
  190. try {
  191. # This requires the AD module to be installed on the environment where the script runs
  192. Import-Module ActiveDirectory -ErrorAction SilentlyContinue
  193. # Ensure 'description' is always retrieved
  194. $adComputer = Get-ADComputer -Filter "servicePrincipalName -like '*$smbiosGuid*'" -Properties description, Name -ErrorAction SilentlyContinue
  195. if ($adComputer) {
  196. Write-Output "Found existing AD computer object: $($adComputer.Name)"
  197. $existingAssetTag = $adComputer.description
  198. if ([string]::IsNullOrWhiteSpace($existingAssetTag)) {
  199. Write-Output "Existing AD object has no Asset Tag in its description."
  200. } else {
  201. Write-Output "Existing Asset Tag in AD: $existingAssetTag"
  202. }
  203. }
  204. else { Write-Output "No existing AD object found for this machine." }
  205. }
  206. catch {
  207. Write-Warning "Could not query Active Directory. Error: $($_.Exception.Message)"
  208. }
  209.  
  210. ---
  211. ## Laptop Logic
  212. ---
  213. if ($isLaptop) {
  214. $computerName = "LT-$($serialNumber)"
  215. Write-Output "Determined Laptop Computer Name: $computerName"
  216.  
  217. $assetTagToStore = $existingAssetTag
  218. # Only prompt if existing asset tag is null or empty
  219. if ([string]::IsNullOrWhiteSpace($existingAssetTag)) {
  220. Write-Output "AD object exists but description (Asset Tag) is missing or empty. Prompting user."
  221. $promptedAssetTag = Show-LaptopAssetTagPrompt -PrefillAssetTag $existingAssetTag
  222.  
  223. # Since the prompt now enforces input, $promptedAssetTag will always contain a value if the function returns.
  224. $assetTagToStore = $promptedAssetTag
  225. }
  226.  
  227. # Update AD description if an AD object was found and an asset tag is determined
  228. # This condition also ensures we don't write back the same value if it was already there
  229. # and not changed by the user.
  230. if ($adComputer -and ($assetTagToStore -ne $existingAssetTag)) {
  231. Update-ADComputerDescription -ADComputerObject $adComputer -NewDescription $assetTagToStore
  232. }
  233.  
  234. $tsenv.Value('OSDComputerName') = $computerName
  235. Write-Output "Set OSDComputerName to '$computerName' in Task Sequence environment."
  236. }
  237. ---
  238. ## Desktop Logic
  239. ---
  240. else {
  241. $buildingCodeFile = "\\scssccm2\Sources\Script_Sources\BuildingCodeList.txt"
  242. if (-not (Test-Path $buildingCodeFile)) {
  243. Write-Error "Cannot find Building Code list at '$buildingCodeFile'. Cannot continue."
  244. exit 1 # Exit task sequence if building code file is missing
  245. }
  246. $buildingCodes = New-Object System.Collections.Generic.List[string]
  247. Get-Content $buildingCodeFile | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | ForEach-Object { $buildingCodes.Add($_.Trim()) }
  248.  
  249. $prefill = @{ Building = ''; Room = ''; AssetTag = $existingAssetTag } # Pre-fill AssetTag from AD
  250. if ($adComputer) {
  251. # Try to pre-fill building and room from existing AD computer name
  252. $nameParts = $adComputer.Name.Split('-')
  253. if ($nameParts.Count -ge 2) {
  254. if ($buildingCodes.Contains($nameParts[0])) { $prefill.Building = $nameParts[0] }
  255. $prefill.Room = $nameParts[1]
  256. }
  257. }
  258.  
  259. $userInput = Show-DesktopNamingForm -BuildingCodes $buildingCodes -PrefillBuilding $prefill.Building -PrefillRoom $prefill.Room -PrefillAssetTag $prefill.AssetTag
  260.  
  261. # Since desktop naming form now enforces input, $userInput will never be $null here
  262. $last5OfSerial = if ($serialNumber.Length -gt 5) { $serialNumber.Substring($serialNumber.Length - 5) } else { $serialNumber }
  263. $computerName = "$($userInput.BuildingCode)-$($userInput.RoomNumber)-$($last5OfSerial)"
  264.  
  265. $tsenv.Value('OSDComputerName') = $computerName
  266. Write-Output "Set OSDComputerName to '$computerName' in Task Sequence environment."
  267.  
  268. # Update AD description with the entered Asset Tag
  269. if ($adComputer -and ($userInput.AssetTag -ne $existingAssetTag)) {
  270. Update-ADComputerDescription -ADComputerObject $adComputer -NewDescription $userInput.AssetTag
  271. }
  272. }
  273. }
  274. catch {
  275. Write-Error "A critical error occurred in the naming script: $($_.Exception.Message)"
  276. # Exit with a non-zero code to fail the Task Sequence step
  277. exit 1
  278. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement