WVD Send Message to User Session

This WVD Script Based Action allows you to send a message to a user, logged on to a WVD Desktop or RemoteApp session._x000A_README: https://support.controlup.com/hc/en-us/articles/360011378518

Version: 1.4.4
Created: 2020-06-13
Modified: 2020-07-22
Creator: Esther Barthel, MSc
Downloads: 5
Tags:
The Script Copy Script Copied to clipboard

<# .SYNOPSIS Send a Message to a WVD 2020 Spring Release User Session. .DESCRIPTION Send a Message to a WVD 2020 Spring Release User Session, using the new Az.Desktopvirtualization PowerShell Module and WVD ARM Architecture (2020 Spring Release). .EXAMPLE Invoke-WVDSendMessageToUserSession .CONTEXT Windows Virtual Desktops .MODIFICATION_HISTORY Esther Barthel, MSc - 13/06/20 - Original code Esther Barthel, MSc - 13/06/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2) .LINK https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-clixml?view=powershell-7 .COMPONENT Set-AzSPCredentials - The required Azure Service Principal (Subcription level) and tenantID information need to be securely stored in a Credentials File. The Set-AzSPCredentials Script Action will ensure the file is created according to ControlUp standards Az.Desktopvirtualization PowerShell Module - The Az.Desktopvirtualization PowerShell Module must be installed on the machine running this Script Action .NOTES Version: 0.1 Author: Esther Barthel, MSc Creation Date: 2020-06-13 Updated: 2020-06-13 Standardized the function, based on the ControlUp Standards (v0.2) Purpose: Script Action, created for ControlUp WVD Monitoring Copyright (c) cognition IT. All rights reserved. #>
[CmdletBinding()]
Param
(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the User of an active WVD Session’
)]
[string] $User,

[Parameter(
Position=1,
Mandatory=$true,
HelpMessage=’Enter the message body’
)]
[string] $Message
)

# dot sourcing WVD Functions
[string]$mainformXAML = @’



{
Set-Variable -Name “WPF$($_.Name)” -Value $Form.FindName($_.Name) -Scope Global
}
}
else
{
Throw “Failed to convert input XAML to WPF XML”
}

$form
}

