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

Independent Consultant | Contractor | Microsoft & Citrix Specialist | Desktop Virtualization Specialist at J House Consulting
Jeremy is a highly respected, IT Professional, with over 30 years’ experience in the industry. He is an independent IT consultant providing expertise to enterprise, corporate, higher education and government clients. His skill set, high ethical standards, integrity, morals and attention to detail, coupled with his friendly nature and exceptional design and problem solving skills, makes him one of the most highly respected and sought after Microsoft and Citrix technical resources in Australia. His alignment with industry and vendor best practices puts him amongst the leaders of his field.
Jeremy Saunders
Jeremy Saunders
Jeremy Saunders

Previous post:

Next post: