Created
September 5, 2024 18:17
-
-
Save SMSAgentSoftware/864e44b960a30ad0db35a61730dd6585 to your computer and use it in GitHub Desktop.
Azure automation runbook to bulk restart all Windows 365 Cloud PCs and Microsoft Dev Boxes.
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
################################################################################################################### | |
## Azure Automation Runbook Script to initiate a restart of all Cloud PCs and Microsoft Dev Boxes ## | |
################################################################################################################### | |
# Requires PS7+ | |
# Requires Az.Accounts module | |
# Requires Az.DevCenter module | |
# If using Runtime environments, ensure an up-to-date Az module is installed in the environment | |
# For Dev Boxes, requires "DevCenter Project Admin" role assignment on the Dev Center project for the Automation Account Managed Identity, or... | |
# a custom role with at least the following permissions: | |
# "Microsoft.DevCenter/projects/users/devboxes/adminStart/action" | |
# "Microsoft.DevCenter/projects/users/devboxes/adminStop/action" | |
# "Microsoft.DevCenter/projects/users/devboxes/adminRead/action" | |
# "Microsoft.DevCenter/projects/users/devboxes/adminWrite/action" | |
# "Microsoft.DevCenter/devcenters/read" | |
# "Microsoft.DevCenter/projects/read" | |
# For Cloud PCs, requires "CloudPC Administrator" role assignment in Intune for the Automation Account Managed Identity, or... | |
# a custom role containing the "Reboot" action on the "CloudPC" resource type, or... | |
# the following Microsoft.Graph permissions: | |
# "CloudPC.ReadWrite.All" | |
#region ----------------------------------------------- Parameters ------------------------------------------------ | |
# A list of Dev Center endpoints to query for Dev Boxes | |
$DevBoxEndpoints = @("https://a84894e7-1234-5678-9876-320d0334b3zz-mydevcenter.devcenter.azure.com/") | |
$ProgressPreference = 'SilentlyContinue' | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Functions ------------------------------------------------- | |
# Function to invoke a web request with basic error handling | |
Function script:Invoke-WebRequestPro { | |
Param ($URL,$Headers,$Method,$Body,$ContentType) | |
If ($Method -in "GET","DELETE") | |
{ | |
try { | |
$WebRequest = Invoke-WebRequest -Uri $URL -Method $Method -Headers $Headers | |
} | |
catch { | |
$WebRequest = $_.Exception.Response | |
} | |
} | |
elseif ($Method -eq "POST") | |
{ | |
try { | |
$WebRequest = Invoke-WebRequest -Uri $URL -Method $Method -Headers $Headers -Body $Body -ContentType $ContentType | |
} | |
catch { | |
$WebRequest = $_.Exception.Response | |
} | |
} | |
Return $WebRequest | |
} | |
# Function to get all Cloud PCs | |
Function Get-CloudPCs { | |
$URL = "https://graph.microsoft.com/v1.0/deviceManagement/virtualEndpoint/cloudPCs" | |
$headers = @{'Authorization'="Bearer " + $GraphToken} | |
$GraphRequest = Invoke-WebRequestPro -URL $URL -Headers $headers -Method GET | |
return $GraphRequest | |
} | |
# Function to reboot a Cloud PC | |
Function Restart-CloudPC { | |
Param ($CloudPCId) | |
$URL = "https://graph.microsoft.com/v1.0/deviceManagement/virtualEndpoint/cloudPCs/$CloudPCId/reboot" | |
$headers = @{'Authorization'="Bearer " + $GraphToken} | |
$GraphRequest = Invoke-WebRequestPro -URL $URL -Headers $headers -Method POST | |
return $GraphRequest | |
} | |
# Function to get all DevBoxes | |
Function Get-DevBoxes { | |
Param($DevBoxEndpoint) | |
$devBoxes = Get-AzDevCenterUserDevBox -Endpoint $DevBoxEndpoint | |
return $devBoxes | |
} | |
# Function to reboot a DevBox | |
function Restart-DevBox { | |
Param($DevBox,$DexBoxEndpoint) | |
$devBoxInput = @{"DevBoxName" = $DevBox.Name; "UserId" = $DevBox.User; "ProjectName" = $DevBox.ProjectName } | |
$request = Restart-AzDevCenterUserDevBox -InputObject $devBoxInput -Endpoint $DevBoxEndpoint -NoWait -ErrorVariable requestError -ErrorAction SilentlyContinue | |
If ($requestError) | |
{ | |
return $requestError | |
} | |
else | |
{ | |
return $request | |
} | |
} | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Authentication -------------------------------------------- | |
$null = Connect-AzAccount -Identity | |
$script:GraphToken = (Get-AzAccessToken -ResourceTypeName MSGraph -AsSecureString).Token | ConvertFrom-SecureString -AsPlainText | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Get Cloud PCs --------------------------------------------- | |
$CloudPCs = Get-CloudPCs | |
If ($CloudPCs.StatusCode -eq 200) | |
{ | |
$CloudPCs = ($CloudPCs.Content | ConvertFrom-Json).value | where {!($_.servicePlanName -like "Microsoft Dev Box*")} | |
} | |
Else | |
{ | |
throw "Error getting Cloud PCs: $($CloudPCs.StatusCode)" | |
} | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Restart Cloud PCs ----------------------------------------- | |
If ($CloudPCs.Count -ge 1) | |
{ | |
Write-Output "Restarting $($CloudPCs.Count) Cloud PCs" | |
foreach ($CloudPC in $CloudPCs) | |
{ | |
$Status = "Restarting $($CloudPC.displayName): " | |
$Reboot = Restart-CloudPC -CloudPCId $CloudPC.id | |
if ($Reboot.StatusCode -eq 204) | |
{ | |
$Status += "Successfully requested" | |
Write-Output $Status | |
} | |
else | |
{ | |
Write-Error "Error restarting $($CloudPC.displayName): $($Reboot.StatusDescription)" | |
} | |
} | |
} | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Get Dev Boxes --------------------------------------------- | |
$DevBoxes = [System.Collections.Generic.List[object]]::new() | |
foreach ($DevBoxEndpoint in $DevBoxEndpoints) | |
{ | |
[array]$Results = Get-DevBoxes -DevBoxEndpoint $DevBoxEndpoint | |
foreach ($Result in $Results) | |
{ | |
$DevBoxes.Add($Result) | |
} | |
} | |
If (!($DevBoxes.Count -ge 1)) | |
{ | |
Write-Information "No DevBoxes found" | |
} | |
#endregion -------------------------------------------------------------------------------------------------------- | |
#region ----------------------------------------------- Restart Dev Boxes ----------------------------------------- | |
If ($DevBoxes.Count -ge 1) | |
{ | |
Write-Output "Restarting $($DevBoxes.Count) Dev Boxes" | |
foreach ($DevBox in $DevBoxes) | |
{ | |
$Status = "Restarting $($DevBox.Name): " | |
$Reboot = Restart-DevBox -DevBox $DevBox | |
if ($null -eq $Reboot.target) | |
{ | |
Write-Error "Error restarting $($DevBox.Name): $Reboot" | |
} | |
else | |
{ | |
$Status += "Successfully requested" | |
Write-Output $Status | |
} | |
} | |
} | |
#endregion -------------------------------------------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment