And the script for you to test it in your own test environment, don't go with it in production before testing :) # Specify the Delivery Controller Add-PSSnapin Citrix* $AdminAddress = "ddc04.testlab.com:80" # Path to the .txt file containing Hypervisor connection names $HypervisorFilePath = "C:\Temp\HypervisorConnections.txt" # Read the Hypervisor connection names from the file if (Test-Path $HypervisorFilePath) { $HypervisorConnectionNames = Get-Content -Path $HypervisorFilePath if ($HypervisorConnectionNames.Count -eq 0) { Write-Host "The file is empty. Please provide valid Hypervisor connection names." -ForegroundColor Red return } } else { Write-Host "File not found: $HypervisorFilePath. Please provide a valid path." -ForegroundColor Red return } # Function to process each Hypervisor connection function Message_and_MM { param ( [string]$HypervisorConnectionName )
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan # VMs in the pool $vms = Get-BrokerMachine -AdminAddress $AdminAddress | Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } | Select-Object -ExpandProperty Machinename # The message to send $messageText = "Please save your work. The system will undergo maintenance soon." $messageTitle = "System Maintenance Notice" $messageStyle = "Information" # Loop through each VM and send message to logged-in users foreach ($vm in $vms) { Write-Host "Processing VM: $vm" -ForegroundColor Yellow try { # Get active sessions on the machine $sessions = Get-BrokerSession -AdminAddress $adminAddress -Filter {MachineName -eq $vm} if ($sessions.Count -gt 0) { $userNames = $sessions | Select-Object -ExpandProperty UserName Write-Host "Sending message to users: $($userNames -join ', ')" -ForegroundColor Yellow # Send the message to all active sessions by user names $sessionUids = $sessions | Select-Object -ExpandProperty Uid Send-BrokerSessionMessage -AdminAddress $adminAddress -InputObject $sessionUids -LoggingId $operation.Id -MessageStyle $messageStyle -Text $messageText -Title $messageTitle Write-Host "Message sent successfully to users on VM: $vm" -ForegroundColor Green } else { Write-Host "No active users found on VM: $vm" -ForegroundColor Cyan }
} catch { Write-Host "Failed to send message to users on VM: $vm. Error: $_" -ForegroundColor Red }
} # Loop through each VM name an set Maintenance Mode foreach ($VM in $vms) { try { # Set maintenance mode on the VM Set-BrokerMachineMaintenanceMode -AdminAddress $adminAddress -InputObject $VM $True # Log success message in Powershell Write-Host "Maintenance mode enabled for $VM" } catch { # Log any errors Write-Host "An error occurred while processing $VM $_" } } } # First loop to process each Hypervisor connection foreach ($HypervisorConnectionName in $HypervisorConnectionNames) { Message_and_MM -HypervisorConnectionName $HypervisorConnectionName } Write-Host "Messages sent and MM is on" -ForegroundColor Green # Total duration in minutes $TotalMinutes = 0.4 # Convert minutes to seconds $TotalSeconds = $TotalMinutes * 60 # Loop through each second and update the progress bar for ($i = 1; $i -le $TotalSeconds; $i++) { # Calculate the percentage completed $PercentComplete = ($i / $TotalSeconds) * 100 # Calculate elapsed minutes and seconds $ElapsedMinutes = [math]::Floor($i / 60) $ElapsedSeconds = $i % 60 # Write the progress bar Write-Progress -Activity "Waiting for $TotalMinutes minutes..." ` -Status "Elapsed Time: $ElapsedMinutes minutes and $ElapsedSeconds seconds" ` -PercentComplete $PercentComplete # Sleep for 1 second Start-Sleep -Seconds 1 } Write-Host "Done!" -ForegroundColor Green function Log_off_and_PowerOff { param ( [string]$HypervisorConnectionName )
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan # VMs in the pool $vms = Get-BrokerMachine -AdminAddress $AdminAddress | Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } | Select-Object -ExpandProperty Machinename # Loop through each VM and log off users foreach ($vm in $vms) { Write-Host "Processing VM: $vm" -ForegroundColor Yellow try { # Get active sessions on the machine (omit MaxRecordCount for all sessions) $sessions = Get-BrokerSession -AdminAddress $adminAddress -Filter {MachineName -eq $vm} if ($sessions.Count -gt 0) { # Log off each user session foreach ($session in $sessions) { $userName = $session.UserName # Get the username Write-Host "Logging off user: $userName" -ForegroundColor Yellow Stop-BrokerSession -AdminAddress $adminAddress -InputObject $session -LoggingId $operation.Id } Write-Host "Successfully logged off users from VM: $vm" -ForegroundColor Green
} else { Write-Host "No active users found on VM: $vm" -ForegroundColor Cyan } } catch { # Log any errors Write-Host "An error occurred while processing VM: $vm - $_" -ForegroundColor Red } } # Loop through each VM name and Power Off the VM foreach ($VM in $vms) { try { # Power Off VM New-BrokerHostingPowerAction -Action "Shutdown" -AdminAddress $adminAddress -MachineName $vm # Log success message in Powershell Write-Host "Powered off $VM" } catch { # Log any errors Write-Host "An error occurred while processing $VM $_" } } } # Second loop to process each Hypervisor connection foreach ($HypervisorConnectionName in $HypervisorConnectionNames) { Log_off_and_PowerOff -HypervisorConnectionName $HypervisorConnectionName } Write-Host "Users loged off and VMs powered off" -ForegroundColor Green # Request user to confir Write-Host "The next part will Power on and disable maintenance mode." -ForegroundColor Red Write-Host "Do you want to continue? Type 'yes' to proceed or anything else to exit." -ForegroundColor Yellow $confirmation = Read-Host "Please confirm" if ($confirmation -eq "yes") { Write-Host "You chose to continue. Proceeding with the script..." -ForegroundColor Green } else { Write-Host "You chose not to continue. Exiting the script." -ForegroundColor Red exit } function PowerOn_and_Disable_MM { param ( [string]$HypervisorConnectionName )
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan # VMs in the pool $vms = Get-BrokerMachine -AdminAddress $AdminAddress | Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } | Select-Object -ExpandProperty Machinename # Loop through each VM name and Power On the VM foreach ($VM in $vms) { try { # Power On VM New-BrokerHostingPowerAction -Action "TurnOn" -AdminAddress $adminAddress -MachineName $vm # Log success message in Powershell Write-Host "Powered on $VM" } catch { # Log any errors Write-Host "An error occurred while processing $VM $_" } } # Loop through each VM name and disable Maintenance Mode foreach ($VM in $vms) { try { # Set maintenance mode off the VM Set-BrokerMachineMaintenanceMode -AdminAddress $adminAddress -InputObject $VM $False # Log success message in Powershell Write-Host "Maintenance mode enabled for $VM" } catch { # Log any errors Write-Host "An error occurred while processing $VM $_" } } } # Third loop to process each Hypervisor connection foreach ($HypervisorConnectionName in $HypervisorConnectionNames) { PowerOn_and_Disable_MM -HypervisorConnectionName $HypervisorConnectionName } Write-Host "VMs Powered On and MM Disabled" -ForegroundColor Green
If my videos have been helpful to you, please consider supporting my work by buying me a coffee on Ko-fi! ko-fi.com/adrianioja
Great video 📹
And the script for you to test it in your own test environment, don't go with it in production before testing :)
# Specify the Delivery Controller
Add-PSSnapin Citrix*
$AdminAddress = "ddc04.testlab.com:80"
# Path to the .txt file containing Hypervisor connection names
$HypervisorFilePath = "C:\Temp\HypervisorConnections.txt"
# Read the Hypervisor connection names from the file
if (Test-Path $HypervisorFilePath) {
$HypervisorConnectionNames = Get-Content -Path $HypervisorFilePath
if ($HypervisorConnectionNames.Count -eq 0) {
Write-Host "The file is empty. Please provide valid Hypervisor connection names." -ForegroundColor Red
return
}
} else {
Write-Host "File not found: $HypervisorFilePath. Please provide a valid path." -ForegroundColor Red
return
}
# Function to process each Hypervisor connection
function Message_and_MM {
param (
[string]$HypervisorConnectionName
)
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan
# VMs in the pool
$vms = Get-BrokerMachine -AdminAddress $AdminAddress |
Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } |
Select-Object -ExpandProperty Machinename
# The message to send
$messageText = "Please save your work. The system will undergo maintenance soon."
$messageTitle = "System Maintenance Notice"
$messageStyle = "Information"
# Loop through each VM and send message to logged-in users
foreach ($vm in $vms) {
Write-Host "Processing VM: $vm" -ForegroundColor Yellow
try {
# Get active sessions on the machine
$sessions = Get-BrokerSession -AdminAddress $adminAddress -Filter {MachineName -eq $vm}
if ($sessions.Count -gt 0) {
$userNames = $sessions | Select-Object -ExpandProperty UserName
Write-Host "Sending message to users: $($userNames -join ', ')" -ForegroundColor Yellow
# Send the message to all active sessions by user names
$sessionUids = $sessions | Select-Object -ExpandProperty Uid
Send-BrokerSessionMessage -AdminAddress $adminAddress -InputObject $sessionUids -LoggingId $operation.Id -MessageStyle $messageStyle -Text $messageText -Title $messageTitle
Write-Host "Message sent successfully to users on VM: $vm" -ForegroundColor Green
} else {
Write-Host "No active users found on VM: $vm" -ForegroundColor Cyan
}
} catch {
Write-Host "Failed to send message to users on VM: $vm. Error: $_" -ForegroundColor Red
}
}
# Loop through each VM name an set Maintenance Mode
foreach ($VM in $vms) {
try {
# Set maintenance mode on the VM
Set-BrokerMachineMaintenanceMode -AdminAddress $adminAddress -InputObject $VM $True
# Log success message in Powershell
Write-Host "Maintenance mode enabled for $VM"
}
catch {
# Log any errors
Write-Host "An error occurred while processing $VM $_"
}
}
}
# First loop to process each Hypervisor connection
foreach ($HypervisorConnectionName in $HypervisorConnectionNames) {
Message_and_MM -HypervisorConnectionName $HypervisorConnectionName
}
Write-Host "Messages sent and MM is on" -ForegroundColor Green
# Total duration in minutes
$TotalMinutes = 0.4
# Convert minutes to seconds
$TotalSeconds = $TotalMinutes * 60
# Loop through each second and update the progress bar
for ($i = 1; $i -le $TotalSeconds; $i++) {
# Calculate the percentage completed
$PercentComplete = ($i / $TotalSeconds) * 100
# Calculate elapsed minutes and seconds
$ElapsedMinutes = [math]::Floor($i / 60)
$ElapsedSeconds = $i % 60
# Write the progress bar
Write-Progress -Activity "Waiting for $TotalMinutes minutes..." `
-Status "Elapsed Time: $ElapsedMinutes minutes and $ElapsedSeconds seconds" `
-PercentComplete $PercentComplete
# Sleep for 1 second
Start-Sleep -Seconds 1
}
Write-Host "Done!" -ForegroundColor Green
function Log_off_and_PowerOff {
param (
[string]$HypervisorConnectionName
)
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan
# VMs in the pool
$vms = Get-BrokerMachine -AdminAddress $AdminAddress |
Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } |
Select-Object -ExpandProperty Machinename
# Loop through each VM and log off users
foreach ($vm in $vms) {
Write-Host "Processing VM: $vm" -ForegroundColor Yellow
try {
# Get active sessions on the machine (omit MaxRecordCount for all sessions)
$sessions = Get-BrokerSession -AdminAddress $adminAddress -Filter {MachineName -eq $vm}
if ($sessions.Count -gt 0) {
# Log off each user session
foreach ($session in $sessions) {
$userName = $session.UserName # Get the username
Write-Host "Logging off user: $userName" -ForegroundColor Yellow
Stop-BrokerSession -AdminAddress $adminAddress -InputObject $session -LoggingId $operation.Id
}
Write-Host "Successfully logged off users from VM: $vm" -ForegroundColor Green
} else {
Write-Host "No active users found on VM: $vm" -ForegroundColor Cyan
}
} catch {
# Log any errors
Write-Host "An error occurred while processing VM: $vm - $_" -ForegroundColor Red
}
}
# Loop through each VM name and Power Off the VM
foreach ($VM in $vms) {
try {
# Power Off VM
New-BrokerHostingPowerAction -Action "Shutdown" -AdminAddress $adminAddress -MachineName $vm
# Log success message in Powershell
Write-Host "Powered off $VM"
}
catch {
# Log any errors
Write-Host "An error occurred while processing $VM $_"
}
}
}
# Second loop to process each Hypervisor connection
foreach ($HypervisorConnectionName in $HypervisorConnectionNames) {
Log_off_and_PowerOff -HypervisorConnectionName $HypervisorConnectionName
}
Write-Host "Users loged off and VMs powered off" -ForegroundColor Green
# Request user to confir
Write-Host "The next part will Power on and disable maintenance mode." -ForegroundColor Red
Write-Host "Do you want to continue? Type 'yes' to proceed or anything else to exit." -ForegroundColor Yellow
$confirmation = Read-Host "Please confirm"
if ($confirmation -eq "yes") {
Write-Host "You chose to continue. Proceeding with the script..." -ForegroundColor Green
} else {
Write-Host "You chose not to continue. Exiting the script." -ForegroundColor Red
exit
}
function PowerOn_and_Disable_MM {
param (
[string]$HypervisorConnectionName
)
Write-Host "Processing Hypervisor Connection: $HypervisorConnectionName" -ForegroundColor Cyan
# VMs in the pool
$vms = Get-BrokerMachine -AdminAddress $AdminAddress |
Where-Object { $_.HypervisorConnectionName -eq $HypervisorConnectionName } |
Select-Object -ExpandProperty Machinename
# Loop through each VM name and Power On the VM
foreach ($VM in $vms) {
try {
# Power On VM
New-BrokerHostingPowerAction -Action "TurnOn" -AdminAddress $adminAddress -MachineName $vm
# Log success message in Powershell
Write-Host "Powered on $VM"
}
catch {
# Log any errors
Write-Host "An error occurred while processing $VM $_"
}
}
# Loop through each VM name and disable Maintenance Mode
foreach ($VM in $vms) {
try {
# Set maintenance mode off the VM
Set-BrokerMachineMaintenanceMode -AdminAddress $adminAddress -InputObject $VM $False
# Log success message in Powershell
Write-Host "Maintenance mode enabled for $VM"
}
catch {
# Log any errors
Write-Host "An error occurred while processing $VM $_"
}
}
}
# Third loop to process each Hypervisor connection
foreach ($HypervisorConnectionName in $HypervisorConnectionNames) {
PowerOn_and_Disable_MM -HypervisorConnectionName $HypervisorConnectionName
}
Write-Host "VMs Powered On and MM Disabled" -ForegroundColor Green