VMware Horizon Community
MiMenl
Enthusiast
Enthusiast

Script to send messages to multiple users (where HTML 5 is limited in horizon 7.x)

Hi i Just wanted to share this in case it can be of any help to someone.

Its a script (with GUI) which can be used to send messages to connected users in a pod.
The script uses the local instance so you need to connect to the connection server which belongs to the pod you want to send a message too.
It is only possible to sens a message desktop pool based.

I could not find a proper space to add this to teh vemware code part of the forum. but feel free to move this if this is not the right location.

#Powershell script with GUI to send messages to selected users in an horizon environment.
#The HTML 5 interface in horizon 7.x can only send messaged to 20 people at once where flash was able to send many more.
#This will probably be changed in a later release of horizon.
#This script was made to overcome this issue in case you need to send a message to more pople at once.
#It uses the local instance so connect so the connection server of the pod containing the pool you want to send a message too.
#The Script comes without any warranty.
#Mark Platte 2021



Add-Type -assembly System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
#variable setup

$strUser = ""
$strServer = ""
$strPassword = ""
$strdomain = ""


$script:hvServer 
$script:hvServices 
$script:queryResultsService
    
#form Setup

#form
$main_form = New-Object System.Windows.Forms.Form
$main_form.Text ='Horizon send Message ®Mark Platte 2021'
$main_form.Width = 800
$main_form.Height = 810
$main_form.ControlBox =$false
$main_form.StartPosition="CenterScreen"
$main_form.FormBorderStyle = "FixedSingle"
#button connect
$btnButtonConnect = New-Object System.Windows.Forms.Button
$btnButtonConnect.Location = New-Object System.Drawing.Size(0,120)
$btnButtonConnect.Size = New-Object System.Drawing.Size(780,25)
$btnButtonConnect.Text = "Connect to connection server"
$main_form.Controls.Add($btnButtonConnect)

#button exit
$btnExit = New-Object System.Windows.Forms.Button
$btnExit.Location = New-Object System.Drawing.Size(620,740)
$btnExit.Size = New-Object System.Drawing.Size(150,25)
$btnExit.Text = "Exit"
$main_form.Controls.Add($btnExit)


#button sendmessage
$btnSend = New-Object System.Windows.Forms.Button
$btnSend.Location = New-Object System.Drawing.Size(520,475)
$btnSend.Size = New-Object System.Drawing.Size(250,25)
$btnSend.Text = "Send Message(s)"
$main_form.Controls.Add($btnSend)


#button Select all
$btnSelect = New-Object System.Windows.Forms.Button
$btnSelect.Location = New-Object System.Drawing.Size(48,500)
$btnSelect.Size = New-Object System.Drawing.Size(100,25)
$btnSelect.Text = "Select all"
$main_form.Controls.Add($btnSelect)


#button deselectall
$btndeSelect = New-Object System.Windows.Forms.Button
$btndeSelect.Location = New-Object System.Drawing.Size(148,500)
$btndeSelect.Size = New-Object System.Drawing.Size(100,25)
$btndeSelect.Text = "Deselect all"
$main_form.Controls.Add($btndeSelect)

#button Ger users
$btnGetUsers = New-Object System.Windows.Forms.Button
$btnGetUsers.Location = New-Object System.Drawing.Size(525,158)
$btnGetUsers.Size = New-Object System.Drawing.Size(250,25)
$btnGetUsers.Text = "Get Connected Users"
$main_form.Controls.Add($btnGetUsers)

#labels
$lblServer = New-Object System.Windows.Forms.Label
$lblServer.Location = New-Object System.Drawing.Size(0,15)
$lblServer.Size = New-Object System.Drawing.Size(150,25)
$lblServer.Text = "Connection Server:"
$main_form.Controls.Add($lblServer)

$lblUser = New-Object System.Windows.Forms.Label
$lblUser.Location = New-Object System.Drawing.Size(0,40)
$lblUser.Size = New-Object System.Drawing.Size(150,25)
$lblUser.Text = "User Name:"
$main_form.Controls.Add($lblUser)

