Today I got the question from someone that they where trying to send messages to users but had issues with adding the session id’s to the json. I decided to make a quick and nice script that’s able to send a message to all sessions. This uses the standard functions that I always use, the standard Get-HorizonRestData function that I created in this blog post and two custom functions that I created for this script.
The first new function is get-horizonsessions this function gets all local sessions utilizing the get-horizonrestdata function. As you can see pretty basic nothing fancy about it.
function get-horizonsessions(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken
)
try{
Get-HorizonRestData -ServerURL $url -RestMethod "/inventory/v1/sessions/" -accessToken $accessToken
}
catch{
throw $_
}
return $results
}
The second one isn’t that more advanced besides that it has a few more parameters including one called $session_ids that requires an array of the session id’s to where you want to send a message. It creates an ordered hashtable that stores the message, message_type and the array of id’s. This hashtable is than converted to a json file and used as the body for the rest call.
function send-horizonmessage(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[array] $Session_Ids,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $Message,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[validateset("ERROR","WARNING","INFO", IgnoreCase = $false)]
[string] $Message_Type
)
$jsonhashtable = [ordered]@{}
$jsonhashtable.add('message',$message)
$jsonhashtable.add('message_type',$Message_Type)
$jsonhashtable.add('session_ids',$Session_Ids)
$json = $jsonhashtable | convertto-json
try{
$results = Invoke-RestMethod -Method Post -uri "$ServerURL/rest/inventory/v1/sessions/action/send-message" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken) -body $json
}
catch{
throw $_
}
return $results
}
Than I use these 2 lines to actually send the message (after authenticating first, duh). If you want to filter the sessions that can be added to the get-horizonsessions or manually do it on the $sessions array. Be aware that there are no names in this array so you need to gather any of the optional id’s first.
$sessions = get-horizonsessions -accessToken $accessToken -ServerURL $url
send-horizonmessage -accessToken $accessToken -ServerURL $url -Message_Type $Message_Type -message $message -Session_Ids ($sessions).id
And this is how you run the entire script.
.\Horizon_send_messages.ps1 -Credential $credential -ConnectionServerFQDN pod1cbr1.loft.lab -Message "retouw.nl test message" -Message_Type ERROR
And the entire script that’s also available at my Various_Scripts/Horizon_send_messages.ps1 at master · Magneet/Various_Scripts (github.com).
<#
.SYNOPSIS
Send a message to all user sessions
.DESCRIPTION
This script uses the Horizon rest api's to all sessions in a horizon pod
.EXAMPLE
.\find_user_assigned_desktops.ps1 -Credential $creds -ConnectionServerFQDN pod2cbr1.loft.lab -message "test message" -message_type "ERROR"
.PARAMETER Credential
Mandatory: No
Type: PSCredential
Object with credentials for the connection server with domain\username and password
.PARAMETER ConnectionServerFQDN
Mandatory: Yes
Default: String
FQDN of the connection server to connect to
.PARAMETER message
Mandatory: Yes
Message to send to the users
.PARAMETER message_type
Mandatory: Yes
Message type: INFO, ERROR or WARNING
.NOTES
Created by: Wouter Kursten
First version: 23-12-2021
.COMPONENT
Powershell Core
#>
[CmdletBinding()]
param (
[Parameter(Mandatory=$false,
HelpMessage='Credential object as domain\username with password' )]
[PSCredential] $Credential,
[Parameter(Mandatory=$true, HelpMessage='FQDN of the connectionserver' )]
[ValidateNotNullOrEmpty()]
[string] $ConnectionServerFQDN,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $Message,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[validateset("ERROR","WARNING","INFO", IgnoreCase = $false)]
[string] $Message_Type
)
function Get-HRHeader(){
param($accessToken)
return @{
'Authorization' = 'Bearer ' + $($accessToken.access_token)
'Content-Type' = "application/json"
}
}
function Open-HRConnection(){
param(
[string] $username,
[string] $password,
[string] $domain,
[string] $url
)
$Credentials = New-Object psobject -Property @{
username = $username
password = $password
domain = $domain
}
return invoke-restmethod -Method Post -uri "$url/rest/login" -ContentType "application/json" -Body ($Credentials | ConvertTo-Json)
}
function Close-HRConnection(){
param(
$accessToken,
$url
)
return Invoke-RestMethod -Method post -uri "$url/rest/logout" -ContentType "application/json" -Body ($accessToken | ConvertTo-Json)
}
function Get-HorizonRestData(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
ParameterSetName="filteringandpagination",
HelpMessage='Array of ordered hashtables' )]
[array] $filters,
[Parameter(Mandatory=$true,
ParameterSetName="filteringandpagination",
HelpMessage='Type of filter Options: And, Or' )]
[ValidateSet('And','Or')]
[string] $Filtertype,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='Page size, default = 500' )]
[int] $pagesize = 500,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[string] $RestMethod,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken,
[Parameter(Mandatory=$false,
ParameterSetName="filteringandpagination",
HelpMessage='$True for rest methods that contain pagination and filtering, default = False' )]
[switch] $filteringandpagination,
[Parameter(Mandatory=$false,
ParameterSetName="id",
HelpMessage='To be used with single id based queries like /monitor/v1/connection-servers/{id}' )]
[string] $id
)
if($filteringandpagination){
if ($filters){
$filterhashtable = [ordered]@{}
$filterhashtable.add('type',$filtertype)
$filterhashtable.filters = @()
foreach($filter in $filters){
$filterhashtable.filters+=$filter
}
$filterflat=$filterhashtable | convertto-json -Compress
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?filter="+$filterflat+"&page="
}
else{
$urlstart= $ServerURL+"/rest/"+$RestMethod+"?page="
}
$results = [System.Collections.ArrayList]@()
$page = 1
$uri = $urlstart+$page+"&size=$pagesize"
$response = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
$response.foreach({$results.add($_)}) | out-null
if ($responseheader.HAS_MORE_RECORDS -contains "TRUE") {
do {
$page++
$uri = $urlstart+$page+"&size=$pagesize"
$response = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
$response.foreach({$results.add($_)}) | out-null
} until ($responseheader.HAS_MORE_RECORDS -notcontains "TRUE")
}
}
elseif($id){
$uri= $ServerURL+"/rest/"+$RestMethod+"/"+$id
$results = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
}
else{
$uri= $ServerURL+"/rest/"+$RestMethod
$results = Invoke-RestMethod $uri -Method 'GET' -Headers (Get-HRHeader -accessToken $accessToken) -ResponseHeadersVariable responseheader
}
return $results
}
function get-horizonsessions(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken
)
try{
Get-HorizonRestData -ServerURL $url -RestMethod "/inventory/v1/sessions/" -accessToken $accessToken
}
catch{
throw $_
}
return $results
}
function send-horizonmessage(){
[CmdletBinding(DefaultParametersetName='None')]
param(
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $ServerURL,
[Parameter(Mandatory=$true,
HelpMessage='Part after the url in the swagger UI i.e. /external/v1/ad-users-or-groups' )]
[PSCustomObject] $accessToken,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[array] $Session_Ids,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[string] $Message,
[Parameter(Mandatory=$true,
HelpMessage='url to the server i.e. https://pod1cbr1.loft.lab' )]
[validateset("ERROR","WARNING","INFO", IgnoreCase = $false)]
[string] $Message_Type
)
$jsonhashtable = [ordered]@{}
$jsonhashtable.add('message',$message)
$jsonhashtable.add('message_type',$Message_Type)
$jsonhashtable.add('session_ids',$Session_Ids)
$json = $jsonhashtable | convertto-json
try{
$results = Invoke-RestMethod -Method Post -uri "$ServerURL/rest/inventory/v1/sessions/action/send-message" -ContentType "application/json" -Headers (Get-HRHeader -accessToken $accessToken) -body $json
}
catch{
throw $_
}
return $results
}
if($Credential){
$creds = $credential
}
else{
$creds = get-credential
}
$ErrorActionPreference = 'Stop'
$username=($creds.username).split("\")[1]
$domain=($creds.username).split("\")[0]
$password=$creds.password
$url = "https://$ConnectionServerFQDN"
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$accessToken = Open-HRConnection -username $username -password $UnsecurePassword -domain $Domain -url $url
$sessions = get-horizonsessions -accessToken $accessToken -ServerURL $url
send-horizonmessage -accessToken $accessToken -ServerURL $url -Message_Type $Message_Type -message $message -Session_Ids ($sessions).id