-
Notifications
You must be signed in to change notification settings - Fork 0
jaredonair/W365
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
#Running this script is at your own risk
#Please provide the AzureAD licens group name in the parameters.
#This script only works with AzureAD Licens group Cloud-only.
#This only works with Windows 365 Enterprise edition.
#Parameters
#IF you dont have licens group for all Windows 365 Licens type, just leave them blank. But aware of the script will fail if you select a licens you dont have a licens group for.
param(
#2VCPU 4GB Ram
$W365_2vCPU_4GB_64GB = "AAD-LIC-W365ENT-2vCPU-4GB-64GBSSD",
$W365_2vCPU_4GB_128GB = "",
$W365_2vCPU_4GB_256GB = "",
#2VCPU 8GM Ram
$W365_2vCPU_8GB_128GB = "AAD-LIC-W365ENT-2vCPU-8GB-128GBSSD",
$W365_2vCPU_8GB_256GB = "",
#4VCPU 16GM Ram
$W365_4vCPU_16GB_128GB = "",
$W365_4vCPU_16GB_256GB = "",
$W365_4vCPU_16GB_512GB = "",
#8VCPU 32GM Ram
$W365_8vCPU_32GB_128GB = "",
$W365_8vCPU_32GB_256GB = "",
$W365_8vCPU_32GB_512GB = ""
)
#Function to check if MS.Graph module is installed and up-to-date
function invoke-graphmodule {
$graphavailable = (find-module -name microsoft.graph)
$vertemp = $graphavailable.version.ToString()
Write-Output "Latest version of Microsoft.Graph module is $vertemp" | out-host
foreach ($module in $modules){
write-host "Checking module - " $module
$graphcurrent = (get-installedmodule -name $module -ErrorAction SilentlyContinue)
if ($graphcurrent -eq $null) {
write-output "Module is not installed. Installing..." | out-host
try {
Install-Module -name $module -RequiredVersion 1.11.1 -Force -ErrorAction Stop
Import-Module -name $module -RequiredVersion 1.11.1 -force -ErrorAction Stop
}
catch {
write-output "Failed to install " $module | out-host
write-output $_.Exception.Message | out-host
Return 1
}
}
}
$graphcurrent = (get-installedmodule -name Microsoft.Graph.DeviceManagement.Functions)
$vertemp = $graphcurrent.Version.ToString()
write-output "Current installed version of Microsoft.Graph module is $vertemp" | out-host
if ($graphavailable.Version -gt $graphcurrent.Version) { write-host "There is an update to this module available." }
else
{ write-output "The installed Microsoft.Graph module is up to date." | out-host }
}
#Function to connect to the MS.Graph PowerShell Enterprise App
function connect-msgraph {
$tenant = get-mgcontext
if ($tenant.TenantId -eq $null) {
write-output "Not connected to MS Graph. Connecting..." | out-host
try {
Connect-MgGraph -Scopes $GraphAPIPermissions -ErrorAction Stop | Out-Null
}
catch {
write-output "Failed to connect to MS Graph" | out-host
write-output $_.Exception.Message | out-host
Return 1
}
}
$tenant = get-mgcontext
$text = "Tenant ID is " + $tenant.TenantId
Write-Output "Connected to Microsoft Graph" | out-host
Write-Output $text | out-host
}
#Function to set the profile to beta
function set-profile {
Write-Output "Setting profile as beta..." | Out-Host
Select-MgProfile -Name beta
}
$modules = @("Microsoft.Graph.authentication",
"Microsoft.Graph.Identity.DirectoryManagement",
"Microsoft.Graph.Users",
"Microsoft.Graph.Users.Actions",
"Microsoft.Graph.DeviceManagement.Actions",
"Microsoft.Graph.DeviceManagement.Administration",
"Microsoft.Graph.Groups",
"Microsoft.Graph.DeviceManagement.Functions"
)
$WarningPreference = 'SilentlyContinue'
[String]$GraphAPIPermissions = @("Directory.Read.All",
"CloudPC.ReadWrite.All",
"User.ReadWrite.All",
"GroupMember.ReadWrite.All",
"Organization.Read.All")
#Commands to load MS.Graph modules
if (invoke-graphmodule -eq 1) {
write-output "Invoking Graph failed. Exiting..." | out-host
Return 1
}
#Command to connect to MS.Graph PowerShell app
if (connect-msgraph -eq 1) {
write-output "Connecting to Graph failed. Exiting..." | out-host
Return 1
}
#Set Graph Profile
set-profile
function Show-Menu
{
param (
[string]$Title = 'Windows 365 Enterprise sizes'
)
Write-Host "Select the Size you want to resize to"
Write-Host ""
Write-Host "================ $Title ================"
Write-Host "1: Windows 365 Enterprise 2 vCPU, 4 GB, 128 GB"
Write-Host "2: Windows 365 Enterprise 2 vCPU, 4 GB, 256 GB"
Write-Host "3: Windows 365 Enterprise 2 vCPU, 8 GB, 128 GB"
Write-Host "4: Windows 365 Enterprise 2 vCPU, 8 GB, 256 GB"
Write-Host "5: Windows 365 Enterprise 4 vCPU, 16 GB, 128 GB"
Write-Host "6: Windows 365 Enterprise 4 vCPU, 16 GB, 256 GB"
Write-Host "7: Windows 365 Enterprise 4 vCPU, 16 GB, 512 GB"
Write-Host "8: Windows 365 Enterprise 8 vCPU, 32 GB, 128 GB"
Write-Host "9: Windows 365 Enterprise 8 vCPU, 32 GB, 256 GB"
Write-Host "10: Windows 365 Enterprise 8 vCPU, 32 GB, 512 GB"
Write-Host "Q: Press 'Q' to quit."
}
#Lookup UserPrincipalName in AzureAD
try {
$CloudPCName = Read-Host "Enter the Cloud PC Name you wish to resize"
$CloudPC = Get-MgDeviceManagementVirtualEndpointCloudPC | where-object {$_.ManagedDeviceName -eq $CloudPCName}
if(!($CloudPC)) {
Write-Host "Unable to find Cloud PC: $CloudPCName"
Write-Host "Ending script.."
break
}
#output information about selected Cloud PC
$Output = [PSCustomObject]@{
"Cloud PC Name" = "$($CloudPC.ManagedDeviceName)"
"Cloud PC Managed Device ID" = "$($CloudPC.ManagedDeviceId)"
"Cloud PC AAD Device ID" = "$($CloudPC.AadDeviceId)"
"UserPrincipalName" = "$($CloudPC.UserPrincipalName)"
"Current Cloud PC Size" = "$($CloudPC.ServicePlanName)"
}
$Output
#please select which size you wish to resize to.
show-menu
$selection = Read-Host "Please make a selection"
switch ($selection){
'1' {
$SKUName = "Windows 365 Enterprise 2 vCPU, 4 GB, 128 GB"
$NewLicensGroup = $W365_2vCPU_4GB_128GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'2' {
$SKUName = "Windows 365 Enterprise 2 vCPU, 4 GB, 256 GB"
$NewLicensGroup = $W365_2vCPU_4GB_256GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'3' {
$SKUName = "Windows 365 Enterprise 2 vCPU, 8 GB, 128 GB"
$NewLicensGroup = $W365_2vCPU_8GB_128GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'4' {
$SKUName = "Windows 365 Enterprise 2 vCPU, 8 GB, 256 GB"
$NewLicensGroup = $W365_2vCPU_8GB_256GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'5' {
$SKUName = "Windows 365 Enterprise 4 vCPU, 16 GB, 128 GB"
$NewLicensGroup = $W365_4vCPU_16GB_128GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'6' {
$SKUName = "Windows 365 Enterprise 4 vCPU, 16 GB, 256 GB"
$NewLicensGroup = $W365_4vCPU_16GB_256GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'7' {
$SKUName = "Windows 365 Enterprise 4 vCPU, 16 GB, 512 GB"
$NewLicensGroup = $W365_4vCPU_16GB_512GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resiz Cloud PC: $CloudPCName to: $SKUName"
}
'8' {
$SKUName = "Windows 365 Enterprise 8 vCPU, 32 GB, 128 GB"
$NewLicensGroup = $W365_8vCPU_32GB_128GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'9' {
$SKUName = "Windows 365 Enterprise 8 vCPU, 32 GB, 256 GB"
$NewLicensGroup = $W365_8vCPU_32GB_256GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'10'{
$SKUName = "Windows 365 Enterprise 8 vCPU, 32 GB, 512 GB"
$NewLicensGroup = $W365_8vCPU_32GB_512GB
Write-Host "Once the resize has begun there is no way back."
Write-Host "Are you sure you want to contiune resize Cloud PC: $CloudPCName to: $SKUName"
}
'q' {
Write-Host "You have selected quit"
Write-Host "Ending script"
$Endscript = $True
}
}
If ($Endscript){
#Ending script
$Endscript = @()
Break
}
$YesOrNo = Read-Host "Please enter your response (y/n)"
while("y","n" -notcontains $YesOrNo )
{
$YesOrNo = Read-Host "Please enter your response (y/n)"
}
If ($YesOrNo -eq "n") {
Write-Host "You have selected 'NO'"
Write-Host "Ending script"
Break
}
# Check if there is an available license to use
Write-Host "Checking if there is a $SKUName available..."
$SKUNameSplit = $SKUName -split ","
#CPU
$CPU = $SKUNameSplit[0]
$CPU = $CPU -split " "
$CPU = $CPU[3]
#RAM
$RAM = $SKUNameSplit[1]
$RAM = $RAM -split " "
$RAM = $RAM[1]
#Drive
$Drive = $SKUNameSplit[2]
$Drive = $Drive -split " "
$Drive = $Drive[1]
$SkuPartNumber = "CPC_E_$($CPU)C_$($RAM)GB_$($Drive)GB"
$GetSKU = Get-MgSubscribedSku | Where-Object {$_.SkuPartNumber -eq $SkuPartNumber}
if (!$GetSKU){
Write-Host "Unable to find License $SKUName in Azure AD. Please check if you have the license available."
Write-Host "Ending Script."
Break
}
$UsedSKU = $GetSKU.ConsumedUnits
$TotalSKU = $GetSKU.PrepaidUnits.Enabled
if ($UsedSKU -ge $TotalSKU){
Write-Host "There are not enough licenses available."
Write-Host "Please go and add more licenses and run the script again."
Write-Host "Ending Script."
Break
}
#Get Service Plan SKU for new Licens
$GetSKU.ServicePlans | where {$_.ServicePlanName -match "CPC_"}
$NewServiceplan = $GetSKU.ServicePlans | where {$_.ServicePlanName -match "CPC_"}
$NewServicePlanID = $NewServiceplan.ServicePlanId
#Checking user licens group
$UserDetails = Get-MgUser -Filter "userPrincipalName eq '$($CloudPC.UserPrincipalName)'"
$CurrentSKUPartNumber = $CloudPC.ServicePlanName
$CurrentSKUPartNumber = $CurrentSKUPartNumber -split " "
$CurrentSKUPartNumber = $CurrentSKUPartNumber[3] -split "/"
#CPU
$CurrentCPU = $CurrentSKUPartNumber[0]
$CurrentCPU = $CurrentCPU -split "v"
$CurrentCPU = $CurrentCPU[0]
#RAM
$CurrentRAM = $CurrentSKUPartNumber[1]
$CurrentRAM = $CurrentRAM -split "G"
$CurrentRAM = $CurrentRAM[0]
#Drive
$CurrentDrive = $CurrentSKUPartNumber[2]
$CurrentDrive = $CurrentDrive -split "G"
$CurrentDrive = $CurrentDrive[0]
$CurrentSkuPartNumber = "CPC_E_$($CurrentCPU)C_$($CurrentRAM)GB_$($CurrentDrive)GB"
$GetCurrentSKU = Get-MgUserLicenseDetail -UserId $UserDetails.Id | Where-Object {$_.SkuPartNumber -eq $CurrentSkuPartNumber}
if ($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_2C_4GB_64GB'){
$CurrentLicensGroup = $W365_2vCPU_4GB_64GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_2C_4GB_128GB'){
$CurrentLicensGroup = $W365_2vCPU_4GB_128GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_2C_4GB_256GB'){
$CurrentLicensGroup = $W365_2vCPU_4GB_256GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_2C_8GB_128GB'){
$CurrentLicensGroup = $W365_2vCPU_8GB_128GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_2C_8GB_256GB'){
$CurrentLicensGroup = $W365_2vCPU_8GB_256GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_4C_16GB_128GB'){
$CurrentLicensGroup = $W365_4vCPU_16GB_128GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_4C_16GB_256GB'){
$CurrentLicensGroup = $W365_4vCPU_16GB_256GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_4C_16GB_512GB'){
$CurrentLicensGroup = $W365_4vCPU_16GB_512GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_8C_32GB_128GB'){
$CurrentLicensGroup = $W365_8vCPU_32GB_128GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_8C_32GB_256GB'){
$CurrentLicensGroup = $W365_8vCPU_32GB_256GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq 'CPC_E_8C_32GB_512GB'){
$CurrentLicensGroup = $W365_8vCPU_32GB_512GB
}
elseif($GetCurrentSKU.SkuPartNumber -eq $null){
Write-Host "Not able to locate Windows 365 Enterprise sku assigned to the user"
Write-Host "Go check the MEM portal for troubleshooting"
Write-Host "Ending script"
break
}
#Check licensgroup membership
$GroupDetials = Get-MgGroup -Filter "DisplayName eq '$CurrentLicensGroup'"
$CheckCurrentlicensGroupMemberShip = Get-MgGroupMember -GroupId $GroupDetials.Id -All | Where-Object {$_.Id -eq $UserDetails.Id}
if (!($CheckCurrentlicensGroupMemberShip)) {
Write-Host "Unable to find User in licens group $CurrentLicensGroup"
Write-Host "ending script"
break
}
#Removing user from Licens Group
try {
Write-Host "Removeing user from $CurrentLicensGroup"
Invoke-GraphRequest -Method 'Delete' -Uri https://graph.microsoft.com/v1.0/groups/$($GroupDetials.Id)/members/$($UserDetails.Id)/`$ref
}
catch {
write-output $_.Exception.Message | out-host
}
#Assing user licens directly
try {
Write-Host "Assiging current licens directly to user: $($CloudPC.UserPrincipalName)"
Set-MgUserLicense -UserId $UserDetails.Id -AddLicenses @{SkuId = $GetCurrentSKU.SkuId} -RemoveLicenses @() | out-null
}
catch{
write-output $_.Exception.Message | out-host
}
#Resize Cloud PC
try{
#initiate Resize to new sku
write-host "starting resize of Cloud PC: $($CloudPC.ManagedDeviceName)"
Start-Sleep -Seconds 45
$params = @{
TargetServicePlanId = $NewServicePlanID
}
Resize-MgDeviceManagementManagedDeviceCloudPc -ManagedDeviceId $cloudpc.ManagedDeviceId -BodyParameter $params
#Get Cloud PC Resize information
$Resizeprogress = Get-MgDeviceManagementVirtualEndpointCloudPC | where-object {$_.ManagedDeviceName -eq $CloudPCName}
#Timer variables
$Timer = [Diagnostics.Stopwatch]::StartNew()
$TimerRetryInterval = "30"
$Timerout = "900"
#Check if Resize has started
#Check resize progress
While (($Timer.Elapsed.TotalSeconds -lt $Timerout) -and (-not ($Resizeprogress.Status -like "resizing"))) {
Start-Sleep -Seconds $TimerRetryInterval
$TotalSecs = [math]::Round($Timer.Elapsed.TotalSeconds, 0)
Write-Output "Resizeing of Cloud PC: $($CloudPC.ManagedDeviceName) is still in progress of starting. Checking again in $TimerRetryInterval seconds"
$Resizeprogress = Get-MgDeviceManagementVirtualEndpointCloudPC | where-object {$_.ManagedDeviceName -eq $CloudPCName}
}
$Timer.Stop()
If ($Timer.Elapsed.TotalSeconds -gt $Timerout) {
Write-host "Cloud PC: $($CloudPC.ManagedDeviceName) did not start the resizeing with the timeout time."
Write-host "Login to the MEM portal to start troubleshooting"
Write-host "Ending script"
exit
}
#Check resize progress
While (($Timer.Elapsed.TotalSeconds -lt $Timerout) -and (-not ($Resizeprogress.Status -like "provisioned"))) {
Start-Sleep -Seconds $TimerRetryInterval
$TotalSecs = [math]::Round($Timer.Elapsed.TotalSeconds, 0)
Write-Output "Reize of Cloud PC: $($CloudPC.ManagedDeviceName) has started but is not done. Checking again in $TimerRetryInterval seconds"
$Resizeprogress = Get-MgDeviceManagementVirtualEndpointCloudPC | where-object {$_.ManagedDeviceName -eq $CloudPCName}
}
$Timer.Stop()
If ($Timer.Elapsed.TotalSeconds -gt $Timerout) {
Write-host "Cloud PC: $($CloudPC.ManagedDeviceName) did not finish resizeing within the given time."
Write-host "Login to the MEM portal to start troubleshooting"
Write-host "Ending script"
exit
}
}
catch{
write-output $_.Exception.Message | out-host
break
}
#Remove Direct licens from user
try {
Write-Host "Removing direct licens: '$SKUName' from user: $($CloudPC.UserPrincipalName)"
$NewLicenseSKU = Get-MgSubscribedSku | Where {$_.SkuPartNumber -eq $SkuPartNumber}
Set-MgUserLicense -UserId $UserDetails.Id -AddLicenses @() -RemoveLicenses @($NewLicenseSKU.SkuId) | Out-Null
}
catch {
write-output $_.Exception.Message | out-host
break
}
#Add user to Licens group
try {
$NewAzureADLicensGroupName = Get-MgGroup -Filter "displayname eq '$NewLicensGroup'"
new-MgGroupMember -GroupId $NewAzureADLicensGroupName.Id -DirectoryObjectId $UserDetails.Id
Write-Host "User: $($CloudPC.UserPrincipalName) Has been added to the new licens group: $NewLicensGroup"
}
catch {
write-output $_.Exception.Message | out-host
break
}
Write-Host "Resize of Cloud PC: $($CloudPC.ManagedDeviceName) is now done,"
Write-Host "It will take a few minutes before you can sign in."
Write-Host "Remember to 'Refresh' the overview of availalbe Cloud PC in the webportal or Remote Desktop Client"
Write-Host "Ending script."
}
catch {
write-output $_.Exception.Message | out-host
}
About
No description, website, or topics provided.
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published