• Documenting a Citrix XenApp 6.5 Farm with Microsoft PowerShell and Word – Version 4.1

    Whew, Version 4.1 of the XenApp 6.5 script was a lot of work and required a lot of testing.  It is my pleasure to release, after three months of intense testing, Version 4.1.  This article will discuss the new features and fixes.

    The alphabetical list of new features and fixes:

    • Added additional error checking when retrieving Network Interface WMI data
    • Added additional Write-Verbose statements for the AD policy function
    • Added beginning and ending dates for retrieving Configuration Logging data
    • Added four policy settings that are only for AD based Citrix policies
    • Added help text to show the script produces a Word or PDF document
    • Added help text to show the Summary option cannot be used with either the Hardware, Software, StartDate or EndDate parameters
    • Added Parameter sets to support the Summary option
    • Added Summary report option
    • Changed Configuration Logging section to a Word table
    • Changed to using $PSCulture for Word culture setting
    • Don’t abort script if Cover Page is not found
    • Fixed bug where the AD Policy function did not work if there was only one AD policy
    • For applications, move list of servers and worker groups to table
    • For the software inventory add DisplayVersion to the table
    • For Worker Groups, move list of servers and applications to table
    • Function, validStateProp, created by Michael B. Smith to handle “property cannot be found on this object” error on Mobile Experience policy settings
    • If remoting is used, verify that remoting server is not in session-only mode
    • In Appendix B, if the License Server cell is empty replace with the text “Set by policy”
    • Only include Valid hotfixes in the table of installed Citrix hotfixes
    • Removed the Valid column for the Citrix hotfix table
    • Removed the extra blank line between Administrators
    • The XenApp 6.5 Mobility Pack added a new User policy node with three settings
    • Updated for CTX129229 that was updated on 31-Dec-2013

    For some virtual servers, sometimes no NIC information is returned and sometimes NIC information “appears” to be returned but the object has no properties.  I added a check to see if any properties are returned and if not, set the $GotNICs variable to $False.  This prevents that section of the script from displaying the ugly red error for every line of output for the NIC hardware section.

    If( $Nics -eq $Null )
    {
        $GotNics = $False
    }
    Else
    {
        $GotNics = !($Nics.__PROPERTY_COUNT -eq 0)
    }
    

    I had several people tell me that in their large environment that the Configuration Logging (aka History) report adds thousands of pages to the report. I converted this section of the report into a table and added a date range which defaults to the last seven days. Since Citrix provided no help text for showing how to use the dates I provided some in the help text for this script.

    .PARAMETER StartDate
    	Start date, in MM/DD/YYYY HH:MM format, for the Configuration Logging report.
    	Default is today's date minus seven days.
    	If the StartDate is entered as 01/01/2014, the date becomes 01/01/2014 00:00:00.
    .PARAMETER EndDate
    	End date, in MM/DD/YYYY HH:MM format, for the Configuration Logging report.
    	Default is today's date.
    	If the EndDate is entered as 01/01/2014, the date becomes 01/01/2014 00:00:00.
    

    Example using a StartDate of “12/01/2013 00:00” and an EndDate of “12/31/2013 23:59”

    History Report as Table
    History Report as Table

    Instead of four history items per page, now there can be around 25.

    Now that Citrix Active Directory (AD) based policies are processed, there were four AD only computer policy settings I added.

    1. Server Settings\Initial Zone Name
    2. Server Settings\Database Settings\Initial Database Name
    3. Server Settings\Database Settings\Initial Database Server Name
    4. Server Settings\Database Settings\Initial Failover Partner

    A feature that several extremely large organizations wanted was a “Management Report” option.  A normal report in an extremely large organization can be thousands of pages long.  While such a lengthy report is useful to the Citrix Admins, Engineers and Architects, for management such a long and large report is useless.  The new -Summary option will produce a report that only includes things such as Administrator names, Application names, Server names, etc.  It will include no detail, no Configuration Logging (History) report and no Appendix A or B.  Help text was added to explain that the Summary parameter cannot be used with the Hardware, Software, StartDate or EndDate parameters.

    Changing from using $PSUICulture to $PSCulture is for the non US English Word users.  One thing I have found is if you have multiple language packs installed for Word, the default editing language is what sets $PSCulture.  If you have en-US and xx-XX language packs installed AND you want Word and the script to use xx-XX cover pages and table of contents then xx-XX MUST be set as the default editing language in Word.  Otherwise you can enter –CP SomeCoverPageName” as your cover page and the script will tell you that is not a valid (US English) cover page.  With multiple languages installed in Word, all “Building Blocks.dotx” or “Built-In Building Blocks.dotx” files are retrieved in Word language code order.  Usually this means US English (1033) is first in the array and whatever other language is also used is not first.  This keeps the other language’s cover page from being found since only the first template file in the array is used.  Another change made was to not abort the script if the cover page is not found.  The script will continue to run and produce a report but with no cover page or Table of Contents.

    I also fixed a bug, with Michael’s help, where if there was only one AD policy returned the script displayed a message saying there was one policy to process but the policy was not processed.

    For Applications and Worker Groups, the list of servers was moved to a table.  Again, in extremely large environments when the servers are listed in a single column that can add many needless pages to the document.

    Before:

    Applications Before
    Applications Before
    Worker Groups Before
    Worker Groups Before

    After:

    Applications After
    Applications After
    Worker Groups After
    Worker Groups After

    For the Software Inventory, the DisplayVersion has been added to the table.

    Before:

    Software Inventory Before
    Software Inventory Before

    After:

    Software Inventory After
    Software Inventory After

    If the Citrix XenApp 6.5 Mobility Pack is not installed an error was given for each of the three new Mobile Experice policy settings.

    VERBOSE: 01/08/2014 18:34:50:  Started Unfiltered User
    VERBOSE: 01/08/2014 18:34:50:   Computer settings
    VERBOSE: 01/08/2014 18:34:50:    ICA
    VERBOSE: 01/08/2014 18:34:50:    Licensing
    VERBOSE: 01/08/2014 18:34:50:    Power and Capacity Management
    VERBOSE: 01/08/2014 18:34:50:    Server Settings
    VERBOSE: 01/08/2014 18:34:50:    Virtual IP
    VERBOSE: 01/08/2014 18:34:50:    XML Service
    VERBOSE: 01/08/2014 18:34:50:   User settings
    VERBOSE: 01/08/2014 18:34:50:    ICA
    VERBOSE: 01/08/2014 18:34:50:    ICA\Adobe Flash Delivery
    VERBOSE: 01/08/2014 18:34:50:    ICA\Audio
    VERBOSE: 01/08/2014 18:34:50:    ICA\Bandwidth
    VERBOSE: 01/08/2014 18:34:50:    ICA\Desktop UI
    VERBOSE: 01/08/2014 18:34:50:    ICA\File Redirection
    VERBOSE: 01/08/2014 18:34:50:    ICA\Mobile Experience
    Property 'AutoKeyboardPopUp' cannot be found on this object. Make sure that it exists. At C:\webster\XA65_Inventory_V41.ps1:2977 char:20
    + If($Setting. <<<< AutoKeyboardPopUp.State -ne "NotConfigured")
    + CategoryInfo          : InvalidOperation: (.:OperatorToken) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFoundStrict
    Property 'MobileDesktop' cannot be found on this object. Make sure that it exists. At C:\webster\XA65_Inventory_V41.ps1:2981 char:20
    +                             If($Setting. <<<< MobileDesktop.State -ne "NotConfigured")
    + CategoryInfo          : InvalidOperation: (.:OperatorToken) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFoundStrict
    Property 'ComboboxRemoting' cannot be found on this object. Make sure that it exists. At C:\webster\XA65_Inventory_V41.ps1:2985 char:20
    +                             If($Setting. <<<< ComboboxRemoting.State -ne "NotConfigured")
    + CategoryInfo          : InvalidOperation: (.:OperatorToken) [], RuntimeException
    + FullyQualifiedErrorId : PropertyNotFoundStrict
    VERBOSE: 01/08/2014 20:17:16: ICA\Multi-Stream Connections
    VERBOSE: 01/08/2014 18:34:50:    ICA\Port Redirection
    VERBOSE: 01/08/2014 18:34:50:    ICA\Printing
    VERBOSE: 01/08/2014 18:34:50:    ICA\Security
    VERBOSE: 01/08/2014 18:34:50:    ICA\Session limits
    VERBOSE: 01/08/2014 18:34:50:    ICA\Shadowing
    VERBOSE: 01/08/2014 18:34:50:    ICA\Time Zone Control
    VERBOSE: 01/08/2014 18:34:50:    ICA\TWAIN devices
    VERBOSE: 01/08/2014 18:34:50:    ICA\USB devices
    VERBOSE: 01/08/2014 18:34:50:    ICA\Visual Display
    VERBOSE: 01/08/2014 18:34:50:    Server Session Settings
    VERBOSE: 01/08/2014 18:34:50:   Finished Unfiltered User 

    As usual, I had to turn to my PowerShell mentor and guru Michael B. Smith for a solution. Michael provided the following function:

    Function validStateProp( [object] $object, [string] $topLevel, [string] $secondLevel )
    {
        #function created 8-jan-2014 by Michael B. Smith
        If( $object )
        {
             If( ( gm -Name $topLevel -InputObject $object ) )
             {
                 If( ( gm -Name $secondLevel -InputObject $object.$topLevel ) )
                 {
                     Return $true
                 }
             }
         }
         Return $false
    }
    

    And the functions use in the script is done this way:

    # added for the XenApp 6.5 Mobility Pack
    Write-Verbose "$(Get-Date): `t`t`tICA\Mobile Experience"
    If( ( validStateProp $Setting AutoKeyboardPopUp State ) -and ( $Setting.AutoKeyboardPopUp.State -ne "NotConfigured" ) )
    {
         WriteWordLine 0 2 "ICA\Mobile Experience\Automatic keyboard display: " $Setting.AutoKeyboardPopUp.State
    }
    If( ( validStateProp $Setting MobileDesktop State ) -and ( $Setting.MobileDesktop.State -ne "NotConfigured" ) )
    {
         WriteWordLine 0 2 "ICA\Mobile Experience\Launch touch-optimized desktop: " $Setting.MobileDesktop.State
    }
    If( ( validStateProp $Setting ComboboxRemoting State ) -and ( $Setting.ComboboxRemoting.State -ne "NotConfigured" ) )
    {
         WriteWordLine 0 2 "ICA\Mobile Experience\Remote the combo box: " $Setting.ComboboxRemoting.State
    }
    

    And with that quick fix the script will run with no errors if the Mobility Pack is not installed.

    VERBOSE: 01/08/2014 20:17:15:  Started Unfiltered User
    VERBOSE: 01/08/2014 20:17:16:   Computer settings
    VERBOSE: 01/08/2014 20:17:16:    ICA
    VERBOSE: 01/08/2014 20:17:16:    Licensing
    VERBOSE: 01/08/2014 20:17:16:    Power and Capacity Management
    VERBOSE: 01/08/2014 20:17:16:    Server Settings
    VERBOSE: 01/08/2014 20:17:16:    Virtual IP
    VERBOSE: 01/08/2014 20:17:16:    XML Service
    VERBOSE: 01/08/2014 20:17:16:   User settings
    VERBOSE: 01/08/2014 20:17:16:    ICA
    VERBOSE: 01/08/2014 20:17:16:    ICA\Adobe Flash Delivery
    VERBOSE: 01/08/2014 20:17:16:    ICA\Audio
    VERBOSE: 01/08/2014 20:17:16:    ICA\Bandwidth
    VERBOSE: 01/08/2014 20:17:16:    ICA\Desktop UI
    VERBOSE: 01/08/2014 20:17:16:    ICA\File Redirection
    VERBOSE: 01/08/2014 20:17:16:    ICA\Mobile Experience
    VERBOSE: 01/08/2014 20:17:16:    ICA\Multi-Stream Connections
    VERBOSE: 01/08/2014 20:17:16:    ICA\Port Redirection
    VERBOSE: 01/08/2014 20:17:16:    ICA\Printing
    VERBOSE: 01/08/2014 20:17:16:    ICA\Security
    VERBOSE: 01/08/2014 20:17:16:    ICA\Session limits
    VERBOSE: 01/08/2014 20:17:16:    ICA\Shadowing
    VERBOSE: 01/08/2014 20:17:16:    ICA\Time Zone Control
    VERBOSE: 01/08/2014 20:17:16:    ICA\TWAIN devices
    VERBOSE: 01/08/2014 20:17:16:    ICA\USB devices
    VERBOSE: 01/08/2014 20:17:16:    ICA\Visual Display
    VERBOSE: 01/08/2014 20:17:16:    Server Session Settings
    VERBOSE: 01/08/2014 20:17:16:   Finished Unfiltered User
    VERBOSE: 01/08/2014 20:17:16:
    VERBOSE: 01/08/2014 20:17:16: Finished Processing Citrix IMA Policies
    

    If Remoting was used, I was not validating that the XenApp server used for Remoting was a Controller mode server. This caused the script to pause about 60 seconds for every cmdlet used and then give an ugly red error for every cmdlet.

    When configuring a XenApp 6.5 server during initial installation, you can specify a License Server or set the License Server to be set via a policy (IMA or AD).  If the License Server is set via policy, the XenApp server will show no License Server configured when using the Get-XAServer cmdlet.  In Appendix B, if the License Server cell is empty replace with the text “Set by policy”.

    Before:

    Appendix B Before
    Appendix B Before

    After:

    Appendix B After
    Appendix B After

    Several changes were made to the latest revision of CTX129229.  Citrix finally added XenApp 6.5 HRP3 and removed/reorganized the recommended list of Microsoft hotfixes.  If XenApp 6.5 HRP2 or HRP3 are installed, there are still no recommended Citrix updates.  Citrix removed many superseded Microsoft hotfixes.  This section of the report has been modified to include all the changes Citrix made.  For the list of installed Citrix hotfixes, only the valid hotfixes are listed.  If a XenApp 6.5 server was installed and then HRP1, then HRP2 and then HRP3 installed the list of installed Citrix hotfixes was extremely long and most of the hotfixes had been superseded.  Because only valid hotfixes are now listed, the Valid column was removed from the table.

    I have already been given many suggestions for Version 4.2 of this script the main one being able to include only the sections needed.  For example, producing a report for only Applications and Servers or only for Policies.  I will be taking a break from the XenApp scripts so I can complete the XenDesktop 7 and hopefully the XenDesktop 5 scripts.

    NOTE: This script is continually updated.  You can always find the most current version by going to https://carlwebster.com/where-to-get-copies-of-the-documentation-scripts/

    Thanks

    Webster







    About Carl Webster

    Webster is a Sr. Solutions Architect for Choice Solutions, LLC and specializes in Citrix, Active Directory and Technical Documentation. Webster has been working with Citrix products for many years starting with Multi-User OS/2 in 1990.

    View all posts by Carl Webster

    4 Responses to “Documenting a Citrix XenApp 6.5 Farm with Microsoft PowerShell and Word – Version 4.1”

    1. Girdhar Says:

      Hi carl,

      Could you please provide me a powershell script that provide me the complete farm inventory including application published with groups/users

      Reply

    2. Sam Says:

      Hello Carl,
      Trying to document my farm using your script and getting the error below. Can you kindly shed some light on what I am doing wrong please.

      Windows PowerShell
      Copyright (C) 2009 Microsoft Corporation. All rights reserved.

      [EM1TCRA332] C:\Users\okahasa-adm> cd\
      [EM1TCRA332] C:\> cd psscripts
      [EM1TCRA332] C:\psscripts> .\XA65_Inventory_V41.ps1
      Loading Windows PowerShell snap-in: Citrix.Common.Commands
      Loading Windows PowerShell snap-in: Citrix.XenApp.Commands
      You cannot call a method on a null-valued expression.
      At C:\psscripts\XA65_Inventory_V41.ps1:6016 char:50
      + $InstallDate = $hotfix.InstalledOn.ToString <<<< ()
      + CategoryInfo : InvalidOperation: (ToString:String) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull

      You cannot call a method on a null-valued expression.
      At C:\psscripts\XA65_Inventory_V41.ps1:6016 char:50
      + $InstallDate = $hotfix.InstalledOn.ToString <<<< ()
      + CategoryInfo : InvalidOperation: (ToString:String) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull

      You cannot call a method on a null-valued expression.
      At C:\psscripts\XA65_Inventory_V41.ps1:6016 char:50
      + $InstallDate = $hotfix.InstalledOn.ToString <<<< ()
      + CategoryInfo : InvalidOperation: (ToString:String) [], RuntimeException
      + FullyQualifiedErrorId : InvokeMethodOnNull

      Reply

    Leave a Reply