Contoso Paradise
Thursday, January 12, 2023
Tuesday, November 30, 2021
Use paging with Graph to change group tags on all AutoPilot devices
Use paging with Graph to change group tags on all AutoPilot devices. Graph has a 1000 device limit and this script uses paging to get all of the devices. Once we have all of the devices we can manipulate group tags.
I would like to shout out January 2021 – TheSleepyAdmins for the assist on paging as well as Bulk Updating Autopilot enrolled devices with Graph API and assigning a Group Tag based on Purchase OrderID - Systems Management Squad (sysmansquad.com) for help with some of the other bits.
# Application (client) ID, tenant Name and secret
$clientid = Read-Host "Input your Client ID"
$clientSecret = Read-Host "Input Client Secret"
$TenantName = Read-Host "Input Tenant Name"
$resource = "https://graph.microsoft.com/"
#$grouptag = "AP-Tag1"
$ReqTokenBody = @{
Grant_Type = "client_credentials"
Scope = "https://graph.microsoft.com/.default"
client_Id = $clientID
Client_Secret = $clientSecret
}
$TokenResponse = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$TenantName/oauth2/v2.0/token" -Method POST -Body $ReqTokenBody
$apiUrl = 'https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/'
$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl -Method Get
$Results = @()
$Results += $Data.value
[int]$pagecount = 0
$Pages = $Data.'@odata.nextLink'
while($null -ne $Pages) {
$pagecount += 1
Write-host "Checking Page $Pagecount. Count is $($Results.count)"
$Addtional = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $Pages -Method Get
if ($Pages){
$Pages = $Addtional."@odata.nextLink"
}
$Results += $Addtional.value
}
$Results | Export-Csv -Path "c:\temp\Devices.csv" -NoTypeInformation
#Tag the devices
if($grouptag -ne $null){
$body = '{"groupTag":"'+$groupTag+'"}'
foreach ($Result in $Results) {
$apiUrl = "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotDeviceIdentities/$device/UpdateDeviceProperties"
$rest = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl -Body $body -Method Post -ContentType 'application/json'
Write-Host ($device + ' has been added to the ' + $grouptag)
}
#Sync the changes
$apiUrl2 = "https://graph.microsoft.com/beta/deviceManagement/windowsAutopilotSettings/sync"
Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $apiUrl2 -Method Post
}
Tuesday, November 9, 2021
PowerShell Code to get all AD Users and attributes.
#Get All AD Users
$Table = @()
$Arrayofmembers = Get-ADUser -filter {objectClass -eq "user"} -searchbase "DC=LOWES,DC=com" -Properties samaccountname | Sort-Object -Descending
[int]$count = $Arrayofmembers.Count
Foreach($A in $Arrayofmembers) {
$User = Get-ADUser $A.SamAccountName -Properties * | select name,cn,mail,physicaldeliveryofficename,title,extensionattribute12,extensionattribute5,extensionattribute10,extensionAttribute7, @{n=’MemberOf’; e= { ( $_.memberof | % { (Get-ADObject $_).Name }) -join “;” }}
[int]$count = $count - 1
Write-Host "Getting $($a.samaccountname) - $count to go"
$Obj=New-Object PSObject
$Obj | Add-Member -Name "name" -MemberType NoteProperty -Value $User.name
$Obj | Add-Member -Name "CN" -MemberType NoteProperty -Value $User.cn
$Obj | Add-Member -Name "physicaldeliveryofficename" -MemberType NoteProperty -Value $User.physicaldeliveryofficename
$Obj | Add-Member -Name "Title" -MemberType NoteProperty -Value $User.title
$Obj | Add-Member -Name "lowesEffectiveJobCode" -MemberType NoteProperty -Value $User.extensionattribute12
$Obj | Add-Member -Name "lowesEffectiveDeptNumber" -MemberType NoteProperty -Value $User.extensionattribute5
$Obj | Add-Member -Name "extensionattribute10" -MemberType NoteProperty -Value $User.extensionattribute10
$Obj | Add-Member -Name "lowesEffectivePhyLocationCode" -MemberType NoteProperty -Value $User.extensionAttribute7
$Table += $obj
}
$Table | export-csv "c:\Temp\ADUsers.csv" -NoTypeInformation
Monday, November 8, 2021
Installing and Bootstraping an SCCM task sequence during AutoPilot
log-it -message "Starting SCCM Install Script" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
cd $ScriptDir
log-it -message "Working dir is now $ScriptDir" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"
New-Item -Path C:\ -Name "Temp" -ItemType Directory -ErrorAction SilentlyContinue
New-Item -Path C:\Temp -Name "SCCM" -ItemType Directory -ErrorAction SilentlyContinue
log-it -message "PS Policy is now $Policy" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"
Function log-it {
param( $message, $component, $path, $thread = 0, $file = 0 )
[string]$time = Get-Date -format "HH:mm:ss.fff+300"
[string]$date = Get-Date -Format "MM-dd-yyyy"
$a = "<![LOG["
$b = "]LOG]!>"
$carrot = "<"
$closecarrot = ">"
$c = "time=""$time"" date=""$date"" component=""$component"" context="""" type=""1"" thread=""$thread"" file=""$file"""
$logentry = $a+$message+$b+$carrot+$c+$closecarrot
#Add-Content -Path c:\temp\SCCM-Install.log -Value $logentry
Add-Content -Path $path -Value $logmessage
}
log-it -message "Working directory is now $scriptdir" -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"
$dir = dir
log-it -message $dir -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"
Copy-Item .\ccmsetup.exe c:\temp\SCCM
Copy-Item .\CMTrace.exe c:\temp
$script=@'
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
cd $ScriptDir
#If SCCM is installed AND the AutoPilot TS ran
if( (get-service ccmexec -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").tsname -ne $null)
{
Disable-ScheduledTask AutoPilotCMClientInstall
}
#TS hasn't ran or didn't finish
else
{
#Checks if the user is logged in and in an active session
function Query-User
{
$users = (((quser) -ireplace '\s{2,}',',' | ConvertFrom-Csv).username).replace(">","")
if($users -eq "defaultuser0")
{
return $false
}
else
{
return $true
}
}
#Checks to make sure machine is connected to VPN
function Check-VPN
{
if ((Test-Connection $localServer -Count 1 -Quiet) -eq $false)
{
return $false
}
else
{
return $true
}
}
$isOnline = Check-VPN
$isUserLoggedIn = Query-User
While(($isOnline -eq $false) -or ($isUserLoggedIn -eq $false))
{
$isOnline = Check-VPN
$isUserLoggedIn = Query-User
sleep -Seconds 5
}
#If TSManager.exe is not running then the TS is not actively running. Okay to install SCCM
if((ps TSManager -ErrorAction SilentlyContinue) -eq $null)
{
Start-Process c:\temp\SCCM\ccmsetup.exe -argumentlist "/noCRLCheck /mp:CompanyCMG.CLOUDAPP.NET CCMHOSTNAME=CompanyCMG.CLOUDAPP.NET/CCM_Proxy_MutualAuth/72057594037958338 SMSSiteCode=XXX PROVISIONTS=C0220AC4 /forceinstall"
}
sleep -Seconds 600
#If SCCM is installed AND the AutoPilot TS ran
if( (get-service ccmexec -ErrorAction SilentlyContinue) -and (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").tsname -ne $null)
{
Disable-ScheduledTask AutoPilotCMClientInstall
}
}
'@
log-it -message "Creating C:\Temp\SCCM\AutoPilotCMClientInstall.ps1 script." -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"
Add-Content C:\Temp\SCCM\AutoPilotCMClientInstall.ps1 -Value $script
#Checks if SCCM is already installed. If it is, it will not create the scheduled task.
$isInstalled = gwmi win32_product | ? {$_.Name -eq "Configuration Manager Client"}
if($isInstalled -eq $null)
{
log-it -message "Creating Scheduled Task." -component "AP-SCCM-Install" -path "C:\Temp\" -logname "Company_AP.log"
$A = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-Ex Bypass -file C:\Temp\SCCM\AutoPilotCMClientInstall.ps1"
#$T = New-ScheduledTaskTrigger -AtLogOn
$T = @(
$(New-ScheduledTaskTrigger -AtLogOn),
$(New-ScheduledTaskTrigger -Once -At (get-date) -RepetitionInterval (New-TimeSpan -Minutes 1) )
)
$P = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$S = New-ScheduledTaskSettingsSet –AllowStartIfOnBatteries –DontStopIfGoingOnBatteries -DontStopOnIdleEnd
$D = New-ScheduledTask -Action $A -Principal $P -Trigger $T -Settings $S
Register-ScheduledTask AutoPilotCMClientInstall -InputObject $D
}
#Enables UAC visibility through MSRA / Quick Assist
Set-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -name PromptOnSecureDesktop -Value 0 -ErrorAction SilentlyContinue
#Detects if script was successful
$task = (Get-ScheduledTask AutoPilotCMClientInstall -ErrorAction SilentlyContinue).state
if ( ($task -eq "Ready") -or ($task -eq "Running") -or (test-path C:\Windows\CCM\CcmExec.exe) )
{
log-it -message "SCCM is either detected or the installation TS is enabled and will install it." -component "AP" -path "C:\Temp\" -logname "Company_AP.log"
}
else
{
log-it -message "Didn't detect task!" -component "AP" -path "C:\Temp\" -logname "Company_AP.log"
}
Script to get the current user's AD details.
Detect OOBE - Script to see if an AutoPilot device is in OOBE