Place a XenApp Server in and out of service the easy way

by Jeremy Saunders on September 8, 2008

The new theory for placing a server off-line is to apply an “Out of service” load evaluator instead of disabling logons. The “Out of service” load evaluator consists of an empty Scheduling rule. The issue with this theory is that if you automate the move of a server into an “Out of service” load evaluator for maintenance, reboots, etc, then how do you know which load evaluator to move it back into when it’s ready to be placed back into production? I guess most would hard code this, or reference it from an ini file, etc, but that requires too much maintenance, as it can be difficult to manage in the larger farms that make use of different load evaluators across different hardware and load managed groups. So I enhanced the original version of this script to address this exact problem. It will read the existing load evaluator and write it against a registry value called PreviousLoadEvaluator under the HKLM\SOFTWARE\Citrix key. Then you can easily re-run this script with certain parameters to set the load evaluator back to what it was previously using. A simple concept that works very well.

For Example:

To move a server into the “Out of service” load evaluator, run…
cscript.exe AttachLE.vbs “Out of service”

To move a server back into its previous load evaluator, run…
cscript.exe AttachLE.vbs SetPrevious

Enjoy!

'
' Script name: AttachLE.vbs
'
' Purpose: Attaches a load evaluator to a Citrix server.
'
' Syntax: AttachLE lename
'
'    lename         The load evaluator's name (case sensitive)
'
'---------------------------------------------------------------------------------------
'
' Based on a script written by Frank-Peter Schultze (http://www.fpschultze.de)
'
' Version 1.0 - Written by Jeremy@jhouseconsulting on 9th July 2008.
' Version 1.1 - Updated by Jeremy@jhouseconsulting on 1st September 2008.
'
' For Example:
'
' To move a server into the "Out of service" load evaluator, run...
'   cscript.exe AttachLE.vbs "Out of service"
'
' To move a server back into its previous load evaluator, run...
'   cscript.exe AttachLE.vbs SetPrevious

' More Examples:
'
' To move a server into the Default load evaluator run the following command...
' cscript.exe AttachLE.vbs Default
'
' To move a server into the Advanced load evaluator run the following command...
' cscript.exe AttachLE.vbs Advanced
'
'---------------------------------------------------------------------------------------

Option Explicit

' Note that the built-in Default load evaluator is MFDefaultLE, and the Advanced load evaluator is LMSDefaultLE.
Const CTX_LE_DEFAULT  = "MFDefaultLE"
Const CTX_LE_ADVANCED = "LMSDefaultLE"

Dim strCitrixServer : strCitrixServer = ""
Dim strLEName       : strLEName       = ""
Dim WshNetwork

Call GetArgs(strLEName)

Set WshNetwork = WScript.CreateObject("WScript.Network")
strCitrixServer = UCase(WshNetwork.ComputerName)

IF strLEName = "setprevious" Then
  Call SetPreviousLE(strCitrixServer)
Else
  Call GetCurrentLE(strCitrixServer)
  Call AttachLEToServer(strCitrixServer, strLEName)
End If

Set WshNetwork = Nothing
wscript.quit(0)

