Category Archives: VMware

VMware Horizon Logoff Script with PowerCLI

One drawback with Horizon View is that it does not have the ability (through the GUI) to automate user logoffs or reboots on a daily/weekly basis. Thankfully, VMware has written some halfway decent PowerShell snap-ins so we can script such tasks. I say halfway decent because there are only 45 commandlets and only 20 are actually useful…

Automated logoffs are useful in instant and linked cloned scenarios (hopefully everyone is using instant clones and admiring how awesome they are) where you have to deploy an image update immediately and logoff existing sessions later. Thankfully for my blog readers, I have written such a script to do that. This script utilizes the Get-RemoteSession and Send-SessionLogoff Horizon PowerCLI commandlets. Unfortunately there is no PowerCLI commandlet to send messages to the active sessions, so I had to convert each session’s machine name to a string and do a ForEach loop to pipe those names into the msg.exe command.

The other unique thing about this script is that it only does half of the pool at a time (using some variable array magic). The way it’s currently written, it sends a message to half of the sessions that warns them they will be logged off in 15 minutes, warns them again at 60 seconds prior to logoff, logs the first half of sessions off, and then repeats the process with the second half of sessions.

Also, if you want to run this script real-time versus scheduling it in Task Scheduler, I have included Write-Host commands along the way so you can actually see which sessions are being warned and logged off throughout the whole process.

The only thing you’ll need to do before running the script is adjust the 3 variables at the top: $PoolName (name of the Horizon pool), $FirstWarning (How long of a warning the users get before logoff), and $FinalWarning (The second warning time the users get before logoff). Run this or schedule it on a Connection Server and you’re good to go! Enjoy!

###### VMware Horizon Logoff Script ######
###### Created by Nick Burton 10/9/2017 ######

# This script logs off any active sessions for a particular pool. This is useful for enforcing image updates.
# Simply set the pool name and two warning times below! Schedule it with task manager on a Connection Server.

#### KNOWN ISSUES ####
# Currently this script will NOT work if only one session exists due to the array usage in the variables. An IF statement could fix this.
# If two or three sessions exist, this script will logoff all sessions due to the half calculation and array locations starting at 0.
######################

# First, set the poolname below:
$PoolName = “POOL NAME HERE”

# Next, set the first warning time prior to the reboot in seconds. 15 minutes = 900 seconds.
$FirstWarning = 900

# Finally, set the final warning time prior to the reboot in seconds.
$FinalWarning = 60

###################################################################
# DO NOT EDIT ANYTHING BELOW!!! #
###################################################################

# Get first warning time minus final warning time in order to send second message at appropriate time
$WaitTime = $FirstWarning – $FinalWarning
$FirstWarningMinutes = $FirstWarning / 60

# Add all VMware snap-ins for View PowerCLI
Add-PSSnapin *vmware*

# Get all sessions for pool defined in PoolName variable and populate new sessions variable with string data
# Only strings can be accepted for upcoming msg command (VMware hasn’t introduced a message cmdlet)

$sessions = Get-RemoteSession -Pool_id $PoolName | %{$_.DNSName}
$sessionHalf = $sessions.count/2
Write-Host “Here are ALL of the sessions we are logging off:” -ForegroundColor Green
$sessions | Write-Host -ForegroundColor Green

# Populate logoff variable for use later
$Logoffs = Get-RemoteSession -Pool_id $PoolName

# Send first message to first half of sessions in pool using msg.exe using a foreach loop
Write-Host “Sending message to these sessions for pending reboot in $FirstWarningMinutes minutes:” -ForegroundColor Green
$sessions[0 .. $sessionHalf] | Write-Host -ForegroundColor Green
ForEach ($session in $sessions[0 .. $sessionHalf]) {msg /server:$session * “You will be logged off in $FirstWarningMinutes minutes! Please save all work!”}

# Wait for first warning time minus final warning time
Write-Host “Pausing for $WaitTime seconds…” -ForegroundColor Green
Start-Sleep -Seconds $WaitTime

