Pawel Serwan Blog

Citrix, Microsoft and other stuff

[Powershell] Citrix XenApp Monitoring Script ver. 2.1

10 Comments

Monitoring

I got few questions regarding my Citrix XenApp monitoring script written in Powershell. I’ve decided to share with you it’s second better and improved version which has additional conditions on checking if really Citrix ICA connections was launched properly and your Citrix application is available for interaction with user. What is also improved is the overall time needed for the script to run. Right now all logons happen simultaneously thanks to which the script finishes below 2 minutes ( I tested that for about 20 servers). So you have now possibility to schedule a task that will be running more frequent and you will be able to better check health of your Citrix XenApp environment.

Before I share my script please check some prerequisites that are required by a script to execute properly:

1. You must have Citrix Receiver for Windows installed.
2. This script will only work in the x86 version of Powershell. You run it manually like this: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -file “path to the script”
3. You would schedule it like this:
Program/Script: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
Arguments: -ExecutionPolicy Bypass -file “path to the script”
4. You have to create a service account to be used by the scheduled task
5. To allow task to interact with the desktop you have to configure task to run only when the user is logged in
6. You have to set autologon in your Windows desktop or server according to: https://support.microsoft.com/en-us/kb/310584
7. You have to download PSTerminalServices Powershell module from: http://blogs.microsoft.co.il/scriptfanatic/2010/02/22/psterminalservices-powershell-module-for-terminal-services/
8. After that you have to place it under %SystemRoot%\syswow64\WindowsPowerShell\v1.0\Modules
9. In order for the script to interact with the ICO, it requires the following to be set in the registry:
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM
AllowLiveMonitoring REG_DWORD 1
AllowSimulationAPI REG_DWORD 1

And of course I would like to underline that original script was written by Stan Czerno and is available under below link:

http://www.czerno.com/blog/post/2014/06/11/powershell-script-to-launch-a-published-application-from-one-or-more-xenapp-servers

Let me know if you would have any questions or comments.

!!! There is a problem with Powershell code in WordPress. Please check in Windows Powershell ISE editor if everything is OK!!!

# This script launches a specified Published Application for one or more XenApp Servers.
# You can use to this as a Test to make sure the server is actually launching Published Applications
# It will also log the time is takes to logon.
# It can be run by Scheduled Task to check availability of the Citrix XenApp servers.

# You must have Citrix Receiver for Windows installed.

# This script will only work in the x86 version of Powershell

# You run it manually like this: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -file "path to script"

# You would schedule it like this:
# Program/Script: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
# Arguments: -ExecutionPolicy Bypass -file C:\XenAppMonitoringScript\Check-XAAppLaunchReport.ps1
# You have to create a service account to be used by the scheduled task
# To allow task to interact with the desktop you have to configure task to run only when the user is logged in
# You have to set autologon in your Windows desktop or server according to: https://support.microsoft.com/en-us/kb/310584

#You have to download PSTerminalServices Powershell module from: http://blogs.microsoft.co.il/scriptfanatic/2010/02/22/psterminalservices-powershell-module-for-terminal-services/
# After that you have to place it under %SystemRoot%\syswow64\WindowsPowerShell\v1.0\Modules

# In order for the script to interact with the ICO, it requires the following to be set in the registry:
# HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM
# AllowLiveMonitoring REG_DWORD 1
# AllowSimulationAPI REG_DWORD 1

# Parts of the script comes from: http://www.czerno.com/blog/post/2014/06/11/powershell-script-to-launch-a-published-application-from-one-or-more-xenapp-servers

# Created by: Paweł Serwan
# Date: 25.03.2015
# Version: 2.1


## ============================================================ ##
##                      User Variables                          ##
## ============================================================ ##

#Import Citrix modules from Citrix SDK
#Add-PSSnapin Citrix*

# Publish Application Name to launch
$pubapp = "YOUR APP NAME"

# List of Servers to test, one or more can be listed
# If more than one, use this format: "Server1","Server2","Server3"
# If all servers in the farm should be tested: 
# $XAServers = Get-XAServer | Select ServerName
$XAServers = Import-Csv "PATH TO THE CSV FILE WITH LIST OF SERVERS"
#CSV file should look like:
#ServerName
#Server1
#Server2

# User name
$user = "USERNAME"

# User password
$passwd = "PASSWORD"

# Domain Name
$domain = "YOUR DOMAIN"

# E-mail settings 
# If $emailFrom, $emailTo or $smtpServer are blank, no email will be sent
# Define multiple email addresses like "email@domain.com,email2@domain.com"
$emailFrom     = "MAIL_FROM@MYDOMAIN.COM"
$emailTo       = "MAIL_TO@MYDOMAIN.COM"
# If not using a CC address, leave the value blank
#$emailCC       = "mailCC@mydomain.com" 
$smtpServer    = "SMTP.MYDOMAIN.COM"

# The variable below sets how often to send an email if no "new" alerts are detected.
# For example, Server 1 is having issues, an email is sent. If the test is scheduled to run again in 15 minutes
# you may want to set the lag time to something greater than 15 minutes so you are not constantly sent emails
# about the same issue.
# If an existing alert still exists, it will not be sent again until this lag time is reached.
# Be sure to align this with how often you schedule the task.
# The variable is set in seconds, 7200 seconds (2 hours) is the default.
#$EmailAlertsLagTime = "7200"

# This next variable defines if the script will type "EXIT + press ENTER". 
# This is optional, I left it becuase it was cool. If using a Command Prompt as a Test App, 
# you can let the script actually type EXIT then press ENTER. Pretty cool if watching it interactively.
# If you are not using a Command Prompt as a test you probably will want to mark this as $False and 
# set the $logoffmethod as $True.
# If you choose this option, keep the Published Application as Command Prompt, typing in Notepad or Word
# will hang the logoff asking you to save the file.
$typeexit = $False

# Just sends the Logoff command.
# If using the $typeexit method above, leave this $False
$logoffmethod = $False

## ============================================================ ##
##                    END User Variables                        ##
## ============================================================ ##