function Get-AzSPStoredCredentials {
<# .SYNOPSIS Retrieve the Azure Service Principal Stored Credentials. .DESCRIPTION Retrieve the Azure Service Principal Stored Credentials from a stored credentials file. .EXAMPLE Get-AzSPStoredCredentials .CONTEXT Azure .MODIFICATION_HISTORY Esther Barthel, MSc - 03/03/20 - Original code Esther Barthel, MSc - 03/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2) .COMPONENT Import-Clixml - https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/import-clixml?view=powershell-5.1 .NOTES Version: 0.1 Author: Esther Barthel, MSc Creation Date: 2020-03-03 Updated: 2020-03-03 Standardized the function, based on the ControlUp Standards (v0.2) Updated: 2020-05-08 Created a separate Azure Credentials function to support ARM architecture and Az PowerShell Module scripted actions Purpose: Script Action, created for ControlUp WVD Monitoring Copyright (c) cognition IT. All rights reserved. #>
[CmdletBinding()]
Param()

#region function settings
# Stored Credentials XML file
$System = “AZ”
$strAzSPCredFolder = “$([environment]::GetFolderPath(‘CommonApplicationData’))ControlUpScriptSupport”
$AzSPCredentials = $null
#endregion

Write-Verbose “”
Write-Verbose “—————————– ”
Write-Verbose “| Get Azure SP Credentials: | ”
Write-Verbose “—————————– ”
Write-Verbose “”

If (Test-Path -Path “$($strAzSPCredFolder)$($env:USERNAME)_$($System)_Cred.xml”)
{
try
{
$AzSPCredentials = Import-Clixml -Path “$strAzSPCredFolder$($env:USERNAME)_$($System)_Cred.xml”
}
catch
{
Write-Error (“The required PSCredential object could not be loaded. ” + $_)
}
}
Else
{
Write-Error “The Azure Service Principal Credentials file stored for this user ($($env:USERNAME)) cannot be found. `nCreate the file with the Set-AzSPCredentials script action (prerequisite).”
Exit
}
return $AzSPCredentials
}

function Set-AzSPStoredCredentials {
<# .SYNOPSIS Store the Azure Service Principal Credentials. .DESCRIPTION Store the Azure Service Principal Credentials to an encrypted stored credentials file. .EXAMPLE Set-AzSPStoredCredentials .CONTEXT Azure .MODIFICATION_HISTORY Esther Barthel, MSc - 22/03/20 - Original code Esther Barthel, MSc - 22/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2) .COMPONENT Export-Clixml - https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-clixml?view=powershell-5.1 .NOTES Version: 0.1 Author: Esther Barthel, MSc Creation Date: 2020-03-22 Updated: 2020-03-22 Standardized the function, based on the ControlUp Standards (v0.2) Updated: 2020-05-08 Created a separate Azure Credentials function to support ARM architecture and Az PowerShell Module scripted actions Purpose: Script Action, created for ControlUp WVD Monitoring Copyright (c) cognition IT. All rights reserved. #>
[CmdletBinding()]
Param(
)

#region function settings
# Stored Credentials XML file
$System = “AZ”
$strAzSPCredFolder = “$([environment]::GetFolderPath(‘CommonApplicationData’))ControlUpScriptSupport”
$AzSPCredentials = $null
#endregion

Write-Verbose “”
Write-Verbose “——————————- ”
Write-Verbose “| Store Azure SP Credentials: | ”
Write-Verbose “——————————- ”
Write-Verbose “”

If (!(Test-Path -Path “$($strAzSPCredFolder)”))
{
New-Item -ItemType Directory -Path “$($strAzSPCredFolder)”
Write-Verbose “* AzSPCredentials: Path $($strAzSPCredFolder) created”
}
try
{
Add-Type -AssemblyName PresentationFramework
# Show the Form that will ask for the WVD Service Principal information (tenant ID, App ID, & App Secret)
if( $mainForm = Invoke-WVDSPCredentialsForm -inputXaml $mainformXAML )
{
$WPFbuttonOK.Add_Click( {
$_.Handled = $true
$mainForm.DialogResult = $true
$mainForm.Close()
})

$WPFbuttonCancel.Add_Click( {
$_.Handled = $true
$mainForm.DialogResult = $false
$mainForm.Close()
})

$null = $WPFtextboxTenantId.Focus()

if( $mainForm.ShowDialog() )
{
# Retrieve the form input (and check for errors)
# tenant ID
If ([string]::IsNullOrEmpty($($WPFtextboxTenantId.Text)))
{
Write-Error “The provided tenant ID is empty!”
Exit
}
else
{
$tenantID = $($WPFtextboxTenantId.Text)
}
# app ID
If ([string]::IsNullOrEmpty($($WPFtextboxAppId.Text)))
{
Write-Error “The provided app ID is empty!”
Exit
}
else
{
$appID = $($WPFtextboxAppId.Text)
}
# app Secret
If ([string]::IsNullOrEmpty($($WPFtextboxAppSecret.Password)))
{
Write-Error “The provided app Secret is empty!”
Exit
}
else
{
$appSecret = $($WPFtextboxAppSecret.Password)
}

$appSecret = $($WPFtextboxAppSecret.Password)

#Write-Output -InputObject “Tenant id is $($tenantID)”
#Write-Output -InputObject “App id is $($appID)”
#Write-Output -InputObject “App secret is $($appSecret)”
}
else
{
Write-Error “The required tenant ID, app ID and app Secret could not be retrieved from the form.”
Break
}
}
}
catch
{
Write-Error (“The required information could not be retrieved from the input form. ” + $_)
Exit
}
# Create the SP Credentials, so they are encrypted before being stored in the XML file
$secureAppSecret = ConvertTo-SecureString -String $appSecret -AsPlainText -Force
$spCreds = New-Object System.Management.Automation.PSCredential($appID, $secureAppSecret)

try
{
$hashAzSPCredentials = @{
‘tenantID’ = $tenantID
‘spCreds’ = $spCreds
}
$AzSPCredentials = Export-Clixml -Path “$strAzSPCredFolder$($env:USERNAME)_$($System)_Cred.xml” -InputObject $hashAzSPCredentials -Force
}
catch
{
Write-Error (“The required PSCredential object could not be exported. ” + $_)
Exit
}
Write-Verbose “* AzSPCredentials: Exported succesfully.”
return $hashAzSPCredentials
}

function Invoke-CheckInstallAndImportPSModulePrereq() {
<# .SYNOPSIS Check, Install (if allowed) and Import the given PSModule prerequisite. .DESCRIPTION Check, Install (if allowed) and Import the given PSModule prerequisite. .EXAMPLE Invoke-CheckInstallAndImportPSModulePrereq -ModuleName Az.DesktopVirtualization .CONTEXT Windows Virtual Desktops .MODIFICATION_HISTORY Esther Barthel, MSc - 23/03/20 - Original code Esther Barthel, MSc - 23/03/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2) .COMPONENT .NOTES Version: 1.0 Author: Esther Barthel, MSc Creation Date: 2020-03-23 Updated: 2020-03-23 Standardized the function, based on the ControlUp Standards (v0.2) Updated: 2020-07-22 Added an extra check to the Invoke-CheckInstallAndImportPSModuleRepreq function for the required NuGet packageprovider. If minimumversion 2.8.5.201 is not found it will install the NuGet PackageProvider Purpose: Script Action, created for ControlUp WVD Monitoring Copyright (c) cognition IT. All rights reserved. #>
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the PowerShell Module name that needs to be installed and imported’
)]
[ValidateNotNullOrEmpty()]
[string] $ModuleName
)

#region Check if the given PowerShell Module is installed (and if not, install it with elevated right)
# Check if the Module is loaded
If (-not((Get-Module -Name $($ModuleName)).Name))
# Module is not loaded
{
Write-Verbose “* CheckAndInstallPSModulePrereq: PowerShell Module $($ModuleName) is not loaded in current session”
# Check if the Module is installed
If (-not((Get-Module -Name $($ModuleName) -ListAvailable).Name))
# Module is not installed on the system
{
# Check if session is evelated
[bool]$isElevated = (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ($isElevated)
{
Write-Host (“The PowerShell Module $($ModuleName) is installed from an elevated session, Scope is set to AllUsers.”) -ForegroundColor Yellow
$psScope = “AllUsers”
}
else
{
Write-Warning “The PowerShell Module $($ModuleName) is NOT installed from an elevated session, Scope is set to CurrentUser.”
$psScope = “CurrentUser”
}

# Check the version of the installed NuGet Provider and install if the version is lower than 2.8.5.201 or the provider is missing
try
{
If (!(([string](Get-PackageProvider -Name NuGet -ListAvailable -ErrorAction SilentlyContinue).Version) -ge “2.8.5.201”))
{
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Scope $psScope -Force -Confirm:$false -WarningAction SilentlyContinue
}
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
Write-Verbose “* CheckAndInstallPSModulePrereq: The prerequired NuGet PackageProvider is installed.”

# Install the Module from the PSGallery
try
{
# Install the Module from the PSGallery
Write-Verbose “* CheckAndInstallPSModulePrereq: Installing the $($ModuleName) PowerShell Module from the PSGallery.”
PowerShellGetInstall-Module -Name $($ModuleName) -Confirm:$false -Force -AllowClobber -Scope $psScope -WarningAction SilentlyContinue
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
Write-Verbose “* CheckAndInstallPSModulePrereq: The $($ModuleName) PowerShell Module is installed from the PSGallery.”
}
}
# Import the Module
try
{
Import-Module -Name $($ModuleName) -Force
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
Write-Verbose “* CheckAndInstallPSModulePrereq: The $($ModuleName) PowerShell Module is imported in the current session.”
#endregion Check PS Module status
}

function Invoke-NETFrameworkCheck() {
<# .SYNOPSIS Check if the .NET Framework version is 4.7.2 or up. .DESCRIPTION Check if the .NET Framework version is 4.7.2 or up. .EXAMPLE Invoke-NETFrameworkCheck .CONTEXT Windows Virtual Desktops .MODIFICATION_HISTORY Esther Barthel, MSc - 17/05/20 - Original code Esther Barthel, MSc - 17/05/20 - Standardizing script, based on the ControlUp Scripting Standards (version 0.2) .COMPONENT .NOTES Version: 0.1 Author: Esther Barthel, MSc Creation Date: 2020-05-17 Updated: 2020-05-17 Standardized the function, based on the ControlUp Standards (v0.2) Purpose: Script Action, created for ControlUp WVD Monitoring Copyright (c) cognition IT. All rights reserved. #>
[CmdletBinding()]
Param()

#region Check if the current .NET Framework is 4.7.2 or higher (Release Value = 461808 or higher) prerequisite for the Az PowerShell Module
If ((Get-ItemProperty ‘HKLM:SOFTWAREMicrosoftNET Framework SetupNDPv4Full’ -Name Release).Release -ge 461808)
{
# Required .NET Framework found
Write-Verbose “.NET Framework 4.7.2 or up is installed on this machine”
return $true
}
Else
{
return $false
}
#endregion Check .NET Framework
}

function Get-WVDHostpoolSessionHost () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the Subscription ID’
)]
[string] $SubscriptionID,

[Parameter(
Position=1,
Mandatory=$false,
HelpMessage=’Enter the Host Pool name’
)]
[string] $HostPoolName,

[Parameter(
Position=2,
Mandatory=$false,
HelpMessage=’Enter the Session Host name’
)]
[string] $SessionHostName
)

#Retrieve the WVD hostPool information for this Subscription
[array]$psobjectCollection = Get-AzWvdHostPool -SubscriptionId $($azSubscription.Id.ToString()) |
ForEach-Object {
$wvdHostPool = $_
If ($wvdHostPool.Name -like “$HostPoolName*”)
{
# Retrieve the SessionHost information for each HostPool
Get-AzWvdSessionHost -HostPoolName $wvdHostpool.Name -ResourceGroupName $($wvdHostPool.Id.Split(“/”)[4]) |
ForEach-Object {
$wvdSessionHost = $_
If ($wvdSessionHost.Name.Split(“/”)[1] -like “$SessionHostName*”)
{
# retrieve both SessionHost and corresponding HostPool information for each SessionHost
$wvdSessionHost | Select @{Name=’HostPoolName’; Expression={$wvdHostPool.Name}},
@{Name=’SessionHostName’; Expression={$_.Name.Split(“/”)[1]}},
AgentVersion,
AllowNewSession,
@{Name=’DrainMode’; Expression={if($_.AllowNewSession -eq “True”){return “Off”}else{return “On”}}},
AsignedUser,
LastHeartBeat,
LastUpdateTime,
OSVersion,
Session,
@{Name=’ActiveSessions’; Expression={$_.Session}},
Status,
StatusTimestamp,
SxSStackVersion,
Type,
UpdateErrorMessage,
UpdateState,
@{Name=’HostPoolApplicationGroupReference’; Expression={$wvdHostPool.ApplicationGroupReference}},
@{Name=’HostPoolCustomRdpProperty’; Expression={$wvdHostPool.CustomRdpProperty}},
@{Name=’HostPoolDescription’; Expression={$wvdHostPool.Description}},
@{Name=’HostPoolFriendlyName’; Expression={$wvdHostPool.FriendlyName}},
@{Name=’HostPoolType’; Expression={$wvdHostPool.HostPoolType}},
@{Name=’HostPoolLoadBalancerType’; Expression={$wvdHostPool.LoadBalancerType}},
@{Name=’HostpoolLocation’; Expression={$wvdHostPool.Location}},
@{Name=’HostpoolMaxSessionLimit’; Expression={$wvdHostPool.MaxSessionLimit}},
@{Name=’HostpoolResourceGroup’; Expression={$_.Id.Split(“/”)[4]}},
@{Name=’HostPoolSsoContext’; Expression={$wvdHostPool.SsoContext}},
@{Name=’HostPoolVMTemplate’; Expression={$wvdHostPool.VMTemplate}},
@{Name=’HostPoolValidationEnvironment’; Expression={$wvdHostPool.ValidationEnvironment}}
}
}
}
}
return $psobjectCollection
}

function Set-WVDSessionHostDrainMode () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the Session Host Name’
)]
[string] $SessionHostName,

[Parameter(
Position=1,
Mandatory=$false,
HelpMessage=’Enter the Host Pool name’
)]
[string] $HostPoolName,

[Parameter(
Position=2,
Mandatory=$false,
HelpMessage=’Enter the Resource Group name’
)]
[string] $ResourceGroupName,

[Parameter(
Position=2,
Mandatory=$false,
HelpMessage=’Enter the Drain Modee’
)]
[ValidateSet(“ON”,”OFF”)]
[string] $DrainMode
)

# Translate Drain Mode to boolean value
$boolDrainMode = $false
If ($DrainMode -eq “OFF”)
{
$boolDrainMode = $true
}

#Update the WVD Session Host Drain Mode (AllowNewSession parameter)
try
{
Update-AzWvdSessionHost -HostPoolName $HostPoolName -ResourceGroupName $ResourceGroupName -Name $SessionHostName -AllowNewSession:$boolDrainMode | Out-Null

}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
}

function Set-WVDHostpoolMaxSessionLimit () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the Hostpool Name’
)]
[string] $HostpoolName,

[Parameter(
Position=1,
Mandatory=$true,
HelpMessage=’Enter the Resource Group name’
)]
[string] $ResourceGroupName,

[Parameter(
Position=2,
Mandatory=$false,
HelpMessage=’Enter the max session limit’
)]
[int] $MaxSessionLimit
)

#Update the WVD Hostpool Max Session Limit (AllowNewSession parameter)
try
{
Update-AzWvdHostPool -Name $HostPoolName -ResourceGroupName $ResourceGroupName -MaxSessionLimit $MaxSessionLimit | Out-Null
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
}

function Set-WVDHostpoolLoadBalancerType () {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the Hostpool Name’
)]
[string] $HostpoolName,

[Parameter(
Position=1,
Mandatory=$true,
HelpMessage=’Enter the Resource Group name’
)]
[string] $ResourceGroupName,

[Parameter(
Position=2,
Mandatory=$false,
HelpMessage=’Enter the Load Balancer Type’
)]
[ValidateSet(“BreadthFirst”,”DepthFirst”)]
[string] $LoadBalancerType
)

#Update the WVD Hostpool LoadBalancerType
try
{
Update-AzWvdHostPool -Name $HostPoolName -ResourceGroupName $ResourceGroupName -LoadBalancerType $LoadBalancerType | Out-Null
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
}

# dot sourcing ControlUp Script Action settings
#region ControlUp Script Standards – version 0.2
#Requires -Version 5.1

# Configure a larger output width for the ControlUp PowerShell console
[int]$outputWidth = 400
# Altering the size of the PS Buffer
$PSWindow = (Get-Host).UI.RawUI
$WideDimensions = $PSWindow.BufferSize
$WideDimensions.Width = $outputWidth
$PSWindow.BufferSize = $WideDimensions

# Ensure Debug information is shown, without the confirmation question after each Write-Debug
If ($PSBoundParameters[‘Debug’]) {$DebugPreference = “Continue”}
If ($PSBoundParameters[‘Verbose’]) {$VerbosePreference = “Continue”}
$ErrorActionPreference = “Stop”

# ControlUp Monitor
$rootFolderCUMonitor = “C:Program FilesSmart-XControlUpMonitor”
$psModuleDLLCUMonitorUser = “ControlUp.PowerShell.User.dll”

#ControlUp Console
$rootFolderCUConsole = “WVD-SpringRelease”
#endregion

function Load-CUUserPSModule() {
[CmdletBinding()]
Param(
[Parameter(
Position=0,
Mandatory=$true,
HelpMessage=’Enter the ControlUp Monitor root folder’
)]
[ValidateNotNullOrEmpty()]
[string] $CUMonitorRootFolder,

[Parameter(
Position=1,
Mandatory=$true,
HelpMessage=’Enter the ControlUp Monitor PowerShell Module DLL to be imported’
)]
[ValidateNotNullOrEmpty()]
[string] $PSModuleDLL
)

# Load the ControlUp User PowerShell Module
If (Test-Path $CUMonitorRootFolder)
{
# Retrieve the latest version of the CU Monitor
$cuMonitorPath = (Get-ChildItem -Path $CUMonitorRootFolder -Directory -Depth 1 | Sort Name -Descending)[0].FullName
try
{
# Import PowerShell Module
Import-Module “$cuMonitorPath$PSModuleDLL” -Force
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
}
Else
{
Write-Error “CU Monitor installation folder ($($CUMonitorRootFolder)) not found”
Exit
}
}

#————————#
# Script Action Workflow #
#————————#
Write-Host “”

#region Retrieve input parameters
#HUser = $args[0]
If ([string]::IsNullOrEmpty($User))
{
$User = “”
}
#endregion

## Check if the required PowerShell Modules are installed and can be imported
Invoke-CheckInstallAndImportPSModulePrereq -ModuleName “Az.Accounts” #-Verbose
Invoke-CheckInstallAndImportPSModulePrereq -ModuleName “Az.DesktopVirtualization” #-Verbose
# NO need anymore to import the WVD 2019 Fall Release PowerShell Module
# Invoke-CheckInstallAndImportPSModulePrereq -ModuleName “Microsoft.RDInfra.RDPowerShell” -Verbose

## Testing Script output
If ($azSPCredentials = Get-AzSPStoredCredentials)
{
# Sign in to Azure with a Service Principal with Contributor Role at Subscription level
try
{
$azSPSession = Connect-AzAccount -Credential $azSPCredentials.spCreds -Tenant $($azSPCredentials.tenantID).ToString() -ServicePrincipal -WarningAction SilentlyContinue
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}

# Retrieve the Subscription information for the Service Principal (that is logged on)
$azSubscription = Get-AzSubscription

try
{
#Retrieve the WVD hostPool information for this Subscription
[array]$psobjectCollection = Get-AzWvdHostPool -SubscriptionId $($azSubscription.Id.ToString()) |
ForEach-Object {
$wvdHostPool = $_
If ($wvdHostPool.Name -like “*”)
{
# Retrieve the User Session information for each HostPool
Get-AzWvdUserSession -HostPoolName $wvdHostpool.Name -ResourceGroupName $($wvdHostPool.Id.Split(“/”)[4]) |
ForEach-Object {
$wvdUserSession = $_
If ($wvdUserSession.ActiveDirectoryUserName -like “*$User*”)
{
# retrieve User Sessions per HostPool and SessionHost
$wvdUserSession | Select @{Name=’HostPoolName’; Expression={$_.Name.Split(“/”)[0]}},
@{Name=’SessionHostName’; Expression={$_.Name.Split(“/”)[1]}},
@{Name=’UserSessionID’; Expression={$_.Name.Split(“/”)[2]}},
ActiveDirectoryUserName,
ApplicationType,
CreateTime,
Id,
Name,
SessionState,
Type,
UserPrincipalName,
@{Name=’HostpoolResourceGroup’; Expression={$_.Id.Split(“/”)[4]}},
@{Name=’Message’; Expression={$Message}}

# Send Message to selected user sessions!
#debug: Write-Host “Sending message $Message to user $($wvdUserSession.ActiveDirectoryUserName)” -ForegroundColor Yellow
try
{
Send-AzWvdUserSessionMessage -HostPoolName $($wvdUserSession.Name.Split(“/”)[0]) -SessionHostName $($wvdUserSession.Name.Split(“/”)[1]) -ResourceGroupName $($wvdUserSession.Id.Split(“/”)[4]) -UserSessionId $($wvdUserSession.Name.Split(“/”)[2]) -MessageTitle “WVD Admin message” -MessageBody $Message
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Break
}
}
}
}
}
}
catch
{
Write-Error (“A [” + $_.Exception.GetType().FullName + “] ERROR occurred. ” + $_.Exception.Message)
Exit
}
# Return the SessionHost information (limited details with Select)
Write-Host “WVD 2020 Spring Release User Session Message: ” -ForegroundColor Yellow
if ($psobjectCollection.Count -gt 0)
{
$psobjectCollection | Sort-Object HostPoolName, SessionHostName | Select @{Name=’HostPool’; Expression={$_.HostPoolName}}, @{Name=’SessionHost’; Expression={$_.SessionHostName.Split(“.”)[0]}}, @{Name=’SessionID’; Expression={$_.UserSessionID}}, @{Name=’User’; Expression={$_.ActiveDirectoryUserName.Split(“”)[1]}}, @{Name=’State’; Expression={$_.SessionState}}, Message | Format-Table -AutoSize
# $psobjectCollection | Sort-Object HostPoolName, SessionHostName | Select *
}
else
{
Write-Warning “No User Session information could be retrieved”
}
}
else
{
Write-Output “”
Write-Warning “No Azure Credentials could be retrieved from the stored credentials file for this user.”
Write-Output “”
}

# Disconnect the Azure Session
Disconnect-AzAccount | Out-Null

START YOUR TRIAL

Get Your Download Link

Gain access to ControlUp from your PC. Register and get a link to start your Free Trial.