# Send final warning
Write-Host “Sending message to these sessions for pending reboot in $FinalWarning seconds:” -ForegroundColor Green
$sessions[0 .. $sessionHalf] | Write-Host -ForegroundColor Green
ForEach ($session in $sessions[0 .. $sessionHalf]) {msg /server:$session * “You will be logged off in $FinalWarning seconds! Please save all work!”}
Start-Sleep -Seconds $FinalWarning

# Send the logoffs to half the sessions!
Write-Host “Logging off the following sessions!” -ForegroundColor Green
$sessions[0 .. $sessionHalf] | Write-Host -ForegroundColor Green
$Logoffs[0 .. $sessionHalf] | Send-SessionLogoff

# Wait two minutes for desktops to become available, etc. before doing the next half
Write-Host “Waiting two minutes for desktops to become available… there will likely be some errors thrown in a bit since some incoming sessions are already logged off – no big deal.” -ForegroundColor Green
Start-Sleep -Seconds 120

# Send first message to last half of sessions in pool using msg.exe using a foreach loop
Write-Host “Sending message to these sessions for pending reboot in $FirstWarningMinutes minutes:” -ForegroundColor Green
$sessions[$sessionHalf .. $sessions.count] | Write-Host -ForegroundColor Green
ForEach ($session in $sessions[$sessionHalf .. $sessions.count]) {msg /server:$session * “You will be logged off in $FirstWarningMinutes minutes! Please save all work!”}

# Wait for first warning time minus final warning time
Write-Host “Pausing for $WaitTime seconds…” -ForegroundColor Green
Start-Sleep -Seconds $WaitTime

# Send final warning message to last half of sessions in pool using msg.exe using a foreach loop
Write-Host “Sending message to these sessions for pending reboot in $FinalWarning seconds:” -ForegroundColor Green
$sessions[$sessionHalf .. $sessions.count] | Write-Host -ForegroundColor Green
ForEach ($session in $sessions[$sessionHalf .. $sessions.count]) {msg /server:$session * “You will be logged off in $FinalWarning seconds! Please save all work!”}

# Send logoffs to the other half! This will likely have a single error since the median session has already been logged off.
Write-Host “Logging off the following sessions!” -ForegroundColor Green
$sessions[$sessionHalf .. $sessions.count] | Write-Host -ForegroundColor Green
$Logoffs[$LogoffHalf .. $Logoffs.count] | Send-SessionLogoff

Write-Host “Script COMPLETE!” -ForegroundColor Green
# SCRIPT END

Customizing VMware Horizon Connection Server Login Screen

Let’s finally do something on VMware Horizon! This post will cover how to customize your Connection Server login screen, something that is becoming more important as HTML5 access gains popularity. I could not find any documentation on this, so I dug through to find all of the relevant images and files needed. FYI – this was done on a Horizon 7.2 Connection Server. Paths may vary depending on your version.

Here’s the various things we will be customizing and the location to customize them. The path is relevant to C:\Program Files\VMware:

Background: VMware View\Server\broker\webapps\portal\webclient\icons-5622958\bg_image.jpg

Logo on top: VMware View\Server\broker\webapps\portal\webclient\icons-5622958\logo.png

All text in initial login screen*: VMware View\Server\broker\webapps\portal\WEB-INF\classes\com\vmware\vdi\installer\i18n\bundle_en.properties

  • * Requires restart of the VMware Horizon View Web Component service. I recommend just restarting the VMware Horizon View Connection Server service or the entire server.

I also recommend simply renaming the old files to .old so you always have the original file. Don’t forget to clear your cookies or open in incognito, or else the original images get cached!

When editing the bundle_en.properties file, it is pretty self-explanatory on which text to edit. For example, if I change the following lines to:

install.message.first=Here’s where you can customize some text!

install.message.second=Having issues? Contact the help desk at 123-456-7890!

Here’s what it looks after doing that and replacing the logo and background images. Don’t forget that the background image is .jpg and the logo is .png format; also don’t forget to restart the appropriate service, or just restart the Connection Server.

 

If your Connection Servers are behind a load-balancer, (they are, right?) then you can simply place a different background on each Connection Server so it looks like the backgrounds are randomly generated. Cool, huh?

Happy branding!