# ==================== #
# Setup Log Files      #
# ==================== #
# Reads the current directory path from the location of this file
function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value;
    if($Invocation.PSScriptRoot)
    {
        $Invocation.PSScriptRoot;
    }
    Elseif($Invocation.MyCommand.Path)
    {
        Split-Path $Invocation.MyCommand.Path
    }
    else
    {
        $Invocation.InvocationName.Substring(0,$Invocation.InvocationName.LastIndexOf("\"));
    }
}
$currentDir =  Get-ScriptDirectory
$logfile = Join-Path $currentDir ("LaunchPublishedApp.log")
$PreviuosLogFile = Join-Path $currentDir ("LaunchPublishedApp_previuosrun.log")
$AlertsEmailed = Join-Path $currentDir ("LaunchPublishedApp_AlertsEmailed.log")
$CurrentAlerts = Join-Path $currentDir ("LaunchPublishedApp_AlertsCurrent.log")
$AlertEmail = Join-Path $currentDir ("LaunchPublishedApp_AlertsEmailTimeStamp.log")
rm $logfile -force -EA SilentlyContinue

# ==================== #
# Email Style          #
# ==================== #
$ErrorStyle = "style=""background-color: #000000; color: #FF3300;"""

#===================================================================== #
# Sends the results into a logfile as well as in the powershell window #
#===================================================================== #
Function LogMe() 
{
    Param( [parameter(Mandatory = $true, ValueFromPipeline = $true)] $logEntry,
	   [switch]$displaygreen,
	   [switch]$error,
	   [switch]$warning,
	   [switch]$displaynormal,
       [switch]$displayscriptstart,
       [switch]$displayscriptend
	   )
    if($error) { Write-Host "$logEntry" -Foregroundcolor Red; $logEntry = "[ERROR] $logEntry" }
	elseif($warning) { Write-Host "$logEntry" -Foregroundcolor Yellow; $logEntry = "[WARNING] $logEntry"}
	elseif ($displaynormal) { Write-Host "$logEntry" -Foregroundcolor White; $logEntry = "[INFO] $logEntry" }
	elseif($displaygreen) { Write-Host "$logEntry" -Foregroundcolor Green; $logEntry = "[SUCCESS] $logEntry" }
    elseif($displayscriptstart) { Write-Host "$logEntry" -Foregroundcolor Green; $logEntry = "[SCRIPT_START] $logEntry" }
    elseif($displayscriptend) { Write-Host "$logEntry" -Foregroundcolor Green; $logEntry = "[SCRIPT_END] $logEntry" }
    else { Write-Host "$logEntry"; $logEntry = "$logEntry" }

	$logEntry | Out-File $logFile -Append
}

# ============================ #
# Get Client Version Function  #
# ============================ #
function Get-ICAClientVersion{ 
    $ErrorActionPreference = "SilentlyContinue" 
    $ica_client = New-Object -ComObject 'Citrix.ICAClient' 
    if($ica_client) { return $ica_client.ClientVersion } 
    else { return 0 } 
} 

# ====================== #
# Time Elapsed Function  #
# ====================== #
function GetElapsedTime([datetime]$starttime) 
{
    $runtime = $(get-date) - $starttime
    $retStr = [string]::format("{0} sec(s)", $runtime.TotalSeconds)
    $retStr
}

# ===================== #
# Create Registry Item  #
# ===================== #
function CreateRegEntry ($RegPath,$RegName,$PropType,$Val)
{
try {New-ItemProperty -Path $RegPath -Name $RegName -PropertyType $PropType -Value $Val -ErrorAction Stop}
catch {$Script:RegError += $_.Exception.Message
      $_.Exception.Message  | LogMe -error
      }
}

# ===================== #
# Modify Registry Item  #
# ===================== #
function ModifyRegEntry ($RegPath,$RegName,$Val)
{
try {Set-ItemProperty -Path $RegPath -Name $RegName -Value $Val -ErrorAction Stop}
catch {$Script:RegError += $_.Exception.Message
      $_.Exception.Message  | LogMe -error
      }
}

################################################################################
# ============================================================================ #
#                           Start of Script                                    #
# ============================================================================ #
################################################################################
# === Script Start Time
$startTime = Get-Date
cls
"Script Started at $startTime" | LogMe -displayscriptstart

# Making sure Registry Entries exist
# If not, try to create or modify
# If they cannot be created or modified, logging an error 
# and skipping ICA test
$Path = "HKLM:SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM"
$AllowLiveMonitoringName = "AllowLiveMonitoring"
$AllowSimulationAPIName = "AllowSimulationAPI"
$PropertyType = "DWORD"
$Value =  "1"
$AllowLiveMonitoring = Get-ItemProperty -Path $Path -Name $AllowLiveMonitoringName -ErrorAction SilentlyContinue
$AllowSimulationAPI = Get-ItemProperty -Path $Path -Name $AllowSimulationAPIName  -ErrorAction SilentlyContinue
if (!$AllowLiveMonitoring) 
{
"AllowLiveMonitoring does not exist, creating it" | LogMe -warning 
CreateRegEntry $Path $AllowLiveMonitoringName $PropertyType $Value
}
elseif ($AllowLiveMonitoring.AllowLiveMonitoring -ne "1")
{
"AllowLiveMonitoring Value does not equal 1, setting to 1" | LogMe -warning 
ModifyRegEntry $Path $AllowLiveMonitoringName $Value
}
if (!$AllowSimulationAPI)
{ 
"AllowSimulationAPI does not exist, creating it" | LogMe -warning 
CreateRegEntry $Path $AllowSimulationAPIName $PropertyType $Value
}
elseif ($AllowSimulationAPI.AllowSimulationAPI -ne "1")
{
"AllowSimulationAPI value exists but does not equal 1, setting to 1" | LogMe -warning 
ModifyRegEntry $Path $AllowSimulationAPIName $Value
}
if ($RegError -ne $Null) 
{
" " | LogMe
"Errors were encountered when trying to add or modify registry entries required for this script to work" | LogMe -error
"You will either need to run this script once as an Adminitrator or create the following registry entries manually:" | LogMe -error
" " | LogMe
"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM, AllowLiveMonitoring, DWORD, 1" | LogMe -displaynormal
"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM, AllowSimulationAPI, DWORD, 1" | LogMe -displaynormal
$ICAErrors += @"
<p $ErrorStyle>Errors were encountered when trying to add or modify registry entries required for this script to work. 
You will either need to run this script once as an Adminitrator or create the following registry entries manually:<br>
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM, AllowLiveMonitoring, DWORD, 1
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Citrix\ICA Client\CCM, AllowSimulationAPI, DWORD, 1 /p>
"@
}

if ($RegError -eq $Null) 
{
    # Getting Client Version
    $ClientVersion = Get-ICAClientVersion
    Add-Type -AssemblyName System.Windows.Forms

    # Loading the LIB File
    try {Add-Type -Path "C:\Program Files (x86)\Citrix\ICA Client\WfIcaLib.dll"}
    catch 
        {$AddTypeError = $_.Exception.Message
        $_.Exception.Message  | LogMe -error
        }
        If ($AddTypeError -eq $Null)
        {
            #define new array of objects to store ICO connection information
            $connections = @()
            #define new array of objects to store Process ID information of new ICA connections
            $pids = @()
                        
                        
			for($i=0;$i -lt $XAServers.count;$i++)
			{

				$XAserver = $XAServers[$i].ServerName
  
                # Buidling the ICO and starting the ICA Connection to each server
                $ICA = New-Object WFICALib.ICAClientClass
				"Testing Published Application, $pubapp, on Server $XAServer" 
				$ICA.Address = "$XAserver"
				$ICA.Username = "$user"
				$ICA.SetProp("Password","$passwd")
				$ICA.Domain = "$domain"
				$ICA.InitialProgram  = "$pubapp"
				$ICA.Launch = $true
				$ICA.OutputMode = [WFICALib.OutputMode]::OutputModeNormal
				$ICA.DesiredHRes = 200
				$ICA.DesiredVRes = 400
				$ICA.DesiredColor = [WFICALib.ICAColorDepth]::Color16bit
				$ICA.TWIMode = $true
				"Launching ICA Session using Citrix Client version $ClientVersion"
				$LaunchTime = Get-Date
				"Connect Started at $script:LaunchTime" 
				#Launch Citrix app
				$ICA.Connect()
                
                sleep 2

                $connections += $ICA
				#Get PID of launched WFICA32 process
                $sessionID= get-Process -name wfica32|sort starttime -Descending | select -first 1
                $pids += $sessionID
            }

            #wait for ICA connections to launch
            sleep 40

            for($j=0;$j -lt $connections.count;$j++)
            {
                if ($connections[$j].IsConnected() -eq $true -and $connections[$j].Address -eq $XAServers[$j].ServerName)
                {
                    if ($pids[$j].MainWindowTitle -eq "TITLE OF THE WINDOW OF YOUR TESTED APPLICATION")    
                    {
                        "Test ICA Session found running on $($XAServers[$j].ServerName); logging off" | LogMe -displaygreen
                        
					    $logonelapsed = GetElapsedTime $LaunchTime
					    "Time taken to logon is: $logonelapsed" | LogMe -displaygreen
                        $connections[$j].Logoff() 
                    }
                    elseif ($pids[$j].MainWindowTitle -eq "Windows Logon" -or $pids[$j].MainWindowTitle -eq "Notepad" )
                    {
                        "Connection failed to server " + $($XAServers[$j].ServerName) | LogMe -Error
					    $ICAErrors += "<p $ErrorStyle>Error Connection to server <strong>$($XAServers[$j].ServerName).</strong></p>"                        
                        $ICAErrors += "<p $ErrorStyle>Please check for a hanged service (e.g. CpSvc) on server <strong>$($XAServers[$j].ServerName).</strong></p>"
                        $connections[$j].Logoff() 
                    }
                    else
                    {
                        "Connection failed to server " + $($XAServers[$j].ServerName) | LogMe -Error
					    $ICAErrors += "<p $ErrorStyle>Error Connection to server <strong>$($XAServers[$j].ServerName).</strong></p>"                        
                        $ICAErrors += "<p $ErrorStyle>Problem with logon process to server <strong>$($XAServers[$j].ServerName) - please check.</strong></p>"
                        $connections[$j].Logoff()                         
                    }
                }
                elseif ($connections[$j].IsConnected() -eq $false -and $connections[$j].Address -eq $XAServers[$j].ServerName)
                {
                    "Connection failed to server " + $($XAServers[$j].ServerName) | LogMe -Error
					$ICAErrors += "<p $ErrorStyle>Error Connection to server <strong>$($XAServers[$j].ServerName)</strong></p>"
					"Clicking OK in the Citrix Receiver dialog window" | LogMe -displaynormal    
               
					Add-Type @"
					using System;
					using System.Runtime.InteropServices;
					public class SFW {
					[DllImport("user32.dll")]
					[return: MarshalAs(UnmanagedType.Bool)]
					public static extern bool SetForegroundWindow(IntPtr hWnd);
					}
"@

					"Finding a window named Citrix Receiver" | LogMe -displaynormal
					$hwnd = (get-process Receiver).MainWindowHandle # just one Receiver window must be opened!
					if ($hwnd -ne 0)
					{
						"Set Foreground Window to Citrix Receiver" | LogMe -displaynormal
						[SFW]::SetForegroundWindow($hwnd)
						"Sending the Enter command to Window" | LogMe -displaynormal
						[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
					}
					else 
					{
						"There was no Window titled Citrix Receiver, the error is most likely due to the script" | LogMe -warning
					}
            
                }
                else
                {
                	$ICAErrors += "<p $ErrorStyle>Error launching application <strong>$pubapp</strong> on server <strong>$XAServer</strong></p>"
					"Did not detect a Successful Logon or a Connect Failure to server $XAServers[$j].ServerName" | LogMe -Error
					"Assuming Logon Failure, Server is not available or the Application is not available" | LogMe -Error
					"Check the Published Application, Server Logons are Enabled, User Account and/or Script User Variables" | LogMe -Error  
                
                }             


            }

        }
        else 
		{
			$ICAErrors += @"
            <p $ErrorStyle>Errors were encountered when trying to load WfIcaLib.dll.<br>
            $AddTypeError</p>
"@
		}
}

# Get the Current Time for Email Alert Time Stamp
$CurrTime = Get-Date -format g

# Checking to see if there were any Errors Detected
# If there were, update the CurrentAlerts Log File for later comparison
if ($ICAErrors -ne $Null) 
    {
    if (Test-Path $CurrentAlerts) { clear-content $CurrentAlerts }
    foreach ($line in $ICAErrors) {$Line | Add-Content $CurrentAlerts}
            
        # Get Content from Alert Log File, we want the first line, which should be the previuos time stamp.
        if (Test-Path $AlertEmail) 
            { $AlertFileTime = gc $AlertEmail -TotalCount 1 } 

        # Check to see if the Time Span for sending alerts has passed
        if ($AlertFileTime)
            {$AlertTimeSpan = New-TimeSpan $AlertFileTime $(Get-Date -format g)
            $AlertTimeDifference = $AlertTimeSpan.TotalSeconds 
                if (!$AlertTimeDifference) { $SendEmail = $True }
                if ($AlertTimeDifference -ge $EmailAlertsLagTime) { $SendEmail = $True }
                else { $SendEmail = $False }
            }
        if (!$AlertFileTime) { $SendEmail = $True }

        # Checking Alert Log Contents from last run for comparison
        if (Test-Path $AlertsEmailed) { $AlertLogContents = gc $AlertsEmailed }

        # Checking Current Errors and Warnings found this duration for comparison
        if (Test-Path $CurrentAlerts) { $CurrentAlertsContents = gc $CurrentAlerts }

        # If the Alerts Email Log is empty but the Current Log is not, there are new alerts.
        If (!$AlertLogContents -and $CurrentAlertsContents) 
            {
            $NewAlerts = $True
            $SendEmail = $True 
            " " | LogMe
            "New Alerts Detected"  | LogMe -warning
            } 
        # If the Alert Email Log and the Current Alert Log matches then there are most likely no new errors
        If ($AlertLogContents -and $CurrentAlertsContents) 
            {
            $AlertsDiff = compare-object $CurrentAlertsContents $AlertLogContents | Measure
            If ($AlertsDiff.count -ne 0) 
                    { $NewAlerts = $True 
                    " " | LogMe
                    "New Alerts Detected"  | LogMe -warning
                    }
                else 
                    { $NewAlerts = $False 
                    " " | LogMe
                    "No New Alerts Detected"  | LogMe -displaynormal
                    } 
            }

    }
else {if (Test-Path $CurrentAlerts) 
    {clear-content $CurrentAlerts}

}

#=============================================================================================
#                                 Email Section
#=============================================================================================  
If (($NewAlerts -eq $True) -or ($SendEmail -eq $True)) 
    { 
        if (Test-Path $AlertsEmailed) { clear-content $AlertsEmailed }
        foreach ($line in $ICAErrors) { $Line | Add-Content $AlertsEmailed }

        # Setting MailFlag for the validation and error handling
        $MailFlag = $false 

        If(!$emailFrom) { $MailFlag = $True; Write-Warning "From Email is NULL" | LogMe -error }
        If(!$emailTo) { $MailFlag = $True; Write-Warning "To Email is NULL" | LogMe -error }
        If(!$smtpServer) { $MailFlag = $True; Write-Warning "SMTP Server is NULL" | LogMe -error }

        # $MailFlag = $True

        # Send email only if From, To and SMTP adress are not null
        if($MailFlag -match $True) { "Email could not send as the email parameters (FROM/TO/SMTP) failed"  | LogMe -error}
        
        # Send email only if there is either an Error or Warning Detected
        $BODY = $ICAErrors
        $msg = new-object System.Net.Mail.MailMessage
        $msg.From=$emailFrom
        $msg.to.Add($emailTo)
        if($emailCC) { $msg.cc.add($emailCC) }
        $msg.Subject=$emailSubject
        $msg.IsBodyHtml=$true
        $msg.Body=$BODY
        #$msg.Attachments.Add($logfile)
        $smtp = new-object System.Net.Mail.SmtpClient
        $smtp.host=$smtpServer
        Try { $smtp.Send($msg)
            " " | LogMe
            "Email Sent" | LogMe -displaygreen }
        Catch { 
            "" | LogMe
            "Error Sending Email. See Error Messages Below:" | LogMe -error 
            "Error Message: " + $_.Exception.Message | LogMe -error
            "Error Item: " + $_.Exception.ItemName | LogMe -error
                  }
        Start-Sleep 2
        $msg.Dispose()
        if (Test-Path $AlertEmail) { clear-content $AlertEmail }
        $CurrTime | Add-Content $AlertEmail
        }
else 
    { 
    " " | LogMe
    "Not sending an email since there were no new Errors detected" | LogMe -displaynormal
    }



$scriptelapsed = GetElapsedTime $startTime
" " | LogMe
"Total Elapsed Script Time: $scriptelapsed" | LogMe -displaygreen
" " | LogMe
"Script Ended at $(get-date)" | LogMe -displayscriptend
" " | LogMe

# Killing left over processes from Receiver so the script will work the next time it is executed
# This is really only needed when running as a scheduled task
# If these processes are allowed to remain the Connection fails after the second try
$KillApps = $True
if ($KillApps -eq $True){

try {kill -name wfcrun32 -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}

try {kill -name concentr -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}

try {kill -name redirector -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}

try {kill -name wfica32 -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}

try {kill -name receiver -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}

try {kill -name ssonsvr -Force -ErrorAction SilentlyContinue}
catch {$_.Exception.Message | LogMe -warning}
}

# Creating Log file for previuos ran jobs
# File is cleared when it reaches 1MB
$size = Get-ChildItem $PreviuosLogFile
if ($size.length -ge 1048576)
    {clear-content $PreviuosLogFile}
$LogPattern = @("[SUCCESS]","[ERROR]","[WARNING]","[SCRIPT_START]","[SCRIPT_END]")
if (Test-Path $LogFile) {Get-Content $LogFile | Select-String -Pattern $LogPattern -SimpleMatch | add-Content $PreviuosLogFile}

EXIT

#==============================================================================================
# END OF SCRIPT
#==============================================================================================


10 thoughts on “[Powershell] Citrix XenApp Monitoring Script ver. 2.1

  1. Hi Paul
    Thanks for taking your valuable time to share your time and script. Really appreciate it. I would be interested to see how the output looks like . Could you post that as well please if you get some time. Thanks again . Suresh

    Like

  2. Can you please provide the lines to suppress windows logon screen.. where we need to manually click on OK

    Like

  3. Hi,

    I’m receiving 2 errors:
    1. Get-Process : Cannot find a process with the name “wfica32”. Verify the process name and call the cmdlet again.
    2. Get-Process : Cannot find a process with the name “Receiver”. Verify the process name and call the cmdlet again.

    Please help.

    Thank you,
    Andrei

    Like

    • hi Andrei,

      Does any Citrix session starts properly? If so – can you see and wfica.exe process under Task Manager?

      Like

      • Hi Pawelserman, yes sessions starts properly and I saw wfica.exe under Task Manager. But I still having this errors.
        can you help?
        Thank You.
        Edioson.

        Like

  4. ################################################################################################
    ## XenApp Server HealthCheck based on the WorkerGroup Name report
    ## Author: Rajat (email id)
    ## April 2015
    ## v3.2 — Included User Profile Service check in the script.
    ## v3.3 — Included Licensing service and usage report
    ## — Updated new header and footer with Wright logo
    ## — Added new color code INFO-Yellow, DISPLAY-Ash
    ##
    ## The script checks the health of XenApp 6.x servers based on the WorkerGroup membership (with powershell SDKs installed) and e-mails the report.
    ## This script checks the following:
    ## – Ping response
    ## – Logon enabled?
    ## – Assigned correct Load Evaluator?
    ## – Active and Disconnected sessions
    ## – RDP port response
    ## – ICA port response
    ## – Citrix IMA, Citrix Print Manager and Spooler services status
    ## – WMI response (to check for WMI corruption)
    ## – Uptime, CPU/RAM Usage
    ## – Farm Session Info – Total active & disconnected sessions
    ##
    ## You are free to use this script in your environment but please e-mail me for any improvements.
    ################################################################################################
    if ((Get-PSSnapin „Citrix.*” -EA silentlycontinue) -eq $null) {
    try { Add-PSSnapin Citrix.* -ErrorAction Stop }
    catch { write-error „Error loading XenApp Powershell snapin”; Return }
    }
    # Change the below variables to suit your environment
    #==============================================================================================
    # Servers belongs to this worker group only evaluated
    $WorkerGroupName = „Weekly Reboot”
    # Default load evaluator assigned to servers.
    $defaultLE = „Default”
    # License Server Name for Citrix Farm to check the license usage.
    $LicenseServer = „clicense.us.wmgi.com”
    # License Type to be defined [Eg: @(„MPS_PLT_CCU”, „MPS_ENT_CCU”)].
    # The license file can be in Enterprise or Platinum versions.
    $LicenseTypes = @(„MPS_ENT_CCU”,”MPS_PLT_CCU”)
    # Only change this if you have changed the default port to custom port
    $RDPPort = „3389”
    $ICAPort = „1494”
    $maxUpTimeDays = „7”
    $sessionReliabilityPort = „2598”
    $Amberram = „70”
    $Redram = „95”
    # E-mail report details
    $emailFrom = „WMT.Monitoring@wright.com”
    #$emailTo = „rajat.gupta@wright.com,Jesudass.Chinapan@wright.com”
    #$emailTo = „WMTInfrasupport@wmt.com,WMTITISCitrix@wmt.com,dan.gabrielson@wmt.com,Micheal.Cooley@wmt.com,Lakshmanan.Veluchamy@wmt.com,WMTITISL3@wmt.com”
    $emailTo = „WrightInfrasupport@wright.com,WMTITISCitrix@wmt.com”
    $smtpServer = „exch-f01.us.wmgi.com”
    $emailSubject = „Wright Health Check Report 6.5 [Citrix] ”
    # Identifies the current directory path and creates logs there.
    $currentDir = Split-Path $MyInvocation.MyCommand.Path
    $logfile = Join-Path $currentDir („wmt.log”)
    $resultsHTM = Join-Path $currentDir („wsm_Health_Check_Results.htm”)
    # Images are used as the company logo for better presentation
    $ImgHdr = Join-Path $currentDir („header1.jpg”)
    $ImgFtr = Join-Path $currentDir („footer1.jpg”)
    $Image1path = Join-Path $currentDir („wmt.gif”)
    $Image2path = Join-Path $currentDir („cts.gif”)
    $Signaturepath = Join-Path $currentDir („cts_sign.gif”)
    # Table Header creates based on the number of header names defined
    $headerNames = „FolderPath”, „Ping”, „Logons”, „Active” , „Disconnected”, „LoadEvaluator”, „RDPPort”, „GroupPolicy” , „ICAPort”, „IMA”, „CGPPort” , „UserProfile” , „CitrixPrint”, „WMI”, „Spooler” , „Uptime” , „RAMUsage” , „DiskFree”, „ServerLoad”
    $headerWidths = „6”, „4”, „4”, „4”, „4” , „4” , „4”, „4”, „4”, „4”, „4”, „4” , „4” , „4”, „4” ,”4″ , „4” , „4” , „4”
    #==============================================================================================
    # Functions used in the Main program
    #==============================================================================================
    #==============================================================================================
    # This function will check the license usage report on the license server and will report the current usage
    #==============================================================================================
    Function CheckLicense()
    {
    if(!$LicenseServer) { „No License Server Name defined” | LogMe -Error; $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    if(!$LicenseTypes) { „No License Type defined” | LogMe -Error; $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    # Declare the variables to capture and calculate the License Usage
    [int]$TotalLicense = 0; [int]$InUseLicense = 0; [int]$PercentageLS = 0; $LicenseResult = ” ”
    # Error Handling if the server is not accessible for the license details or WMI issues
    Try
    { if(Get-Service -Display „Citrix Licensing” -ComputerName $LicenseServer -ErrorAction Stop) { „Citrix Licensing service is available.” | LogMe }
    else { „Citrix Licensing’ service is NOT available.” | LogMe -Error; Return „Error; Check Logs” }
    Try { if($licensePool = gwmi -class „Citrix_GT_License_Pool” -Namespace „ROOT\CitrixLicensing” -comp $LicenseServer -ErrorAction Stop)
    { „License Server WMI Class file found” | LogMe -Display
    $LicensePool | ForEach-Object{
    foreach ($Ltype in $LicenseTypes)
    { if ($_.PLD -match $Ltype) { $TotalLicense = $TotalLicense + $_.count; $InUseLicense = $InUseLicense + $_.InUseCount } } }
    „The total number of licenses available: $TotalLicense ” | LogMe
    „The number of licenses are in use: $InUseLicense ” | LogMe
    if(!(($InUseLicense -eq 0) -or ($TotalLicense -eq 0 ))) { $PercentageLS = (($InUseLicense / $TotalLicense ) * 100); $PercentageLS = „{0:N2}” -f $PercentageLS }
    if($PercentageLS -gt 90) { „The License usage is $PercentageLS % ” | LogMe -Error }
    elseif($PercentageLS -gt 80) { „The License usage is $PercentageLS % ” | LogMe -Warning }
    else { „The License usage is $PercentageLS % ” | LogMe }
    $LicenseResult = „$InUseLicense [ $PercentageLS % ]”; return $LicenseResult
    }
    } Catch {
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    „License Server WMI Class file failed. An Error Occured while capturing the License information” | LogMe -Error
    „You may need to uninstall your License Server and reinstall.” | LogMe -Error
    „There are known issues with doing an in place upgrade of the license service.” | LogMe -Error
    $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    } Catch { „Error returned while checking the Licensing Service. Server may be down or some permission issue” | LogMe -error; return „Error; Check Detailed Logs” }
    }
    #================================================================================================
    # The function will check the service using its display name. If the service could not find, then return a value as N/A
    Function CheckService() { Param($ServiceName)
    #if (!(Get-Service -Name $ServiceName -ComputerName $server -ErrorAction SilentlyContinue) ) { „$ServiceName is not available…” | LogMe; $ServiceResult = „N/A” }
    if (!(Get-Service -Display $ServiceName -ComputerName $server -ErrorAction SilentlyContinue) ) { „$ServiceName is not available…” | LogMe; $ServiceResult = „N/A” }
    else {
    if ((Get-Service -Display $ServiceName -ComputerName $server).Status -Match „Running”) { „$ServiceName is running…” | LogMe; $ServiceResult = „Success” }
    else { „$ServiceName is not running” | LogMe -display -error; $ServiceResult = „Error” }
    }
    return $ServiceResult
    }
    #==============================================================================================
    # The function will log the data / result into a logfile. The data is send to function as parameter or a piped command output
    Function LogMe() {
    Param( [parameter(Mandatory = $true, ValueFromPipeline = $true)] $logEntry,
    [switch]$display,
    [switch]$error,
    [switch]$warning,
    [switch]$progress)
    if ($error) { $logEntry = „[ERROR] $logEntry” ; Write-Host „$logEntry” -Foregroundcolor Red }
    elseif ($warning) { Write-Warning „$logEntry” ; $logEntry = „[WARNING] $logEntry” }
    elseif ($progress) { Write-Host „$logEntry” -Foregroundcolor Green }
    elseif ($display) { Write-Host „$logEntry” }
    #$logEntry = ((Get-Date -uformat „%D %T”) + ” – ” + $logEntry)
    $logEntry | Out-File $logFile -Append
    }
    #==============================================================================================
    # The function will check the ping response to the server and reports failure
    Function Ping ([string]$hostname, [int]$timeout = 200) {
    $ping = new-object System.Net.NetworkInformation.Ping #creates a ping object
    try { $result = $ping.send($hostname, $timeout).Status.ToString() }
    catch { $result = „Failure” }
    return $result
    }
    #==============================================================================================
    # The function check the response from the port like a telnet query. If ICA port, then it check for the ICA response too
    Function Check-Port() { param ([string]$hostname, [string]$port)
    try { $socket = new-object System.Net.Sockets.TcpClient($hostname, $Port) } #creates a socket connection to see if the port is open
    catch {
    $socket = $null
    „Socket connection on $port failed” | LogMe -display -error
    return $false }
    if($socket -ne $null) { „Socket Connection on $port Successful” | LogMe
    if ($port -eq „1494”) {
    $stream = $socket.GetStream() #gets the output of the response
    $buffer = new-object System.Byte[] 1024
    $encoding = new-object System.Text.AsciiEncoding
    Start-Sleep -Milliseconds 500 #records data for half a second
    while($stream.DataAvailable) {
    $read = $stream.Read($buffer, 0, 1024)
    $response = $encoding.GetString($buffer, 0, $read)
    #Write-Host „Response: ” + $response
    if($response -like ‚*ICA*’){
    „ICA protocol responded” | LogMe
    return $true }
    }
    „ICA did not response correctly” | LogMe -display -error
    return $false
    } else { return $true }
    } else { „Socket connection on $port failed” | LogMe -display -error; return $false }
    }
    #===========================================================================================
    # HTML Report Formating Part
    #===========================================================================================
    Function writeHtmlHeader { param($title, $fileName, $TotalServers)
    $date = ( Get-Date -format R)
    $head = @”
    $title

    $title $date
    Total Number of Wright Citrix Servers: $TotalServers
    Citrix License Usage: $LicenseReport
    Total Active Sessions: $TotalActiveSessions
    Total Disconnected: $TotalDisconnectedSessions
    „@
    $head | Out-File $fileName
    }
    # ==============================================================================================
    Function writeTableHeader { param($fileName)
    $tableHeader = @”
    ServerName
    „@
    $i = 0
    while ($i -lt $headerNames.count) {
    $headerName = $headerNames[$i]
    $headerWidth = $headerWidths[$i]
    $tableHeader += „$headerName
    $i++ }
    $tableHeader += „”
    $tableHeader | Out-File $fileName -append
    }
    # ==============================================================================================
    Function writeData { param($data, $fileName)
    $data.Keys | sort | foreach {
    $tableEntry += „”
    $computerName = $_
    $tableEntry += („$computerName”)
    #$data.$_.Keys | foreach {
    $headerNames | foreach {
    #”$computerName : $_” | LogMe -display
    try {
    if ($data.$computerName.$_[0] -eq „SUCCESS”) { $bgcolor = „#387C44”; $fontColor = „#FFFFFF” }
    elseif ($data.$computerName.$_[0] -eq „WARNING”) { $bgcolor = „#FF7700”; $fontColor = „#FFFFFF” }
    elseif ($data.$computerName.$_[0] -eq „INFO”) { $bgcolor = „#ffff99”; $fontColor = „#000000” }
    elseif ($data.$computerName.$_[0] -eq „ERROR”) { $bgcolor = „#FF0000”; $fontColor = „#FFFFFF” }
    else { $bgcolor = „#CCCCCC”; $fontColor = „#003399” }
    $testResult = $data.$computerName.$_[1]
    }
    catch {
    $bgcolor = „#CCCCCC”; $fontColor = „#003399”
    #$bgcolor = „#AEB404”; $fontColor = „#4000FF”
    $testResult = „N/A”
    }
    $tableEntry += („$testResult”)
    }
    $tableEntry += „”
    }
    $tableEntry | Out-File $fileName -append
    }
    # ==============================================================================================
    Function writeHtmlFooter
    {
    param($fileName)
    @”
    NOTE: The above results are generated from an automation task created by Wright Citrix Team. Any issues reported in the above report will be actioned by Wright Citrix Team
    Author: Wright Citrix Team Email: rajat.gupta@wright.com ; WMTITISCitrix@wmt.com
    „@ | Out-File $FileName -append
    }
    # END OF THE FUNCTIONS
    #=================================================================================================
    # ==============================================================================================
    # ======= MAIN SCRIPT =======
    # ==============================================================================================
    rm $logfile -force -EA SilentlyContinue
    $date1 = Get-Date -format R
    „Checking server health…… ($date1)” | LogMe -display -progress
    $TotalServers = 0
    $allResults = @{}
    # Calling the license checking function here
    „Checking Citrix License usage on $LicenseServer” | LogMe -Display
    $LicenseReport = CheckLicense
    # Get session list once to use throughout the script
    $sessions = Get-XASession
    $WorkerGroupServers = Get-XAWorkerGroup $WorkerGroupName
    $servers = $WorkerGroupServers.ServerNames | sort-object $_.ServerNames
    #$servers = „C1″,”C10″,”C11″,”C12″,”C13″,”C14″,”C15″,”C16″,”C17″,”C18″,”C19″,”C2″,”C20″,”C23″,”C24″,”C25″,”C26″,”C27″,”C28″,”C29″,”C3″,”C30″,”C4″,”C5″,”C6″,”C7″,”C8″,”QTSVPW8CTX01″,”QTSVPW8CTX02″,”QTSVTW8CTX01″,”QTSVTW8CTX02”
    #$servers= „C1″,”C10″,”C6″,”QTSVPW8CTX01”
    foreach($server in $servers){
    $tests = @{}
    „———————————————————” | LogMe
    $server | LogMe -display -progress
    $TotalServers = $TotalServers + 1
    # Check Folder Path
    $folder= (Get-XAServer -ServerName $server | % {$_.FolderPath})
    if ($folder -ne $null)
    {
    $tests.FolderPath = „DISPLAY”, $folder.trim(„Servers/”)
    „$folder” | LogMe
    }
    else
    {
    $tests.FolderPath = „ERROR”, $folder
    }
    # Ping server
    $result = Ping $server 100
    if ($result -ne „SUCCESS”)
    {
    $tests.Ping = „ERROR”, $result
    „Ping Results : $result. Skipping rest of the tests” | LogMe -display -error
    }
    else
    {
    $tests.Ping = „SUCCESS”, $result
    „Ping Results : $result.” | LogMe
    # Check server logons
    if((Get-XAServer -ServerName $server).LogOnsEnabled -eq $false)
    {
    „Logons are disabled on this server” | LogMe -display -error
    $tests.Logons = „ERROR”, „Disabled”
    }
    else
    {
    „Logons are enabled on this server” | LogMe
    $tests.Logons = „SUCCESS”,”Enabled”
    }
    # Test Session Reliability port
    if (Check-Port $server $sessionReliabilityPort)
    { $tests.CGPPort = „SUCCESS”, „Success” }
    else { $tests.CGPPort = „ERROR”, „No response” }
    # Check Load Evaluator
    if ((Get-XALoadEvaluator -ServerName $server).LoadEvaluatorName -ne $defaultLE)
    {
    #”Non-default Load Evaluator assigned” | LogMe -display -warning
    $LE = (Get-XALoadEvaluator -ServerName $server)
    $tests.LoadEvaluator = „SUCCESS”, $LE
    „$LE Load Evaluator assigned” | LogMe -display
    }
    else
    {
    „Default Load Evaluator assigned” | LogMe
    $tests.LoadEvaluator = „DISPLAY”, $defaultLE
    }
    # Report on active server sessions
    #$activeServerSessions = [array]($sessions | ? {$_.State -eq „Active” -and $_.Protocol -eq „Ica” -and $_.ServerName -match $server})
    $activeServerSessions = [array]($sessions | ? {$_.State -eq “Active” -and $_.Protocol -eq “Ica” -and $_.ServerName -eq $server})
    if ($activeServerSessions)
    {
    $totalActiveServerSessions = $activeServerSessions.count
    }
    else
    {
    $totalActiveServerSessions = 0
    }
    $tests.Active = „SUCCESS”, $totalActiveServerSessions
    „Number of active sessions on the server: $totalActiveServerSessions” | LogMe
    # Report on disconnected sessions
    $discServerSessions = [array]($sessions | ? {$_.State -eq „Disconnected” -and $_.Protocol -eq „Ica” -and $_.ServerName -match $server})
    if ($discServerSessions)
    {
    $totalDiscServerSessions = $discServerSessions.count
    }
    else
    {
    $totalDiscServerSessions = 0
    }
    $tests.Disconnected = „SUCCESS”, $totalDiscServerSessions
    „Number of disconnected sessions on the server: $totalDiscServerSessions” | LogMe
    # Creates a warnig if both active and disconnected sessions are zero
    if (($totalActiveServerSessions -eq 0) -and ($totalDiscServerSessions -eq 0))
    {
    $tests.Active = „INFO”, $totalActiveServerSessions
    $tests.Disconnected = „INFO”, $totalDiscServerSessions
    }
    # Test ICA connectivity
    if (Check-Port $server $ICAPort)
    {
    $tests.ICAPort = „SUCCESS”, „Success”
    }
    else
    {
    $tests.ICAPort = „ERROR”,”No response”
    }
    # Test RDP connectivity
    if (Check-Port $server $RDPPort)
    {
    $tests.RDPPort = „DISPLAY”, „Success”
    }
    else
    {
    $tests.RDPPort = „SUCCESS”, „Disabled”
    }
    # Check the IMA service
    $ServiceOP = CheckService („Citrix Independent Management Architecture”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.IMA = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.IMA = „SUCCESS”, $ServiceOP
    }
    # Checks the Print Spooler service
    $ServiceOP = CheckService („Print Spooler”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.Spooler = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.Spooler = „SUCCESS”, $ServiceOP
    }
    # Checks the Citrix Print Manager service
    $ServiceOP = CheckService („Citrix Print Manager Service”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.CitrixPrint = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.CitrixPrint = „SUCCESS”, $ServiceOP
    }
    # Checks the Group policy Client service
    $ServiceOP = CheckService („Group Policy Client”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.GroupPolicy = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.GroupPolicy = „SUCCESS”, $ServiceOP
    }
    # Checks the User profile service
    $ServiceOP = CheckService („User Profile Service”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.UserProfile = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.UserProfile = „SUCCESS”, $ServiceOP
    }
    # Test WMI
    try { $wmi=Get-WmiObject -class Win32_OperatingSystem -computername $server }
    catch { $wmi = $null }
    if ($wmi -ne $null)
    {
    $tests.WMI = „SUCCESS”, „Success”
    $LBTime=$wmi.ConvertToDateTime($wmi.Lastbootuptime)
    [TimeSpan]$uptime=New-TimeSpan $LBTime $(get-date)
    if ($uptime.days -gt $maxUpTimeDays){
    „Server reboot warning, last reboot: {0:D}” -f $LBTime | LogMe -display -warning
    $tests.Uptime = „WARNING”, $uptime.days
    } else {
    $tests.Uptime = „SUCCESS”, $uptime.days
    }
    }
    else
    {
    $tests.WMI = „ERROR”,”Error”
    „WMI connection failed – check WMI for corruption” | LogMe -display -error
    }
    # If the IMA service is running, check the server load
    if ($tests.IMA[0] -eq „Success”) {
    $CurrentServerLoad = Get-XAServerLoad -ServerName $server
    #$CurrentServerLoad.GetType().Name|LogMe -display -warning
    if( [int] $CurrentServerLoad.load -lt 7500) {
    „Serverload is low” | LogMe
    $tests.Serverload = „SUCCESS”, ($CurrentServerload.load)
    }
    elseif([int] $CurrentServerLoad.load -lt 9000) {
    „Serverload is Medium” | LogMe -display -warning
    $tests.Serverload = „WARNING”, ($CurrentServerload.load)
    }
    else {
    „Serverload is High” | LogMe -display -error
    $tests.Serverload = „ERROR”, ($CurrentServerload.load)
    }
    $CurrentServerLoad = 0
    }
    #RAM Usage
    #$OS = (Get-WmiObject Win32_OperatingSystem -computername $server).caption
    try { $RAM = Get-WmiObject -Class Win32_OperatingSystem -computername $server | Select-Object Name, TotalVisibleMemorySize, FreePhysicalMemory }
    catch { $RAM = $null }
    if ($RAM -ne $null )
    {
    $tests.RAM = „SUCCESS”, „Success”
    $TotalRAM = $RAM.TotalVisibleMemorySize/1MB
    $FreeRAM = $RAM.FreePhysicalMemory/1MB
    $UsedRAM = $TotalRAM – $FreeRAM
    $RAMPercentused = ($usedRAM / $TotalRAM) * 100
    $TotalRAM = [Math]::Round($TotalRAM, 2)
    $FreeRAM = [Math]::Round($FreeRAM, 2)
    $UsedRAM = [Math]::Round($UsedRAM, 2)
    $RAMPercentused = [Math]::Round($RAMPercentUsed, 2)
    $RAMPUsed = „$RAMPercentused%”
    „RAM Usage: $RAMPUsed” | LogMe
    if ($RAMPercentused -gt $Redram){
    $tests.ramusage = „ERROR”, $RAMPUsed
    } elseif (($RAMPercentused -gt $Amberram) -AND ($RAMPercentused -lt $Redram)) {
    $tests.ramusage = „WARNING”, $RAMPUsed
    } else {
    $tests.ramusage = „SUCCESS”, $RAMPUsed
    }
    }
    else
    {
    $tests.RAM = „ERROR”,”Error”
    „WMI connection failed – check WMI for corruption” | LogMe -display -error
    }
    }
    #Hard Disk
    try { $HardDisk = Get-WmiObject Win32_LogicalDisk -ComputerName $server -Filter „DeviceID=’C:’” | Select-Object Size,FreeSpace }
    catch { $HardDisk = $null }
    if ($HardDisk -ne $null)
    {
    $DiskTotalSize = $HardDisk.Size
    $DiskFreeSpace = $HardDisk.FreeSpace
    $PercentageDS = (($DiskFreeSpace / $DiskTotalSize ) * 100); $PercentageDS = „{0:N2}” -f $PercentageDS
    $DSP =”$PercentageDS%”
    if( $PercentageDS -gt 15)
    { „Disk Free is normal: $DSP” | LogMe
    $tests.DiskFree = „SUCCESS”, $DSP
    }
    elseif( $PercentageDS -lt 15)
    { „Disk Free is Low: $DSP” | LogMe
    $tests.DiskFree = „WARNING”, $DSP
    }
    elseif( $PercentageDS -lt 5)
    { „Disk Free is normal: $DSP” | LogMe
    $tests.DiskFree = „ERROR”, $DSP
    }
    elseif( $PercentageDS -eq 0)
    { „Disk Free test failed” | LogMe -error;
    $tests.DiskFree = „ERROR”, „Err”
    } }
    else
    { $tests.DiskFree = „ERROR”, ($PercentageDS)
    „Disk Free is Critical” | LogMe -display -error
    }
    $PercentageDS = 0
    $allResults.$server = $tests
    }
    # Get farm session info
    $ActiveSessions = [array]($sessions | ? {$_.State -eq „Active” -and $_.Protocol -eq „Ica”})
    $DisconnectedSessions = [array]($sessions | ? {$_.State -eq „Disconnected” -and $_.Protocol -eq „Ica”})
    if ($ActiveSessions) { $TotalActiveSessions = $ActiveSessions.count }
    else { $TotalActiveSessions = 0 }
    if ($DisconnectedSessions) { $TotalDisconnectedSessions = $DisconnectedSessions.count }
    else { $TotalDisconnectedSessions = 0 }
    „Total Active Sessions: $TotalActiveSessions” | LogMe -display
    „Total Disconnected Sessions: $TotalDisconnectedSessions” | LogMe -display
    # Write all results to an html file
    writeHtmlHeader $emailSubject $resultsHTM $TotalServers
    writeTableHeader $resultsHTM
    $allResults | % { writeData $allResults $resultsHTM }
    writeHtmlFooter $resultsHTM
    #=============================================================================================
    # Emailing Part
    #=============================================================================================
    $msg = new-object System.Net.Mail.MailMessage
    $msg.From=$emailFrom
    $msg.to.Add($emailTo)
    $msg.Subject=$emailSubject
    $msg.IsBodyHtml=$true
    # Images are found by the ‚COntentID-CID’ in the body of the message. Both logos to be paced in the same directory where we save the script
    $att = new-object System.Net.Mail.Attachment($ImgHdr)
    $att.ContentDisposition.Inline = $True
    $att.ContentDisposition.DispositionType = „Inline”
    $att.ContentType.MediaType = „image/jpeg”
    $att.ContentId = „header”
    $att1 = new-object System.Net.Mail.Attachment($ImgFtr)
    $att1.ContentDisposition.Inline = $True
    $att1.ContentDisposition.DispositionType = „Inline”
    $att1.ContentType.MediaType = „image/jpeg”
    $att1.ContentId = „Signature”
    $msg.Body=(gc $resultsHTM) | Out-String
    $msg.Attachments.Add($logfile)
    $msg.Attachments.Add($att)
    $msg.Attachments.Add($att1)
    $smtp = new-object System.Net.Mail.SmtpClient
    $smtp.host=$smtpServer
    $smtp.Send($msg)
    Start-Sleep 5
    $att.Dispose()
    $att1.Dispose()
    $msg.Dispose()
    Write-host „Email Sent”
    #======================= END OF MAIN PROGRAM ++++++++++++++++++++++++++++++++++++++++++++++
    ###############################################################################################

    Like

  5. ———- Forwarded message ———
    From: Pradeep B
    Date: Wed, 23 May 2018, 6:22 pm
    Subject: Healthcheck 6.5
    To: Joseph A
    ################################################################################################
    ## XenApp Server HealthCheck based on the WorkerGroup Name report
    ## Author: Rajat (email id)
    ## April 2015
    ## v3.2 — Included User Profile Service check in the script.
    ## v3.3 — Included Licensing service and usage report
    ## — Updated new header and footer with Wright logo
    ## — Added new color code INFO-Yellow, DISPLAY-Ash
    ##
    ## The script checks the health of XenApp 6.x servers based on the WorkerGroup membership (with powershell SDKs installed) and e-mails the report.
    ## This script checks the following:
    ## – Ping response
    ## – Logon enabled?
    ## – Assigned correct Load Evaluator?
    ## – Active and Disconnected sessions
    ## – RDP port response
    ## – ICA port response
    ## – Citrix IMA, Citrix Print Manager and Spooler services status
    ## – WMI response (to check for WMI corruption)
    ## – Uptime, CPU/RAM Usage
    ## – Farm Session Info – Total active & disconnected sessions
    ##
    ## You are free to use this script in your environment but please e-mail me for any improvements.
    ################################################################################################
    if ((Get-PSSnapin „Citrix.*” -EA silentlycontinue) -eq $null) {
    try { Add-PSSnapin Citrix.* -ErrorAction Stop }
    catch { write-error „Error loading XenApp Powershell snapin”; Return }
    }
    # Change the below variables to suit your environment
    #==============================================================================================
    # Servers belongs to this worker group only evaluated
    $WorkerGroupName = „Weekly Reboot”
    # Default load evaluator assigned to servers.
    $defaultLE = „Default”
    # License Server Name for Citrix Farm to check the license usage.
    $LicenseServer = „clicense.us.wmgi.com”
    # License Type to be defined [Eg: @(„MPS_PLT_CCU”, „MPS_ENT_CCU”)].
    # The license file can be in Enterprise or Platinum versions.
    $LicenseTypes = @(„MPS_ENT_CCU”,”MPS_PLT_CCU”)
    # Only change this if you have changed the default port to custom port
    $RDPPort = „3389”
    $ICAPort = „1494”
    $maxUpTimeDays = „7”
    $sessionReliabilityPort = „2598”
    $Amberram = „70”
    $Redram = „95”
    # E-mail report details
    $emailFrom = „WMT.Monitoring@wright.com”
    #$emailTo = „rajat.gupta@wright.com,Jesudass.Chinapan@wright.com”
    #$emailTo = „WMTInfrasupport@wmt.com,WMTITISCitrix@wmt.com,dan.gabrielson@wmt.com,Micheal.Cooley@wmt.com,Lakshmanan.Veluchamy@wmt.com,WMTITISL3@wmt.com”
    $emailTo = „WrightInfrasupport@wright.com,WMTITISCitrix@wmt.com”
    $smtpServer = „exch-f01.us.wmgi.com”
    $emailSubject = „Wright Health Check Report 6.5 [Citrix] ”
    # Identifies the current directory path and creates logs there.
    $currentDir = Split-Path $MyInvocation.MyCommand.Path
    $logfile = Join-Path $currentDir („wmt.log”)
    $resultsHTM = Join-Path $currentDir („wsm_Health_Check_Results.htm”)
    # Images are used as the company logo for better presentation
    $ImgHdr = Join-Path $currentDir („header1.jpg”)
    $ImgFtr = Join-Path $currentDir („footer1.jpg”)
    $Image1path = Join-Path $currentDir („wmt.gif”)
    $Image2path = Join-Path $currentDir („cts.gif”)
    $Signaturepath = Join-Path $currentDir („cts_sign.gif”)
    # Table Header creates based on the number of header names defined
    $headerNames = „FolderPath”, „Ping”, „Logons”, „Active” , „Disconnected”, „LoadEvaluator”, „RDPPort”, „GroupPolicy” , „ICAPort”, „IMA”, „CGPPort” , „UserProfile” , „CitrixPrint”, „WMI”, „Spooler” , „Uptime” , „RAMUsage” , „DiskFree”, „ServerLoad”
    $headerWidths = „6”, „4”, „4”, „4”, „4” , „4” , „4”, „4”, „4”, „4”, „4”, „4” , „4” , „4”, „4” ,”4″ , „4” , „4” , „4”
    #==============================================================================================
    # Functions used in the Main program
    #==============================================================================================
    #==============================================================================================
    # This function will check the license usage report on the license server and will report the current usage
    #==============================================================================================
    Function CheckLicense()
    {
    if(!$LicenseServer) { „No License Server Name defined” | LogMe -Error; $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    if(!$LicenseTypes) { „No License Type defined” | LogMe -Error; $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    # Declare the variables to capture and calculate the License Usage
    [int]$TotalLicense = 0; [int]$InUseLicense = 0; [int]$PercentageLS = 0; $LicenseResult = ” ”
    # Error Handling if the server is not accessible for the license details or WMI issues
    Try
    { if(Get-Service -Display „Citrix Licensing” -ComputerName $LicenseServer -ErrorAction Stop) { „Citrix Licensing service is available.” | LogMe }
    else { „Citrix Licensing’ service is NOT available.” | LogMe -Error; Return „Error; Check Logs” }
    Try { if($licensePool = gwmi -class „Citrix_GT_License_Pool” -Namespace „ROOT\CitrixLicensing” -comp $LicenseServer -ErrorAction Stop)
    { „License Server WMI Class file found” | LogMe -Display
    $LicensePool | ForEach-Object{
    foreach ($Ltype in $LicenseTypes)
    { if ($_.PLD -match $Ltype) { $TotalLicense = $TotalLicense + $_.count; $InUseLicense = $InUseLicense + $_.InUseCount } } }
    „The total number of licenses available: $TotalLicense ” | LogMe
    „The number of licenses are in use: $InUseLicense ” | LogMe
    if(!(($InUseLicense -eq 0) -or ($TotalLicense -eq 0 ))) { $PercentageLS = (($InUseLicense / $TotalLicense ) * 100); $PercentageLS = „{0:N2}” -f $PercentageLS }
    if($PercentageLS -gt 90) { „The License usage is $PercentageLS % ” | LogMe -Error }
    elseif($PercentageLS -gt 80) { „The License usage is $PercentageLS % ” | LogMe -Warning }
    else { „The License usage is $PercentageLS % ” | LogMe }
    $LicenseResult = „$InUseLicense [ $PercentageLS % ]”; return $LicenseResult
    }
    } Catch {
    $ErrorMessage = $_.Exception.Message
    $FailedItem = $_.Exception.ItemName
    „License Server WMI Class file failed. An Error Occured while capturing the License information” | LogMe -Error
    „You may need to uninstall your License Server and reinstall.” | LogMe -Error
    „There are known issues with doing an in place upgrade of the license service.” | LogMe -Error
    $LicenseResult = ” Error; Check Detailed Logs „; return $LicenseResult }
    } Catch { „Error returned while checking the Licensing Service. Server may be down or some permission issue” | LogMe -error; return „Error; Check Detailed Logs” }
    }
    #================================================================================================
    # The function will check the service using its display name. If the service could not find, then return a value as N/A
    Function CheckService() { Param($ServiceName)
    #if (!(Get-Service -Name $ServiceName -ComputerName $server -ErrorAction SilentlyContinue) ) { „$ServiceName is not available…” | LogMe; $ServiceResult = „N/A” }
    if (!(Get-Service -Display $ServiceName -ComputerName $server -ErrorAction SilentlyContinue) ) { „$ServiceName is not available…” | LogMe; $ServiceResult = „N/A” }
    else {
    if ((Get-Service -Display $ServiceName -ComputerName $server).Status -Match „Running”) { „$ServiceName is running…” | LogMe; $ServiceResult = „Success” }
    else { „$ServiceName is not running” | LogMe -display -error; $ServiceResult = „Error” }
    }
    return $ServiceResult
    }
    #==============================================================================================
    # The function will log the data / result into a logfile. The data is send to function as parameter or a piped command output
    Function LogMe() {
    Param( [parameter(Mandatory = $true, ValueFromPipeline = $true)] $logEntry,
    [switch]$display,
    [switch]$error,
    [switch]$warning,
    [switch]$progress)
    if ($error) { $logEntry = „[ERROR] $logEntry” ; Write-Host „$logEntry” -Foregroundcolor Red }
    elseif ($warning) { Write-Warning „$logEntry” ; $logEntry = „[WARNING] $logEntry” }
    elseif ($progress) { Write-Host „$logEntry” -Foregroundcolor Green }
    elseif ($display) { Write-Host „$logEntry” }
    #$logEntry = ((Get-Date -uformat „%D %T”) + ” – ” + $logEntry)
    $logEntry | Out-File $logFile -Append
    }
    #==============================================================================================
    # The function will check the ping response to the server and reports failure
    Function Ping ([string]$hostname, [int]$timeout = 200) {
    $ping = new-object System.Net.NetworkInformation.Ping #creates a ping object
    try { $result = $ping.send($hostname, $timeout).Status.ToString() }
    catch { $result = „Failure” }
    return $result
    }
    #==============================================================================================
    # The function check the response from the port like a telnet query. If ICA port, then it check for the ICA response too
    Function Check-Port() { param ([string]$hostname, [string]$port)
    try { $socket = new-object System.Net.Sockets.TcpClient($hostname, $Port) } #creates a socket connection to see if the port is open
    catch {
    $socket = $null
    „Socket connection on $port failed” | LogMe -display -error
    return $false }
    if($socket -ne $null) { „Socket Connection on $port Successful” | LogMe
    if ($port -eq „1494”) {
    $stream = $socket.GetStream() #gets the output of the response
    $buffer = new-object System.Byte[] 1024
    $encoding = new-object System.Text.AsciiEncoding
    Start-Sleep -Milliseconds 500 #records data for half a second
    while($stream.DataAvailable) {
    $read = $stream.Read($buffer, 0, 1024)
    $response = $encoding.GetString($buffer, 0, $read)
    #Write-Host „Response: ” + $response
    if($response -like ‚*ICA*’){
    „ICA protocol responded” | LogMe
    return $true }
    }
    „ICA did not response correctly” | LogMe -display -error
    return $false
    } else { return $true }
    } else { „Socket connection on $port failed” | LogMe -display -error; return $false }
    }
    #===========================================================================================
    # HTML Report Formating Part
    #===========================================================================================
    Function writeHtmlHeader { param($title, $fileName, $TotalServers)
    $date = ( Get-Date -format R)
    $head = @”
    $title

    $title $date
    Total Number of Wright Citrix Servers: $TotalServers
    Citrix License Usage: $LicenseReport
    Total Active Sessions: $TotalActiveSessions
    Total Disconnected: $TotalDisconnectedSessions
    „@
    $head | Out-File $fileName
    }
    # ==============================================================================================
    Function writeTableHeader { param($fileName)
    $tableHeader = @”
    ServerName
    „@
    $i = 0
    while ($i -lt $headerNames.count) {
    $headerName = $headerNames[$i]
    $headerWidth = $headerWidths[$i]
    $tableHeader += „$headerName
    $i++ }
    $tableHeader += „”
    $tableHeader | Out-File $fileName -append
    }
    # ==============================================================================================
    Function writeData { param($data, $fileName)
    $data.Keys | sort | foreach {
    $tableEntry += „”
    $computerName = $_
    $tableEntry += („$computerName”)
    #$data.$_.Keys | foreach {
    $headerNames | foreach {
    #”$computerName : $_” | LogMe -display
    try {
    if ($data.$computerName.$_[0] -eq „SUCCESS”) { $bgcolor = „#387C44”; $fontColor = „#FFFFFF” }
    elseif ($data.$computerName.$_[0] -eq „WARNING”) { $bgcolor = „#FF7700”; $fontColor = „#FFFFFF” }
    elseif ($data.$computerName.$_[0] -eq „INFO”) { $bgcolor = „#ffff99”; $fontColor = „#000000” }
    elseif ($data.$computerName.$_[0] -eq „ERROR”) { $bgcolor = „#FF0000”; $fontColor = „#FFFFFF” }
    else { $bgcolor = „#CCCCCC”; $fontColor = „#003399” }
    $testResult = $data.$computerName.$_[1]
    }
    catch {
    $bgcolor = „#CCCCCC”; $fontColor = „#003399”
    #$bgcolor = „#AEB404”; $fontColor = „#4000FF”
    $testResult = „N/A”
    }
    $tableEntry += („$testResult”)
    }
    $tableEntry += „”
    }
    $tableEntry | Out-File $fileName -append
    }
    # ==============================================================================================
    Function writeHtmlFooter
    {
    param($fileName)
    @”
    NOTE: The above results are generated from an automation task created by Wright Citrix Team. Any issues reported in the above report will be actioned by Wright Citrix Team
    Author: Wright Citrix Team Email: rajat.gupta@wright.com ; WMTITISCitrix@wmt.com
    „@ | Out-File $FileName -append
    }
    # END OF THE FUNCTIONS
    #=================================================================================================
    # ==============================================================================================
    # ======= MAIN SCRIPT =======
    # ==============================================================================================
    rm $logfile -force -EA SilentlyContinue
    $date1 = Get-Date -format R
    „Checking server health…… ($date1)” | LogMe -display -progress
    $TotalServers = 0
    $allResults = @{}
    # Calling the license checking function here
    „Checking Citrix License usage on $LicenseServer” | LogMe -Display
    $LicenseReport = CheckLicense
    # Get session list once to use throughout the script
    $sessions = Get-XASession
    $WorkerGroupServers = Get-XAWorkerGroup $WorkerGroupName
    $servers = $WorkerGroupServers.ServerNames | sort-object $_.ServerNames
    #$servers = „C1″,”C10″,”C11″,”C12″,”C13″,”C14″,”C15″,”C16″,”C17″,”C18″,”C19″,”C2″,”C20″,”C23″,”C24″,”C25″,”C26″,”C27″,”C28″,”C29″,”C3″,”C30″,”C4″,”C5″,”C6″,”C7″,”C8″,”QTSVPW8CTX01″,”QTSVPW8CTX02″,”QTSVTW8CTX01″,”QTSVTW8CTX02”
    #$servers= „C1″,”C10″,”C6″,”QTSVPW8CTX01”
    foreach($server in $servers){
    $tests = @{}
    „———————————————————” | LogMe
    $server | LogMe -display -progress
    $TotalServers = $TotalServers + 1
    # Check Folder Path
    $folder= (Get-XAServer -ServerName $server | % {$_.FolderPath})
    if ($folder -ne $null)
    {
    $tests.FolderPath = „DISPLAY”, $folder.trim(„Servers/”)
    „$folder” | LogMe
    }
    else
    {
    $tests.FolderPath = „ERROR”, $folder
    }
    # Ping server
    $result = Ping $server 100
    if ($result -ne „SUCCESS”)
    {
    $tests.Ping = „ERROR”, $result
    „Ping Results : $result. Skipping rest of the tests” | LogMe -display -error
    }
    else
    {
    $tests.Ping = „SUCCESS”, $result
    „Ping Results : $result.” | LogMe
    # Check server logons
    if((Get-XAServer -ServerName $server).LogOnsEnabled -eq $false)
    {
    „Logons are disabled on this server” | LogMe -display -error
    $tests.Logons = „ERROR”, „Disabled”
    }
    else
    {
    „Logons are enabled on this server” | LogMe
    $tests.Logons = „SUCCESS”,”Enabled”
    }
    # Test Session Reliability port
    if (Check-Port $server $sessionReliabilityPort)
    { $tests.CGPPort = „SUCCESS”, „Success” }
    else { $tests.CGPPort = „ERROR”, „No response” }
    # Check Load Evaluator
    if ((Get-XALoadEvaluator -ServerName $server).LoadEvaluatorName -ne $defaultLE)
    {
    #”Non-default Load Evaluator assigned” | LogMe -display -warning
    $LE = (Get-XALoadEvaluator -ServerName $server)
    $tests.LoadEvaluator = „SUCCESS”, $LE
    „$LE Load Evaluator assigned” | LogMe -display
    }
    else
    {
    „Default Load Evaluator assigned” | LogMe
    $tests.LoadEvaluator = „DISPLAY”, $defaultLE
    }
    # Report on active server sessions
    #$activeServerSessions = [array]($sessions | ? {$_.State -eq „Active” -and $_.Protocol -eq „Ica” -and $_.ServerName -match $server})
    $activeServerSessions = [array]($sessions | ? {$_.State -eq “Active” -and $_.Protocol -eq “Ica” -and $_.ServerName -eq $server})
    if ($activeServerSessions)
    {
    $totalActiveServerSessions = $activeServerSessions.count
    }
    else
    {
    $totalActiveServerSessions = 0
    }
    $tests.Active = „SUCCESS”, $totalActiveServerSessions
    „Number of active sessions on the server: $totalActiveServerSessions” | LogMe
    # Report on disconnected sessions
    $discServerSessions = [array]($sessions | ? {$_.State -eq „Disconnected” -and $_.Protocol -eq „Ica” -and $_.ServerName -match $server})
    if ($discServerSessions)
    {
    $totalDiscServerSessions = $discServerSessions.count
    }
    else
    {
    $totalDiscServerSessions = 0
    }
    $tests.Disconnected = „SUCCESS”, $totalDiscServerSessions
    „Number of disconnected sessions on the server: $totalDiscServerSessions” | LogMe
    # Creates a warnig if both active and disconnected sessions are zero
    if (($totalActiveServerSessions -eq 0) -and ($totalDiscServerSessions -eq 0))
    {
    $tests.Active = „INFO”, $totalActiveServerSessions
    $tests.Disconnected = „INFO”, $totalDiscServerSessions
    }
    # Test ICA connectivity
    if (Check-Port $server $ICAPort)
    {
    $tests.ICAPort = „SUCCESS”, „Success”
    }
    else
    {
    $tests.ICAPort = „ERROR”,”No response”
    }
    # Test RDP connectivity
    if (Check-Port $server $RDPPort)
    {
    $tests.RDPPort = „DISPLAY”, „Success”
    }
    else
    {
    $tests.RDPPort = „SUCCESS”, „Disabled”
    }
    # Check the IMA service
    $ServiceOP = CheckService („Citrix Independent Management Architecture”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.IMA = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.IMA = „SUCCESS”, $ServiceOP
    }
    # Checks the Print Spooler service
    $ServiceOP = CheckService („Print Spooler”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.Spooler = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.Spooler = „SUCCESS”, $ServiceOP
    }
    # Checks the Citrix Print Manager service
    $ServiceOP = CheckService („Citrix Print Manager Service”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.CitrixPrint = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.CitrixPrint = „SUCCESS”, $ServiceOP
    }
    # Checks the Group policy Client service
    $ServiceOP = CheckService („Group Policy Client”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.GroupPolicy = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.GroupPolicy = „SUCCESS”, $ServiceOP
    }
    # Checks the User profile service
    $ServiceOP = CheckService („User Profile Service”)
    if ($ServiceOP -eq „Error”)
    {
    $tests.UserProfile = „ERROR”, $ServiceOP
    }
    else
    {
    $tests.UserProfile = „SUCCESS”, $ServiceOP
    }
    # Test WMI
    try { $wmi=Get-WmiObject -class Win32_OperatingSystem -computername $server }
    catch { $wmi = $null }
    if ($wmi -ne $null)
    {
    $tests.WMI = „SUCCESS”, „Success”
    $LBTime=$wmi.ConvertToDateTime($wmi.Lastbootuptime)
    [TimeSpan]$uptime=New-TimeSpan $LBTime $(get-date)
    if ($uptime.days -gt $maxUpTimeDays){
    „Server reboot warning, last reboot: {0:D}” -f $LBTime | LogMe -display -warning
    $tests.Uptime = „WARNING”, $uptime.days
    } else {
    $tests.Uptime = „SUCCESS”, $uptime.days
    }
    }
    else
    {
    $tests.WMI = „ERROR”,”Error”
    „WMI connection failed – check WMI for corruption” | LogMe -display -error
    }
    # If the IMA service is running, check the server load
    if ($tests.IMA[0] -eq „Success”) {
    $CurrentServerLoad = Get-XAServerLoad -ServerName $server
    #$CurrentServerLoad.GetType().Name|LogMe -display -warning
    if( [int] $CurrentServerLoad.load -lt 7500) {
    „Serverload is low” | LogMe
    $tests.Serverload = „SUCCESS”, ($CurrentServerload.load)
    }
    elseif([int] $CurrentServerLoad.load -lt 9000) {
    „Serverload is Medium” | LogMe -display -warning
    $tests.Serverload = „WARNING”, ($CurrentServerload.load)
    }
    else {
    „Serverload is High” | LogMe -display -error
    $tests.Serverload = „ERROR”, ($CurrentServerload.load)
    }
    $CurrentServerLoad = 0
    }
    #RAM Usage
    #$OS = (Get-WmiObject Win32_OperatingSystem -computername $server).caption
    try { $RAM = Get-WmiObject -Class Win32_OperatingSystem -computername $server | Select-Object Name, TotalVisibleMemorySize, FreePhysicalMemory }
    catch { $RAM = $null }
    if ($RAM -ne $null )
    {
    $tests.RAM = „SUCCESS”, „Success”
    $TotalRAM = $RAM.TotalVisibleMemorySize/1MB
    $FreeRAM = $RAM.FreePhysicalMemory/1MB
    $UsedRAM = $TotalRAM – $FreeRAM
    $RAMPercentused = ($usedRAM / $TotalRAM) * 100
    $TotalRAM = [Math]::Round($TotalRAM, 2)
    $FreeRAM = [Math]::Round($FreeRAM, 2)
    $UsedRAM = [Math]::Round($UsedRAM, 2)
    $RAMPercentused = [Math]::Round($RAMPercentUsed, 2)
    $RAMPUsed = „$RAMPercentused%”
    „RAM Usage: $RAMPUsed” | LogMe
    if ($RAMPercentused -gt $Redram){
    $tests.ramusage = „ERROR”, $RAMPUsed
    } elseif (($RAMPercentused -gt $Amberram) -AND ($RAMPercentused -lt $Redram)) {
    $tests.ramusage = „WARNING”, $RAMPUsed
    } else {
    $tests.ramusage = „SUCCESS”, $RAMPUsed
    }
    }
    else
    {
    $tests.RAM = „ERROR”,”Error”
    „WMI connection failed – check WMI for corruption” | LogMe -display -error
    }
    }
    #Hard Disk
    try { $HardDisk = Get-WmiObject Win32_LogicalDisk -ComputerName $server -Filter „DeviceID=’C:’” | Select-Object Size,FreeSpace }
    catch { $HardDisk = $null }
    if ($HardDisk -ne $null)
    {
    $DiskTotalSize = $HardDisk.Size
    $DiskFreeSpace = $HardDisk.FreeSpace
    $PercentageDS = (($DiskFreeSpace / $DiskTotalSize ) * 100); $PercentageDS = „{0:N2}” -f $PercentageDS
    $DSP =”$PercentageDS%”
    if( $PercentageDS -gt 15)
    { „Disk Free is normal: $DSP” | LogMe
    $tests.DiskFree = „SUCCESS”, $DSP
    }
    elseif( $PercentageDS -lt 15)
    { „Disk Free is Low: $DSP” | LogMe
    $tests.DiskFree = „WARNING”, $DSP
    }
    elseif( $PercentageDS -lt 5)
    { „Disk Free is normal: $DSP” | LogMe
    $tests.DiskFree = „ERROR”, $DSP
    }
    elseif( $PercentageDS -eq 0)
    { „Disk Free test failed” | LogMe -error;
    $tests.DiskFree = „ERROR”, „Err”
    } }
    else
    { $tests.DiskFree = „ERROR”, ($PercentageDS)
    „Disk Free is Critical” | LogMe -display -error
    }
    $PercentageDS = 0
    $allResults.$server = $tests
    }
    # Get farm session info
    $ActiveSessions = [array]($sessions | ? {$_.State -eq „Active” -and $_.Protocol -eq „Ica”})
    $DisconnectedSessions = [array]($sessions | ? {$_.State -eq „Disconnected” -and $_.Protocol -eq „Ica”})
    if ($ActiveSessions) { $TotalActiveSessions = $ActiveSessions.count }
    else { $TotalActiveSessions = 0 }
    if ($DisconnectedSessions) { $TotalDisconnectedSessions = $DisconnectedSessions.count }
    else { $TotalDisconnectedSessions = 0 }
    „Total Active Sessions: $TotalActiveSessions” | LogMe -display
    „Total Disconnected Sessions: $TotalDisconnectedSessions” | LogMe -display
    # Write all results to an html file
    writeHtmlHeader $emailSubject $resultsHTM $TotalServers
    writeTableHeader $resultsHTM
    $allResults | % { writeData $allResults $resultsHTM }
    writeHtmlFooter $resultsHTM
    #=============================================================================================
    # Emailing Part
    #=============================================================================================
    $msg = new-object System.Net.Mail.MailMessage
    $msg.From=$emailFrom
    $msg.to.Add($emailTo)
    $msg.Subject=$emailSubject
    $msg.IsBodyHtml=$true
    # Images are found by the ‚COntentID-CID’ in the body of the message. Both logos to be paced in the same directory where we save the script
    $att = new-object System.Net.Mail.Attachment($ImgHdr)
    $att.ContentDisposition.Inline = $True
    $att.ContentDisposition.DispositionType = „Inline”
    $att.ContentType.MediaType = „image/jpeg”
    $att.ContentId = „header”
    $att1 = new-object System.Net.Mail.Attachment($ImgFtr)
    $att1.ContentDisposition.Inline = $True
    $att1.ContentDisposition.DispositionType = „Inline”
    $att1.ContentType.MediaType = „image/jpeg”
    $att1.ContentId = „Signature”
    $msg.Body=(gc $resultsHTM) | Out-String
    $msg.Attachments.Add($logfile)
    $msg.Attachments.Add($att)
    $msg.Attachments.Add($att1)
    $smtp = new-object System.Net.Mail.SmtpClient
    $smtp.host=$smtpServer
    $smtp.Send($msg)
    Start-Sleep 5
    $att.Dispose()
    $att1.Dispose()
    $msg.Dispose()
    Write-host „Email Sent”
    #======================= END OF MAIN PROGRAM ++++++++++++++++++++++++++++++++++++++++++++++
    ###############################################################################################

    Like

Leave a comment