$lblPassword = New-Object System.Windows.Forms.Label
$lblPassword.Location = New-Object System.Drawing.Size(0,65)
$lblPassword.Size = New-Object System.Drawing.Size(150,25)
$lblPassword.Text = "Password:"
$main_form.Controls.Add($lblPassword)

$lbldomain = New-Object System.Windows.Forms.Label
$lbldomain.Location = New-Object System.Drawing.Size(0,90)
$lbldomain.Size = New-Object System.Drawing.Size(150,25)
$lbldomain.Text = "Domain:"
$main_form.Controls.Add($lbldomain)

$lblPool = New-Object System.Windows.Forms.Label
$lblPool.Location = New-Object System.Drawing.Size(0,165)
$lblPool.Size = New-Object System.Drawing.Size(75,25)
$lblPool.Text = "Select pool: "
$main_form.Controls.Add($lblPool)

$lblStatus = New-Object System.Windows.Forms.Label
$lblStatus.Location = New-Object System.Drawing.Size(50,740)
$lblStatus.Size = New-Object System.Drawing.Size(50,25)
$lblStatus.Text = "Status: "
$main_form.Controls.Add($lblStatus)

$lblMessage = New-Object System.Windows.Forms.Label
$lblMessage.Location = New-Object System.Drawing.Size(100,740)
$lblMessage.Size = New-Object System.Drawing.Size(700,25)
$lblMessage.Text = "Please fill in the requested information to connect"
$main_form.Controls.Add($lblMessage)


$lblPriority = New-Object System.Windows.Forms.Label
$lblPriority.Location = New-Object System.Drawing.Size(520,455)
$lblPriority.Size = New-Object System.Drawing.Size(55,25)
$lblPriority.Text = "Sevirity:"
$main_form.Controls.Add($lblPriority)

#textboxes

$txtServer = New-Object System.Windows.Forms.TextBox
$txtServer.Location = New-Object System.Drawing.Size(150,10)
$txtServer.Size = New-Object System.Drawing.Size(400,25)
$txtServer.Text = ""
$main_form.Controls.Add($txtServer)

$txtUser = New-Object System.Windows.Forms.TextBox
$txtUser.Location = New-Object System.Drawing.Size(150,35)
$txtUser.Size = New-Object System.Drawing.Size(400,25)
$txtUser.Text = ""
$main_form.Controls.Add($txtUser)

$txtPass = New-Object System.Windows.Forms.TextBox
$txtPass.Location = New-Object System.Drawing.Size(150,60)
$txtPass.Size = New-Object System.Drawing.Size(400,25)
$txtPass.Text = ""
$txtPass.PasswordChar ="*"
$main_form.Controls.Add($txtPass)

$txtdomain = New-Object System.Windows.Forms.TextBox
$txtdomain.Location = New-Object System.Drawing.Size(150,85)
$txtdomain.Size = New-Object System.Drawing.Size(400,25)
$txtdomain.Text = ""
$main_form.Controls.Add($txtdomain)


$txtMessage = New-Object System.Windows.Forms.TextBox
$txtMessage.Multiline =$true
$txtMessage.Location = New-Object System.Drawing.Size(520,200)
$txtMessage.Size = New-Object System.Drawing.Size(250,240)
$txtMessage.Text = ""
$main_form.Controls.Add($txtMessage)

$txtstatus = New-Object System.Windows.Forms.TextBox
$txtstatus.Location = New-Object System.Drawing.Size(50,530)
$txtstatus.Size = New-Object System.Drawing.Size(725,195)
$txtstatus.Multiline =$true
$txtstatus.ScrollBars="Vertical"
$txtstatus.Text = ""
$main_form.Controls.Add($txtstatus)


#comboboxes