Sub SetPreviousLE(strCitrixServer)

  Dim WshShell, strLEName, strKey, strValue

  Set WshShell = CreateObject("WScript.Shell")

  strKey = "HKLM\SOFTWARE\Citrix"
  strValue = "PreviousLoadEvaluator"

  If RegValueExists(strKey & "\" & strValue) Then
    strLEName = WshShell.RegRead(strKey & "\" & strValue)
    wscript.echo "The previous load evaluator was " & chr(34) & strLEName & chr(34)
  Else
    wscript.echo "The previous load evaluator was not set. This script will exit."
    Set WshShell = Nothing
    Exit Sub
  End If

  Select Case LCase(strLEName)
    Case "default"
      strLEName = CTX_LE_DEFAULT
    Case "advanced"
      strLEName = CTX_LE_ADVANCED
    Case Else
  End Select

  Call AttachLEToServer(strCitrixServer, strLEName)
  WshShell.RegDelete(strKey & "\" & strValue)

  Set WshShell = Nothing
End Sub

Sub AttachLEToServer(strCitrixServer, strLEName)

  Dim objFarm

  On Error Resume Next
  Set objFarm = WScript.CreateObject("MetaFrameCOM.MetaFrameLoadEvaluator")
  On Error GoTo 0
  If IsObject(objFarm) Then
    objFarm.LEName = strLEName
    objFarm.LoadData(True)
    objFarm.AttachToServerByName False, strCitrixServer
    objFarm.SaveData()
    Set objFarm = Nothing
    Select Case strLEName
      Case "MFDefaultLE"
        strLEName = "Default"
      Case "LMSDefaultLE"
        strLEName = "Advanced"
      Case Else
    End Select
    wscript.echo "The load evaluator for " & strCitrixServer & " has now been set to " & chr(34) & strLEName & chr(34)
  Else
    WScript.Echo "Can not create MFCOM object."
  End If
  Set objFarm = Nothing
End Sub

Sub GetCurrentLE(strCitrixServer)

  Dim WshShell, ServerObj, sCurrentLE, strCurrentValue, strKey, strValue

  Const MetaFrameWinSrvObject = 6

  Set WshShell = CreateObject("WScript.Shell")
  Set ServerObj = CreateObject("MetaframeCom.MetaFrameServer")

  ServerObj.Initialize MetaFrameWinSrvObject, strCitrixServer

  Set sCurrentLE=ServerObj.AttachedLE
  sCurrentLE.Loaddata(True)

  strCurrentValue=sCurrentLE.LEName

  Select Case strCurrentValue
    Case "MFDefaultLE"
      strCurrentValue = "Default"
    Case "LMSDefaultLE"
      strCurrentValue = "Advanced"
    Case Else
  End Select

  strKey = "HKLM\SOFTWARE\Citrix"
  strValue = "PreviousLoadEvaluator"

  WshShell.RegWrite strKey & "\" & strValue, StrCurrentValue

  wscript.echo strCitrixServer & " is currently using the " & chr(34) & StrCurrentValue & chr(34) & " load evaluator"

  Set WshShell = Nothing
  Set ServerObj = Nothing
End Sub

Sub GetArgs(ByRef strLEName)
  Dim objArgs, strTmp
  Set objArgs = WScript.Arguments
  If (objArgs.Count = 1) Then
    strTmp = objArgs.Item(0)
    Select Case LCase(strTmp)
      Case "default"
        strLEName = CTX_LE_DEFAULT
      Case "advanced"
        strLEName = CTX_LE_ADVANCED
      Case "setprevious"
        strLEName = "setprevious"
      Case Else
        strLEName = strTmp
    End Select
  Else
    Call Usage(True)
    Exit Sub
  End If
End Sub

Sub Usage(blnQuit)
  WScript.Echo "Attaches a load evaluator to a Citrix server." & VbCrlf & VbCrlf & _
               "Usage: " & WScript.ScriptName & " ''<lename>''" & VbCrlf & VbCrlf & _
               "Where lename is the load evaluator's name. It IS case sensitive" & VbCrlf & _
               "and MUST be surrounded with double quotes if it contains spaces." & VbCrlf
  If blnQuit Then WScript.Quit(0)
End Sub

Function RegValueExists(sRegValue)
' Returns True or False based of the existence of a registry value.
  Dim oShell, RegReadReturn
  Set oShell = CreateObject("WScript.Shell")
  RegValueExists = True  ' init value
  On Error Resume Next
  RegReadReturn = oShell.RegRead(sRegValue)
  If Err.Number <> 0 Then
    RegValueExists = False
  End if
  On Error Goto 0
  Set oShell = Nothing
End Function
Jeremy Saunders

Jeremy Saunders

Technical Architect | DevOps Evangelist | Software Developer | Microsoft, NVIDIA, Citrix and Desktop Virtualisation (VDI) Specialist/Expert | Rapper | Improvisor | Comedian | Property Investor | Kayaking enthusiast at J House Consulting
Jeremy Saunders is the Problem Terminator. He is a highly respected IT Professional with over 35 years’ experience in the industry. Using his exceptional design and problem solving skills with precise methodologies applied at both technical and business levels he is always focused on achieving the best business outcomes. He worked as an independent consultant until September 2017, when he took up a full time role at BHP, one of the largest and most innovative global mining companies. With a diverse skill set, high ethical standards, and attention to detail, coupled with a friendly nature and great sense of humour, Jeremy aligns to industry and vendor best practices, which puts him amongst the leaders of his field. He is intensely passionate about solving technology problems for his organisation, their customers and the tech community, to improve the user experience, reliability and operational support. Views and IP shared on this site belong to Jeremy.
Jeremy Saunders
Jeremy Saunders

Previous post:

Next post: