XA65 SummaryReportV2
XA65 SummaryReportV2
XA65 SummaryReportV2
<#
.SYNOPSIS
Creates a Summary Report of the inventory of a Citrix XenApp 6.5 farm using
Microsoft Word.
.DESCRIPTION
Creates a Summary Report of the inventory of a Citrix XenApp 6.5 farm using
Microsoft Word.
Includes support for the following language versions of Microsoft Word:
Catalan
Chinese
Danish
Dutch
English
Finnish
French
German
Norwegian
Portuguese
Spanish
Swedish
.EXAMPLE
PS C:\PSScript > .\XA65_SummaryReport.ps1
.INPUTS
None. You cannot pipe objects to this script.
.OUTPUTS
No objects are output from this script. This script creates a Word document.
.NOTES
NAME: XA65_SummaryReportV2.ps1
VERSION: 2.00
AUTHOR: Carl Webster
LASTEDIT: February 10, 2018
#>
Set-StrictMode -Version 2
$hash = @{}
# http://www.thedoctools.com/index.php?
show=wt_style_names_english_danish_german_french
$wdStyleHeading1 = -2
$wdStyleHeading2 = -3
$wdStyleHeading3 = -4
$wdStyleHeading4 = -5
$wdStyleNoSpacing = -158
$myHash = $hash
$myHash.Word_NoSpacing = $wdStyleNoSpacing
$myHash.Word_Heading1 = $wdStyleheading1
$myHash.Word_Heading2 = $wdStyleheading2
$myHash.Word_Heading3 = $wdStyleheading3
$myHash.Word_Heading4 = $wdStyleheading4
Function CheckWordPrereq
{
If((Test-Path REGISTRY::HKEY_CLASSES_ROOT\Word.Application) -eq $False)
{
Write-Host "This script directly outputs to Microsoft Word, please
install Microsoft Word"
exit
}
#http://stackoverflow.com/questions/5648931/test-if-registry-value-exists
# This Function just gets $True or $False
Function Test-RegistryValue($path, $name)
{
$key = Get-Item -LiteralPath $path -EA 0
$key -and $Null -ne $key.GetValue($name, $Null)
}
Function WriteWordLine
#Function created by Ryan Revord
#@rsrevord on Twitter
#Function created to make output to Word easy in this script
#updated 27-Mar-2014 to include font name, font size, italics and bold options
{
Param([int]$style=0,
[int]$tabs = 0,
[string]$name = '',
[string]$value = '',
[string]$fontName=$Null,
[int]$fontSize=0,
[bool]$italics=$False,
[bool]$boldface=$False,
[Switch]$nonewline)
#build # of tabs
While($tabs -gt 0)
{
$output += "`t"; $tabs--;
}
If(![String]::IsNullOrEmpty($fontName))
{
$Selection.Font.name = $fontName
}
If($fontSize -ne 0)
{
$Selection.Font.size = $fontSize
}
Function Check-LoadedModule
#Function created by Jeff Wouters
#@JeffWouters on Twitter
#modified by Michael B. Smith to handle when the module doesn't exist on server
#modified by @andyjmorgan
#bug fixed by @schose
#bug fixed by Peter Bosen
#This Function handles all three scenarios:
#
# 1. Module is already imported into current session
# 2. Module is not already imported into current session, it does exists on the
server and is imported
# 3. Module does not exist on the server
{
Param([parameter(Mandatory = $True)][alias("Module")][string]$ModuleName)
#$LoadedModules = Get-Module | Select Name
#following line changed at the recommendation of @andyjmorgan
$LoadedModules = Get-Module |% { $_.Name.ToString() }
#bug reported on 21-JAN-2013 by @schose
#the following line did not work if the citrix.grouppolicy.commands.psm1
module
#was manually loaded from a non Default folder
#$ModuleFound = (!$LoadedModules -like "*$ModuleName*")
Function Check-NeededPSSnapins
{
Param([parameter(Mandatory = $True)][alias("Snapin")][string[]]$Snapins)
#Function specifics
$MissingSnapins = @()
[bool]$FoundMissingSnapin = $False
$LoadedSnapins = @()
$RegisteredSnapins = @()
ForEach($Snapin in $Snapins)
{
#check if the snapin is loaded
If(!($LoadedSnapins -like $snapin))
{
#Check if the snapin is missing
If(!($RegisteredSnapins -like $Snapin))
{
#set the flag if it's not already
If(!($FoundMissingSnapin))
{
$FoundMissingSnapin = $True
}
#add the entry to the list
$MissingSnapins += $Snapin
}
Else
{
#Snapin is registered, but not loaded, loading it now:
Write-Host "Loading Windows PowerShell snap-in: $snapin"
Add-PSSnapin -Name $snapin -EA 0
}
}
}
If($FoundMissingSnapin)
{
Write-Warning "Missing Windows PowerShell snap-ins Detected:"
$missingSnapins | % {Write-Warning "($_)"}
return $False
}
Else
{
Return $True
}
}
Function ProcessCitrixPolicies
{
Param([string]$xDriveName)
}
Else
{
Write-Warning "Citrix Policy information could not be retrieved."
}
$Policies = $Null
If($xDriveName -ne "")
{
Write-Host "$(Get-Date): `tRemoving ADGpoDrv PSDrive"
Remove-PSDrive ADGpoDrv -EA 0
Write-Host "$(Get-Date): "
}
}
Function GetCtxGPOsInAD
{
#thanks to the Citrix Engineering Team for pointers and for Michael B. Smith
for creating the function
$root = [ADSI]"LDAP://RootDSE"
$domainNC = $root.defaultNamingContext.ToString()
$root = $null
$xArray = @()
Function AbortScript
{
$Script:Word.quit()
Write-Verbose "$(Get-Date): System Cleanup"
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Script:Word) |
Out-Null
If(Test-Path variable:global:word)
{
Remove-Variable -Name word -Scope Global 4>$Null
}
[gc]::collect()
[gc]::WaitForPendingFinalizers()
Write-Verbose "$(Get-Date): Script has been aborted"
$ErrorActionPreference = $SaveEAPreference
Exit
}
#Script begins
If(!(Check-NeededPSSnapins "Citrix.Common.Commands","Citrix.XenApp.Commands"))
{
#We're missing Citrix Snapins that we need
Write-Error "Missing Citrix PowerShell Snap-ins Detected, check the console
above for more information. Are you sure you are running this script on a XenApp
6.5 Server? Script will now close."
Exit
}
CheckWordPreReq
[bool]$Remoting = $False
$RemoteXAServer = Get-XADefaultComputerName -EA 0
If(![String]::IsNullOrEmpty($RemoteXAServer))
{
$Remoting = $True
}
If($Remoting)
{
Write-Host "$(Get-Date): Remoting is enabled to XenApp server
$RemoteXAServer"
}
Else
{
Write-Host "$(Get-Date): Remoting is not being used"
#now need to make sure the script is not being run on a session-only host
$ServerName = (Get-Childitem env:computername).value
$Server = Get-XAServer -ServerName $ServerName -EA 0
If($Server.ElectionPreference -eq "WorkerMode")
{
Write-Warning "This script cannot be run on a Session-only Host Server
if Remoting is not enabled."
Write-Warning "Use Set-XADefaultComputerName XA65ControllerServerName
or run the script on a controller."
Write-Error "Script cannot continue. See messages above."
Exit
}
}
If($?)
{
Write-Host "$(Get-Date): Verify farm version"
#first check to make sure this is a XenApp 6.5 farm
If($Farm.ServerVersion.ToString().SubString(0,3) -eq "6.5")
{
#this is a XenApp 6.5 farm, script can proceed
}
Else
{
#this is not a XenApp 6.5 farm, script cannot proceed
Write-Warning "This script is designed for XenApp 6.5 and should not be
run on previous versions of XenApp"
Return 1
}
[string]$FarmName = $farm.FarmName
[string]$filename1 = "$($pwd.path)\Summary Report for $($FarmName).docx"
}
Else
{
Write-Warning "Farm information could not be retrieved"
If($Remoting)
{
Write-Error "A remote connection to $RemoteXAServer could not be
established. Script cannot continue."
}
Else
{
Write-Error "Farm information could not be retrieved. Script cannot
continue."
}
Exit
}
$farm = $Null
[int]$WordVersion = [int]$Word.Version
If($WordVersion -eq $wdWord2016)
{
$WordProduct = "Word 2016"
}
ElseIf($WordVersion -eq $wdWord2013)
{
$WordProduct = "Word 2013"
}
ElseIf($WordVersion -eq $wdWord2010)
{
$WordProduct = "Word 2010"
}
ElseIf($WordVersion -eq $wdWord2007)
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tMicrosoft Word 2007 is no longer
supported.`n`n`t`tScript will end.`n`n"
AbortScript
}
Else
{
$ErrorActionPreference = $SaveEAPreference
Write-Error "`n`n`t`tYou are running an untested or unsupported version of
Microsoft Word.`n`n`t`tScript will end.`n`n`t`tPlease send info on your version of
Word to webster@carlwebster.com`n`n"
AbortScript
}
$Selection = $Word.Selection
If($Selection -eq $Null)
{
Write-Host "$(Get-Date): "
Write-Error "An unknown error happened selecting the entire Word document for
default formatting options. Script cannot continue."
AbortScript
}
#set Default tab stops to 1/2 inch (this line is not from Jeff Hicks)
#36 = .50"
$Word.ActiveDocument.DefaultTabStop = 36
#Disable Spell and Grammar Check to resolve issue and improve performance (from Pat
Coughlin)
Write-Host "$(Get-Date): Disable grammar and spell checking"
$Word.Options.CheckGrammarAsYouType = $False
$Word.Options.CheckSpellingAsYouType = $False
If($?)
{
If($ConfigurationLogging.LoggingEnabled)
{
$ConfigLog = $True
}
}
Else
{
Write-Warning "Configuration Logging could not be retrieved"
}
$ConfigurationLogging = $Null
Write-Host "$(Get-Date): Finished Configuration Logging"
Write-Host "$(Get-Date): "
If($?)
{
ForEach($Administrator in $Administrators)
{
Write-Host "$(Get-Date): `t`tProcessing administrator $
($Administrator.AdministratorName)"
Switch ($Administrator.AdministratorType)
{
"Unknown" {}
"Full" {$TotalFullAdmins++}
"ViewOnly" {$TotalViewAdmins++}
"Custom" {$TotalCustomAdmins++}
Default {}
}
}
}
Else
{
Write-Warning "Administrator information could not be retrieved"
}
$Administrators = $Null
Write-Host "$(Get-Date): Finished Processing Administrators"
Write-Host "$(Get-Date): "
ForEach($Application in $Applications)
{
Write-Host "$(Get-Date): `t`tProcessing application $
($Application.BrowserName)"
#type properties
Switch ($Application.ApplicationType)
{
"Unknown" {}
"ServerInstalled" {$TotalPublishedApps++}
"ServerDesktop" {$TotalPublishedDesktops++}
"Content" {$TotalPublishedContent++}
"StreamedToServer" {$TotalStreamedApps++}
"StreamedToClient" {$TotalStreamedApps++}
"StreamedToClientOrInstalled" {$TotalStreamedApps++}
"StreamedToClientOrStreamedToServer" {$TotalStreamedApps++}
Default {}
}
}
}
ElseIf($Applications -eq $Null)
{
Write-Host "$(Get-Date): There are no Applications published"
}
Else
{
Write-Warning "Application information could not be retrieved. Do you have
any published applications?"
}
$Applications = $Null
Write-Host "$(Get-Date): Finished Processing Applications"
Write-Host "$(Get-Date): "
[int]$TotalConfigLogItems = 0
#load evaluators
Write-Host "$(Get-Date): Processing Load Evaluators"
[int]$TotalLoadEvaluators = 0
If($?)
{
ForEach($LoadEvaluator in $LoadEvaluators)
{
$TotalLoadEvaluators++
Write-Host "$(Get-Date): `t`tProcessing Load Evaluator $
($LoadEvaluator.LoadEvaluatorName)"
}
}
Else
{
Write-Warning "Load Evaluator information could not be retrieved"
}
$LoadEvaluators = $Null
Write-Host "$(Get-Date): Finished Processing Load Evaluators"
Write-Host "$(Get-Date): "
#servers
Write-Host "$(Get-Date): Processing Servers"
[int]$TotalControllers = 0
[int]$TotalWorkers = 0
If($?)
{
ForEach($server in $servers)
{
Write-Host "$(Get-Date): `t`tProcessing server $($server.ServerName)"
Switch ($server.ElectionPreference)
{
"Unknown" {}
"MostPreferred" {$TotalControllers++}
"Preferred" {$TotalControllers++}
"DefaultPreference" {$TotalControllers++}
"NotPreferred" {$TotalControllers++}
"WorkerMode" {$TotalWorkers++}
Default {}
}
}
}
Else
{
Write-Warning "Server information could not be retrieved"
}
$servers = $Null
Write-Host "$(Get-Date): Finished Processing Servers"
Write-Host "$(Get-Date): "
#worker groups
Write-Host "$(Get-Date): Processing Worker Groups"
[int]$TotalWGByServerName = 0
[int]$TotalWGByServerGroup = 0
[int]$TotalWGByOU = 0
[int]$Global:TotalComputerPolicies = 0
[int]$Global:TotalUserPolicies = 0
[int]$Global:TotalIMAPolicies = 0
[int]$Global:TotalADPolicies = 0
[int]$Global:TotalADPoliciesNotProcessed = 0
#if remoting is enabled, the citrix.grouppolicy.commands module does not work with
remoting so skip it
If($Remoting)
{
Write-Warning "Remoting is enabled."
Write-Warning "The Citrix.GroupPolicy.Commands module does not work with
Remoting."
Write-Warning "Citrix Policy documentation will not take place."
}
Else
{
#make sure Citrix.GroupPolicy.Commands module is loaded
If(!(Check-LoadedModule "Citrix.GroupPolicy.Commands"))
{
Write-Warning "The Citrix Group Policy module
Citrix.GroupPolicy.Commands.psm1 could not be loaded `nPlease see
http://tinyurl.com/XenApp6PSPolicies `nCitrix Policy documentation will not take
place"
Write-Host "$(Get-Date): "
}
Else
{
Write-Host "$(Get-Date): Processing Citrix IMA Policies"
Write-Host "$(Get-Date): `tRetrieving IMA Farm Policies"
ProcessCitrixPolicies
Write-Host "$(Get-Date): Finished Processing Citrix IMA Policies"
Write-Host "$(Get-Date): "
ForEach($CtxGPO in $CtxGPOArray)
{
Write-Host "$(Get-Date): Creating ADGpoDrv PSDrive"
New-PSDrive -Name ADGpoDrv -PSProvider CitrixGroupPolicy
-Root \ -DomainGpo $($CtxGPO) -Scope "Global" | out-null
If(Get-PSDrive ADGpoDrv -EA 0)
{
ProcessCitrixPolicies "ADGpoDrv"
}
Else
{
$Global:TotalADPoliciesNotProcessed++
}
}
#summary page
Write-Host "$(Get-Date): Create Summary Report"
WriteWordLine 1 0 "Summary Report for the $($FarmName) Farm"
Write-Host "$(Get-Date): `tAdd administrator summary info"
WriteWordLine 0 0 "Administrators"
WriteWordLine 0 1 "Total Full Administrators`t: " $TotalFullAdmins
WriteWordLine 0 1 "Total View Administrators`t: " $TotalViewAdmins
WriteWordLine 0 1 "Total Custom Administrators`t: " $TotalCustomAdmins
WriteWordLine 0 2 "Total Administrators`t: " ($TotalFullAdmins + $TotalViewAdmins +
$TotalCustomAdmins)
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd application summary info"
WriteWordLine 0 0 "Applications"
WriteWordLine 0 1 "Total Published Applications`t: " $TotalPublishedApps
WriteWordLine 0 1 "Total Published Content`t`t: " $TotalPublishedContent
WriteWordLine 0 1 "Total Published Desktops`t: " $TotalPublishedDesktops
WriteWordLine 0 1 "Total Streamed Applications`t: " $TotalStreamedApps
WriteWordLine 0 2 "Total Applications`t: " ($TotalPublishedApps +
$TotalPublishedContent + $TotalPublishedDesktops + $TotalStreamedApps)
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd configuration logging summary info"
WriteWordLine 0 0 "Configuration Logging"
WriteWordLine 0 1 "Total Config Log Items`t`t: " $TotalConfigLogItems
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd load balancing policies summary info"
WriteWordLine 0 0 "Load Balancing Policies"
WriteWordLine 0 1 "Total Load Balancing Policies`t: " $TotalLBPolicies
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd load evaluator summary info"
WriteWordLine 0 0 "Load Evaluators"
WriteWordLine 0 1 "Total Load Evaluators`t`t: " $TotalLoadEvaluators
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd server summary info"
WriteWordLine 0 0 "Servers"
WriteWordLine 0 1 "Total Controllers`t`t: " $TotalControllers
WriteWordLine 0 1 "Total Workers`t`t`t: " $TotalWorkers
WriteWordLine 0 2 "Total Servers`t`t: " ($TotalControllers + $TotalWorkers)
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd worker group summary info"
WriteWordLine 0 0 "Worker Groups"
WriteWordLine 0 1 "Total WGs by Server Name`t: " $TotalWGByServerName
WriteWordLine 0 1 "Total WGs by Server Group`t: " $TotalWGByServerGroup
WriteWordLine 0 1 "Total WGs by AD Container`t: " $TotalWGByOU
WriteWordLine 0 2 "Total Worker Groups`t: " ($TotalWGByServerName +
$TotalWGByServerGroup + $TotalWGByOU)
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd zone summary info"
WriteWordLine 0 0 "Zones"
WriteWordLine 0 1 "Total Zones`t`t`t: " $TotalZones
WriteWordLine 0 0 ""
Write-Host "$(Get-Date): `tAdd policy summary info"
WriteWordLine 0 0 "Policies"
WriteWordLine 0 1 "Total Computer Policies`t`t: " $Global:TotalComputerPolicies
WriteWordLine 0 1 "Total User Policies`t`t: " $Global:TotalUserPolicies
WriteWordLine 0 2 "Total Policies`t`t: " ($Global:TotalComputerPolicies +
$Global:TotalUserPolicies)
WriteWordLine 0 0 ""
WriteWordLine 0 1 "IMA Policies`t`t`t: " $Global:TotalIMAPolicies
WriteWordLine 0 1 "Citrix AD Policies Processed`t: $($Global:TotalADPolicies)`t(AD
Policies can contain multiple Citrix policies)"
WriteWordLine 0 1 "Citrix AD Policies not Processed`t: "
$Global:TotalADPoliciesNotProcessed
Write-Host "$(Get-Date): Finished Create Summary Page"
Write-Host "$(Get-Date): "
Write-Host "$(Get-Date): Finishing up Word document"