$cbPools = New-Object System.Windows.Forms.ComboBox
$cbPools.Location = New-Object System.Drawing.Size(80,160)
$cbPools.Size = New-Object System.Drawing.Size(150,25)
$main_form.Controls.Add($cbPools)


$cbPriority = New-Object System.Windows.Forms.ComboBox
$cbPriority.Location = New-Object System.Drawing.Size(575,450)
$cbPriority.Size = New-Object System.Drawing.Size(195,25)
$cbPriority.Items.Add("WARNING")
$cbPriority.Items.Add("ERROR")
$cbPriority.Items.Add("INFO")
$cbPriority.SelectedIndex =2

$main_form.Controls.Add($cbPriority)

#ListView
$dvUsers = New-Object System.Windows.Forms.ListView 
$dvUsers.Location = New-Object System.Drawing.Size(50,200)
$dvUsers.Size = New-Object System.Drawing.Size(450,300)
$dvUsers.MultiSelect =$true
$dvusers.CheckBoxes =$true
$dvUsers.View ="Details"
$dvUsers.GridLines =$true
$dvusers.Columns.Add("User").Width =150
$dvusers.Columns.Add("Session State").Width =150
$dvusers.Columns.Add("Desktop Pool").Width =150
$dvusers.Columns.Add("id").Width =150
$main_form.Controls.Add($dvUsers)
 
#Checkboxes

$checkbox1 = new-object System.Windows.Forms.checkbox
$checkbox1.Location = new-object System.Drawing.Size(250,145)
$checkbox1.Size = new-object System.Drawing.Size(250,50)
$checkbox1.Text = "Only get Conneted sessions"
$checkbox1.Checked = $true
$main_form.Controls.Add($checkbox1)  

#functions
#fucntion to conenct to 1 connection server
function Connect-Horizon 
{
    try{
        $lblMessage.text = "Trying to connect to " + $strServer.ToString()
        Connect-HVServer -Server $strServer -User $strUser -Password $strPassword -Domain $strdomain
        $lblMessage.text = "Connected to " + $strServer.ToString()
        }
    catch{$lblMessage.Text = "Error While connecting please check provided information "}
}

function Write-text($string)
{
$txtstatus.Text = $txtstatus.text + $string + "`r`n"
}



#eventhandling

#btnConnect handler
#Click will get details form textfields to getr connection information (its not all secure no secure string is used so be sureto close program after use)
#it will also populate the pool combobox.
$btnButtonConnect.Add_Click(
{
    $cbPools.Items.Clear()
    $strServer = $txtServer.Text.ToString()
    $strUser =$txtUser.Text.ToString()
    $strPassword = $txtPass.Text.ToString()
    $strdomain = $txtdomain.Text.ToString()

    if( $strServer -ne "" -and $strUser -ne "" -and $strPassword -ne "" )
    {
        $script:hvServer = Connect-Horizon
        $script:hvServices = $hvServer.ExtensionData
        try{
                $queryServiceDesktop = New-Object VMware.Hv.QueryServiceService
                $defn = New-Object VMware.Hv.QueryDefinition
                $defn.queryEntityType = 'DesktopSummaryView'
                $defn.sortBy = 'desktopSummaryData.name'
                $defn.sortDescending = $true
                $queryResultsDesktop = $queryServiceDesktop.QueryService_Create($script:hvServices, $defn)

                try{
                    foreach ($DTresult in $queryResultsDesktop.Results) 
                    {
                        $cbPools.Items.Add( $DTresult.DesktopSummaryData.Name.ToString())
                    }
                $cbpools.SelectedIndex = 0
       
                    }
        catch {Write-text "An error occured while retrieving data"}
             }
    catch{ 
    Write-text "An Error Occured"
    }
   
    
    }
    else {$lblMessage.text = "Provide all data"}
}
)

