├── LICENSE ├── Pwsh-Gather.ps1 └── README.md /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jonathan Conway 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Pwsh-Gather.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .DESCRIPTION 3 | Script to replace MDT Gather in MECM Task Sequences 4 | .EXAMPLE 5 | PowerShell.exe -ExecutionPolicy ByPass -File .ps1 [-Debug] 6 | .NOTES 7 | Author(s): Jonathan Conway 8 | Modified: 01/09/2021 9 | Version: 1.10 10 | #> 11 | 12 | Param ( 13 | [Switch]$Debug 14 | ) 15 | 16 | $TSvars = @{ } 17 | 18 | Function Get-BatteryInfo { 19 | 20 | # Is a battery present? 21 | if ($null -ne (Get-CimInstance -ClassName 'Win32_Battery')) { 22 | 23 | # Check if AC Power is connected - if it is connected then return '$IsOnBattery' = '$false' 24 | if ((Get-CimInstance -Namespace 'root\WMI' -Query 'SELECT * FROM BatteryStatus Where Voltage > 0' -ErrorAction 'SilentlyContinue').PowerOnline) { 25 | $IsOnBattery = $false 26 | } 27 | else { 28 | $IsOnBattery = $true 29 | } 30 | } 31 | else { 32 | # Otherwise return 'AcConnected' = 'false' 33 | $IsOnBattery = $false 34 | } 35 | 36 | $TSvars.Add('IsOnBattery', $IsOnBattery) 37 | 38 | } 39 | 40 | Function Get-BaseBoardInfo { 41 | 42 | $BaseBoard = Get-CimInstance -ClassName 'Win32_BaseBoard' 43 | 44 | $TSvars.Add('Product', $BaseBoard.Product) 45 | 46 | } 47 | 48 | Function Get-BiosInfo { 49 | 50 | $Bios = Get-CimInstance -ClassName 'Win32_BIOS' 51 | 52 | $TSvars.Add('BIOSReleaseDate', $Bios.ReleaseDate) 53 | $TSvars.Add('BIOSVersion', $Bios.SMBIOSBIOSVersion) 54 | $TSvars.Add('SerialNumber', $Bios.SerialNumber) 55 | 56 | } 57 | 58 | Function Get-BitLockerInfo { 59 | 60 | $EncryptionMethods = @{ 61 | '0' = 'NO_ENCRYPTION'; 62 | '1' = 'AES_128_WITH_DIFFUSER'; 63 | '2' = 'AES_256_WITH_DIFFUSER'; 64 | '3' = 'AES_128'; 65 | '4' = 'AES_256'; 66 | '5' = 'HARDWARE_ENCRYPTION'; 67 | '6' = 'AES_256'; 68 | '7' = 'XTS_AES_256' 69 | } 70 | 71 | $IsBDE = $false 72 | $BitlockerEncryptionMethod = "N/A" 73 | $EncryptedVolumes = Get-CimInstance -Namespace 'ROOT\cimv2\Security\MicrosoftVolumeEncryption' -Query 'SELECT * FROM Win32_EncryptableVolume' 74 | 75 | if ($EncryptedVolumes) { 76 | 77 | foreach ($EncryptedVolume in $EncryptedVolumes) { 78 | 79 | if ($EncryptedVolume.ProtectionStatus -ne '0') { 80 | 81 | $EncryptionMethod = [int]$EncryptedVolume.EncryptionMethod 82 | 83 | if ($EncryptionMethods.ContainsKey("$EncryptionMethod")) { 84 | $BitlockerEncryptionMethod = $EncryptionMethods["$EncryptionMethod"] 85 | } 86 | 87 | $IsBDE = $true 88 | 89 | } 90 | } 91 | } 92 | 93 | $TSvars.Add('IsBDE', $IsBDE.ToString()) 94 | $TSvars.Add('BitlockerEncryptionMethod', $BitlockerEncryptionMethod) 95 | 96 | } 97 | 98 | Function Get-ChassisInfo { 99 | 100 | $VirtualHosts = @{ 101 | 'Virtual Machine' = 'Hyper-V' 102 | 'VMware Virtual Platform' = 'VMware' 103 | 'VMware7,1' = 'VMware' 104 | 'VirtualBox' = 'VirtualBox' 105 | 'Xen' = 'Xen' 106 | 'AHV' = 'Nutanix' 107 | } 108 | 109 | $ComputerSystem = Get-CimInstance -ClassName 'Win32_ComputerSystem' 110 | 111 | $TSvars.Add('Memory', ($ComputerSystem.TotalPhysicalMemory / 1024 / 1024).ToString()) 112 | $TSvars.Add('Make', $ComputerSystem.Manufacturer) 113 | if ($ComputerSystem.Manufacturer -eq 'LENOVO') { 114 | $LenovoModel = (Get-CimInstance -ClassName Win32_ComputerSystemProduct).Version 115 | $TSvars.Add('Model', $LenovoModel) 116 | } 117 | else { 118 | $TSvars.Add('Model', $ComputerSystem.Model) 119 | } 120 | $TSvars.Add('SystemSKU', $ComputerSystem.SystemSKUNumber) 121 | 122 | if ($VirtualHosts.ContainsKey($ComputerSystem.Model)) { 123 | $IsVM = $true 124 | $TSvars.Add('IsVM', "$IsVM") 125 | $TSvars.Add('VMPlatform', $VirtualHosts[$ComputerSystem.Model]) 126 | } 127 | else { 128 | $IsVM = $false 129 | $TSvars.Add('IsVM', "$IsVM") 130 | $TSvars.Add('VMPlatform', 'N/A') 131 | } 132 | 133 | $DesktopChassisTypes = @('3', '4', '5', '6', '7', '13', '15', '16', '35', '36') 134 | $LaptopChassisTypes = @('8', '9', '10', '11', '12', '14', '18', '21') 135 | $ServerChassisTypes = @('23', '28') 136 | $TabletChassisTypes = @('30', '31', '32') 137 | 138 | $ChassisInfo = Get-CimInstance -ClassName 'Win32_SystemEnclosure' 139 | 140 | if ($null -or "" -or " " -eq $ChassisInfo.SMBIOSAssetTag) { 141 | $TSvars.Add('AssetTag', 'N/A') 142 | } 143 | else { 144 | $TSvars.Add('AssetTag', $ChassisInfo.SMBIOSAssetTag) 145 | } 146 | 147 | if ($IsVM -eq $false) { 148 | 149 | $ChassisInfo.ChassisTypes | ForEach-Object { 150 | 151 | if ($TSvars.ContainsKey('IsDesktop')) { 152 | $TSvars['IsDesktop'] = [string]$DesktopChassisTypes.Contains($PSItem.ToString()) 153 | } 154 | else { 155 | $TSvars.Add('IsDesktop', [string]$DesktopChassisTypes.Contains($PSItem.ToString())) 156 | $TSvars.Add('IsLaptop', "$false") 157 | $TSvars.Add('IsServer', "$false") 158 | $TSvars.Add('IsTablet', "$false") 159 | } 160 | 161 | if ($TSvars.ContainsKey('IsLaptop')) { 162 | $TSvars['IsLaptop'] = [string]$LaptopChassisTypes.Contains($PSItem.ToString()) 163 | } 164 | else { 165 | $TSvars.Add('IsLaptop', [string]$LaptopChassisTypes.Contains($PSItem.ToString())) 166 | $TSvars.Add('IsDesktop', "$false") 167 | $TSvars.Add('IsServer', "$false") 168 | $TSvars.Add('IsTablet', "$false") 169 | } 170 | 171 | if ($TSvars.ContainsKey('IsServer')) { 172 | $TSvars['IsServer'] = [string]$ServerChassisTypes.Contains($PSItem.ToString()) 173 | } 174 | else { 175 | $TSvars.Add('IsServer', [string]$ServerChassisTypes.Contains($PSItem.ToString())) 176 | $TSvars.Add('IsDesktop', "$false") 177 | $TSvars.Add('IsLaptop', "$false") 178 | $TSvars.Add('IsTablet', "$false") 179 | } 180 | 181 | if ($TSvars.ContainsKey('IsTablet')) { 182 | $TSvars['IsTablet'] = [string]$TabletChassisTypes.Contains($PSItem.ToString()) 183 | } 184 | else { 185 | $TSvars.Add('IsTablet', [string]$TabletChassisTypes.Contains($PSItem.ToString())) 186 | $TSvars.Add('IsDesktop', "$false") 187 | $TSvars.Add('IsLaptop', "$false") 188 | $TSvars.Add('IsServer', "$false") 189 | } 190 | } 191 | } 192 | 193 | } 194 | 195 | Function Get-ComputerSystemProductInfo { 196 | 197 | $ComputerSystemProduct = Get-CimInstance -ClassName 'Win32_ComputerSystemProduct' 198 | 199 | $TSvars.Add('UUID', $ComputerSystemProduct.UUID) 200 | $TSvars.Add('Vendor', $ComputerSystemProduct.Vendor) 201 | 202 | } 203 | 204 | Function Get-HardwareInfo { 205 | 206 | $Processor = Get-CimInstance -ClassName 'Win32_Processor' | Select-Object -First '1' 207 | 208 | if ($Processor.Manufacturer -eq 'GenuineIntel') { 209 | 210 | $ProcessorName = $Processor.Name 211 | [String]$RegExPattern = '([^-][0-9]{3,})' 212 | [int]$ProcessorFamily = ($ProcessorName | Select-String -Pattern $RegExPattern | Select-Object -ExpandProperty 'Matches').Value 213 | 214 | if ($ProcessorFamily -ge '8000') { 215 | $IsCoffeeLakeOrLater = $true 216 | } 217 | else { 218 | $IsCoffeeLakeOrLater = $false 219 | } 220 | 221 | $TSvars.Add('IsCoffeeLakeOrLater', "$IsCoffeeLakeOrLater") 222 | $TSvars.Add('ProcessorFamily', $ProcessorFamily) 223 | $TSvars.Add('ProcessorName', $ProcessorName) 224 | 225 | } 226 | 227 | $TSvars.Add('ProcessorManufacturer', $Processor.Manufacturer) 228 | $TSvars.Add('ProcessorSpeed', $Processor.MaxClockSpeed.ToString()) 229 | 230 | } 231 | 232 | Function Get-NetworkInfo { 233 | 234 | (Get-CimInstance -ClassName 'Win32_NetworkAdapterConfiguration' -Filter 'IPEnabled = 1') | ForEach-Object { 235 | 236 | # Get IP address information 237 | $PSItem.IPAddress | ForEach-Object { 238 | if ($PSItem -ne $null) { 239 | if ($PSItem.IndexOf('.') -gt 0 -and -not $PSItem.StartsWith('169.254') -and $PSItem -ne '0.0.0.0') { 240 | 241 | if ($TSvars.ContainsKey('IPAddress')) { 242 | $TSvars['IPAddress'] = $TSvars['IPAddress'] + ',' + $PSItem 243 | } 244 | else { 245 | $TSvars.Add('IPAddress', $PSItem) 246 | } 247 | } 248 | } 249 | } 250 | 251 | # Get Default Gateway information 252 | $PSItem.DefaultIPGateway -split ',' | Select-Object -First '1' | ForEach-Object { 253 | if ($PSItem -ne $null -and $PSItem.IndexOf('.') -gt 0) { 254 | 255 | if ($TSvars.ContainsKey('DefaultGateway')) { 256 | $TSvars['DefaultGateway'] = $TSvars['DefaultGateway'] + ',' + $PSItem 257 | } 258 | else { 259 | $TSvars.Add("DefaultGateway", $PSItem) 260 | } 261 | } 262 | } 263 | 264 | } 265 | 266 | # Check to see if the device is connected via Ethernet and return $true if it is 267 | $EthernetConnection = Get-CimInstance -ClassName 'Win32_NetworkAdapter' | Where-Object { $PSItem.Name -like "*Ethernet Connection*" -or $PSItem.Name -like "*Realtek PCIe*" -and $PSItem.NetConnectionStatus -eq '2' } 268 | 269 | if ($null -eq $EthernetConnection) { 270 | $IsOnEthernet = $false 271 | } 272 | else { 273 | $IsOnEthernet = $true 274 | } 275 | 276 | $TSvars.Add('IsOnEthernet', "$IsOnEthernet") 277 | 278 | # Get device MAC addresses for connected NICs 279 | $Nic = (Get-CimInstance -ClassName 'Win32_NetworkAdapter' -Filter 'NetConnectionStatus = 2') 280 | 281 | $TSvars.Add('MacAddress', $Nic.MACAddress -join ',') 282 | 283 | } 284 | 285 | Function Get-OsInfo { 286 | 287 | $Os = Get-CimInstance -ClassName 'Win32_OperatingSystem' 288 | $OsBuildRegistryInfo = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' 289 | [string]$OsBuildNumber = ($OsBuildRegistryInfo.CurrentBuild) + '.' + ($OsBuildRegistryInfo.UBR) 290 | $OsInWinPE = Test-Path -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\MiniNT' 291 | [string]$OsWindowsInstallationType = $OsBuildRegistryInfo.InstallationType 292 | [string]$OsProductName = $OsBuildRegistryInfo.ProductName 293 | 294 | if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { 295 | $Architecture = 'X64' 296 | } 297 | else { 298 | $Architecture = 'X86' 299 | } 300 | 301 | $TSvars.Add('Architecture', $Architecture) 302 | $TSvars.Add('OSCurrentVersion', $Os.Version) 303 | $TSvars.Add('OSCurrentBuild', $Os.BuildNumber) 304 | $TSvars.Add('OSBuildNumber', $OsBuildNumber) 305 | $TSvars.Add('OsInWinPE', $OsInWinPE) 306 | 307 | if ($OsInWinPE -eq $true) { 308 | $TSvars.Add('OsLocale', 'N/A') 309 | } 310 | else { 311 | $TSvars.Add('OsLocale', (Get-WinSystemLocale).Name) 312 | } 313 | 314 | if ($ComputerInfo.WindowsInstallationType -eq 'WindowsPE' -or $OsInWinPE -eq $true) { 315 | $TSvars.Add('OsTimeZone', 'N/A') 316 | } 317 | else { 318 | $TSvars.Add('OsTimeZone', (Get-TimeZone).DisplayName) 319 | } 320 | 321 | $TSvars.Add('OsWindowsInstallationType', $OsWindowsInstallationType) 322 | $TSvars.Add('OsWindowsProductName', $OsProductName) 323 | 324 | } 325 | 326 | # Run all functions 327 | Get-BatteryInfo 328 | Get-BaseBoardInfo 329 | Get-BiosInfo 330 | Get-BitLockerInfo 331 | Get-ChassisInfo 332 | Get-ComputerSystemProductInfo 333 | Get-HardwareInfo 334 | Get-NetworkInfo 335 | Get-OsInfo 336 | 337 | # If Debug is true then print all variables to the console 338 | if ($Debug) { 339 | 340 | Start-Transcript -Path "$env:windir\Temp\Pwsh-Gather.log" -Append -NoClobber 341 | 342 | $TSvars.Keys | Sort-Object | ForEach-Object { 343 | Write-Host "$($PSItem) = $($TSvars[$PSItem])" -BackgroundColor 'Blue' -ForegroundColor 'Black' 344 | } 345 | 346 | Stop-Transcript 347 | 348 | } 349 | 350 | # If Debug is false then add variables to the Task Sequence environment 351 | else { 352 | 353 | $tsenv = New-Object -ComObject Microsoft.SMS.TSEnvironment 354 | $temp = $tsenv.Value("OSDComputerName") 355 | $LogPath = $tsenv.Value("_SMSTSLogPath") 356 | 357 | Start-Transcript -Path $LogPath\Pwsh-Gather.log -Append -NoClobber 358 | 359 | if (-not $temp) { 360 | $TSvars.Add("OSDComputerName", $tsenv.Value("_SMSTSMachineName")) 361 | } 362 | 363 | $TSvars.Keys | Sort-Object | ForEach-Object { 364 | $tsenv.Value($PSItem) = $TSvars[$PSItem] 365 | Write-Output "$($PSItem) = $($TSvars[$PSItem])" 366 | } 367 | 368 | Stop-Transcript 369 | 370 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PowerShell_Gather 2 | PowerShell script to replace MDT Gather in Windows OSD. 3 | 4 | It collects information from a device and stores these as variables which can then be utilised as SCCM Task Sequence variables to set logic for various actions. 5 | 6 | The advantage of this is that in most scenarios, you not longer need to use MDT-integrated Task Sequences and can therefore avoid using and maintaining the various MDT components required otherwise. 7 | 8 | Script can be run in a Task in an SCCM Task Sequence - easiest way is to add the script content as a "Run PowerShell Script' step with the Execution Policy set to 'Bypass'. 9 | 10 | For testing, the script can be run locally by using the '-Debug' parameter as per the example below from an Administrator PowerShell prompt: 11 | 12 | **PS C:\Users\Administrator\Documents\PowerShell_Gather> .\Pwsh-Gather.ps1 -Debug** 13 | 14 | The vast majority of the groundwork for this script was done by Johan Schrewelius (https://gallery.technet.microsoft.com/PowerShell-script-that-a8a7bdd8) who has kindly allowed me to share and update his work. 15 | 16 | Variables currently gathered are shown in the example output below: 17 | 18 | - Architecture = X64 19 | - AssetTag = CZC6XXXXXX 20 | - BIOSReleaseDate = 04/19/2021 01:00:00 21 | - BIOSVersion = N01 Ver. 02.53 22 | - BitlockerEncryptionMethod = N/A 23 | - DefaultGateway = 192.168.1.1 24 | - IPAddress = 192.168.1.20 25 | - IsBDE = False 26 | - IsCoffeeLakeOrLater = False 27 | - IsDesktop = True 28 | - IsLaptop = False 29 | - IsOnBattery = False 30 | - IsOnEthernet = True 31 | - IsServer = False 32 | - IsTablet = False 33 | - IsVM = False 34 | - MacAddress = 48:0F:CF:45:06:F1,48:0F:CF:45:06:F1 35 | - Make = HP 36 | - Memory = 65415.58203125 37 | - Model = HP EliteDesk 800 G2 SFF 38 | - OSBuildNumber = 17763.2114 39 | - OSCurrentBuild = 17763 40 | - OSCurrentVersion = 10.0.17763 41 | - OsInWinPE = False 42 | - OsLocale = en-GB 43 | - OsTimeZone = (UTC+00:00) Dublin, Edinburgh, Lisbon, London 44 | - OsWindowsInstallationType = Server 45 | - OsWindowsProductName = Windows Server 2019 Standard 46 | - ProcessorFamily = 6700 47 | - ProcessorManufacturer = GenuineIntel 48 | - ProcessorName = Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz 49 | - ProcessorSpeed = 3408 50 | - Product = 8054 51 | - SerialNumber = CZC6XXXXXX 52 | - SystemSKU = L1G76AV 53 | - UUID = D41CCC6A-E086-11E5-9C43-BC0000EE0000 54 | - Vendor = HP 55 | - VMPlatform = N/A --------------------------------------------------------------------------------