# click will query user sessions from connection server for the selected pool eithe rall sessions or only connected sessions based on checkbox
$btnGetUsers.Add_Click(
{
    $queryServiceService = New-Object VMware.Hv.QueryServiceService
    $defnService = New-Object VMware.Hv.QueryDefinition
    $defnService.queryEntityType = 'SessionLocalSummaryView'
    $defnService.sortDescending = $False
    $script:queryResultsService = $queryServiceService.QueryService_query($script:hvServices, $defnService)
    $dvUsers.Items.Clear()

    try {
            $lblMessage.text = "Getting Users"
            $nUsers = 0
            foreach ($result in $script:queryResultsService.Results) 
            {
                  if($checkbox1.CheckState -eq "Checked")
                  {
                    if($result.NamesData.DesktopPoolCN.ToString() -eq $cbPools.SelectedItem.ToString().ToLower() -and $result.SessionData.SessionState.ToString() -eq "CONNECTED")
                    {
                        $nUsers = $nUsers + 1
                        $lvData = New-Object System.Windows.Forms.ListViewItem
                        $lvData.Text = $result.NamesData.UserName.ToString() 
                        $lvData.SubItems.Add($result.SessionData.SessionState.ToString())
                        $lvData.SubItems.Add($result.NamesData.DesktopPoolCN.ToString())
                        $lvData.SubItems.Add($result.Id.tostring())
                        $dvUsers.items.Add($lvData)
       
                    }
      
                 }
      
                if($checkbox1.CheckState -eq "Unchecked")
                {
                    if($result.NamesData.DesktopPoolCN.ToString() -eq $cbPools.SelectedItem.ToString().ToLower() )
                    {
                        $nUsers = $nUsers + 1
                        $lvData = New-Object System.Windows.Forms.ListViewItem
                        $lvData.Text = $result.NamesData.UserName.ToString() 
                        $lvData.SubItems.Add($result.SessionData.SessionState.ToString())
                        $lvData.SubItems.Add($result.NamesData.DesktopPoolCN.ToString())
                        $lvData.SubItems.Add($result.Id.tostring())
                        $dvUsers.items.Add($lvData)
                    }
                }
         $lblMessage.text = "Retrieved " + $nUsers.ToString() + " sessions"
         
      }
      Write-text $lblMessage.text = "Retrieved " + $nUsers.ToString() + " sessions"

    } 
    catch {}
}
)

#Click will send message to all selected users (it will loop trough query results so its not entirly optimal but I did not spend time in saving the ID to an object for later use.
$btnSend.Add_Click(
{


$nerror=0
$nsend=0
foreach($item in $dvUsers.CheckedItems)
{
    foreach($result in $script:queryResultsService.Results)
    {
        if($result.NamesData.UserName.ToString() -eq $item.subitems[0].text)
        {
            $user = $result.NamesData.UserName.ToString()
                try{
                        $hvServices.Session.Session_SendMessage($result.Id,$cbPriority.SelectedItem.ToString(),$txtMessage.Text.ToString())
                        $nsend = $nsend + 1
                        Write-text "Message send to : $user"
                   }
                catch
                    {
                        $nerror = $nerror + 1
                        Write-text "Error While sending Message to : $user"
                    }

        }
    }
}
    $ntotal = $nerror + $nsend
   
    Write-text "Tried to send  $ntotal message(s) | $nerror Errors  | $nsend Send"
}
)

$btnSelect.Add_Click(
{
foreach($item in $dvUsers.Items){
$Item.checked =$true
}

}
)


$btndeSelect.Add_Click(
{
foreach($item in $dvUsers.Items){
$Item.checked =$false
}

}
)


#$hvServices.Session.Session_SendMessage($result.Id,"INFO","test vanuit powershell")



#btnExit handler
$btnExit.Add_Click(
{
    try{
        Disconnect-HVServer $txtServer.Text.ToString() -Force -Confirm $true
       }
       catch{write-host "Could not disconnect"}

$main_form.Close()
}
)


Write-text("Program started ")


$main_form.ShowDialog()

 

Hope it helps.

 

Mark

It's not code it's spaghetti, and who doesn't like pasta ?
Reply
0 Kudos
0 Replies