Pawel Serwan Blog

Citrix, Microsoft and other stuff

Citrix XenApp Monitoring Script

18 Comments

MonitoringMonitoring any infrastructure is demanding task. Despite the numerous monitoring tools available on the market I haven’t found yet the one that would allow to monitor Citrix XenApp farms completely. Not only by checking ping, free space and if IMA service is running. What if there is a problem with other services e.g. Citrix Print Manager service or other Citrix related that hanged and doesn’t allow users to launch their app? Even though you monitor that service you will not know about that.

That is why I was looking a way to check if Citrix XenApp is really accessible and allow users to launch applications. Recently I came across great article by Stan Czerno regarding his monitoring script. It is really good piece of work from him. However for some reasons the script was not working for me and I have changed it a bit. I had the problem with
$ICA.GetNotificationReason() which alwasy got back “EventNone” even if the application launched. That’s the reason I changed the way I check if the application is really launched or not. Additionally I’ve added a way to get all XenApp servers from the farm. Original script can be found here:

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

Please check Stan post and see what you should do before launching the script or setting it as a scheduled task.

My version of the script can be found below:


# This script launches a 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.
# I run this from a Windows 7 VM and schedule it to run once per hour from 6AM to 6PM

# You must have at least Citrix Receiver for Windows 4.1 installed.
# This script has only been tested with Citrix Receiver for Windows 4.1.

# 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 C:\Scripts\LaunchPublishedApp.ps1

# You would schedule it like this:
# Program/Script: %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe
# Arguments: -ExecutionPolicy Bypass -file C:\Scripts\LaunchPublishedApp.ps1

# 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

#Original script: http://www.czerno.com/blog/post/2014/06/11/powershell-script-to-launch-a-published-application-from-one-or-more-xenapp-servers
#Modified by: Paweł Serwan, https://pawelserwan.wordpress.com/2015/01/08/citrix-xenapp-monitoring-script/
#Date: 08.01.2015
#Version: 1.3

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

#Import Citrix modules from Citrix SDK. The best would be to run the script on XenApp server or install Powershell SDK for Citrix Xenapp 6.5 where you would like to run the script.
Add-PSSnapin Citrix*

# Publish Application Name to launch
$pubapp = "PROVIDE APPLICATION NAME"


# If all servers in the farm should be tested. If you use this method you have to run the script with the account that has Citrix admin rights in the farm
$XAServers = Get-XAServer

# List of Servers to test, one or more can be listed
# If more than one, use this format: "Server1","Server2","Server3"
# $XAServers = "PROVIDE SERVER LIST"

# User name
$user = "PROVIDE USERNAME THAT SHOULD BE USED TO LAUNCH APPLICATION"

# User password
$passwd = "PROVIDE PASSWORD FOR THAT ACCOUNT"

# Domain Name
$domain = "PROVIDE THE NAME OF YOUR ACTIVE DIRECTORY DOMAIN"

# E-mail settings 
# If $emailFrom, $emailTo or $smtpServer are blank, no email will be sent
$smtpServer    = "smtp.domain.name"
# Define multiple email addresses like "email@domain.com,email2@domain.com"
$emailFrom     = "XenAppTest@domain.name"
$emailTo       = "your@email.address"
# If not using a CC address, leave the value blank
# $emailCC       = "" 

# 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 = New-Object -ComObject 'Citrix.ICAClient' 
    if($ica) { return $ica.ClientVersion } 
    else { return 0 } 
} 

# ==================== #
# ICA Logoff Function  #
# ==================== #
function Logoff-ICA () {
"Sending logoff command" | LogMe -displaynormal
$ICA.Logoff()
}

# ====================== #
# 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

    # 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)
        {
        # Buidling the ICO and starting the ICA Connection to each server
        $ICA = New-Object WFICALib.ICAClientClass
        foreach ($XAServ in $XAServers)
            {
           # $XAserver = $XAServ.ServerName
           $XAserver = $XAServ
            " " | LogMe 
            "Testing Published Application, $pubapp, on Server $XAServer" | LogMe -displaygreen
            #If you get the list of servers by running Get-XAServer leave it as below
            $ICA.Address = "$XAServer.ServerName"
            #If you provide a list of servers manually use the below
            #$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" | LogMe -displaygreen
            $LaunchTime = Get-Date
            "Connect Started at $script:LaunchTime" | LogMe -displaygreen 
            #Launch Citrix app
            $ICA.Connect()
            "Waiting for an ICA Connection" | LogMe -displaynormal 

            $a = 0
            do 
                {
        $a++
        sleep 1
        }
            until ($ICA.Connected -eq $True -or $a -ge 60)
            if ($ICA.Connected -eq $True)
            {
                sleep 40
                #Enumerate ICA connections             
                $EnumHandle = $ICA.EnumerateCCMSessions()
                $NumSessions = $ICA.GetEnumNameCount($EnumHandle )
                #"Number of live CCM sessions are:" + $NumSessions.tostring()
                for( $index = 0; $index -lt $NumSessions ;$index++)
                {
                    $sessionid = $ICA.GetEnumNameByIndex($EnumHandle, $index)
                    $ICA.StartMonitoringCCMSession($sessionid,$true)
                    $APPSERVER = $ICA.GetSessionString(0)
                    if($AppSERVER -match $XAServer)
                    {
                        "Test ICA Session found running on $AppSERVER; logging off" | LogMe -displaygreen
                        
                        $logonelapsed = GetElapsedTime $LaunchTime
                        "Time taken to logon is: $logonelapsed" | LogMe -displaygreen
                        sleep 5
                        Logoff-ICA
                       <# 
                        if ($logoffmethod -eq $True -and $typexit -eq $True)
                        { Logoff-ICA }
                        elseif ($typeexit -eq $true)
                        {
                        "Typing EXIT and pressing the ENTER key" | LogMe -displaynormal
                        sleep 2
                        $ICA.Session.Keyboard.SendKeyDown(0x45)
                        sleep 2
                        $ICA.Session.Keyboard.SendKeyDown(0x58)
                        sleep 2
                        $ICA.Session.Keyboard.SendKeyDown(0x49)
                        sleep 2
                        $ICA.Session.Keyboard.SendKeyDown(0x54)
                        sleep 2
                        $ICA.Session.Keyboard.SendKeyDown(0x0D)
                        sleep 2
                        Logoff-ICA
                        }
                        if ($logoffmethod -eq $True) { Logoff-ICA }
                        if ($logoffmethod -eq $False -and $typexit -eq $False){ Logoff-ICA }
                        #>
                    }
                    $ICA.StopMonitoringCCMSession($sessionid);     
                }
                $ICA.CloseEnumHandle($EnumHandle)
            }
            elseif ($ICA.Connected -eq $False) 
            {
                "Connection failed to server " + $XAServer | LogMe -Error
                $ICAErrors += "<p $ErrorStyle>Error Connection to server <strong>$XAServer</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" | 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   
            }

        sleep 10
        #Checking if session has terminated
        $EnumSessions = $Null
        $EnumSessions = $ICA.EnumerateCCMSessions()
        $ActiveSessions = $ICA.GetEnumNameCount($EnumSessions)
        if ($ActiveSessions.tostring() -eq 1) {"Waiting for session to end" | LogMe -displaynormal}
        $l = 0
        do {$l++; sleep 1}
        until ($EnumSessions -eq 0 -or $l -ge 60)
        If ($ActiveSessions.tostring() -eq 0) 
            {
        "Number of Active Sessions is: " + $ActiveSessions.tostring() | LogMe -displaynormal
        "Connection Ended at $(get-date)" | LogMe -displaygreen
        $connectionelapsed = GetElapsedTime $LaunchTime
        "Total Elasped Connection Time is: $connectionelapsed" | LogMe -displaygreen
        }
        }
        }
    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 (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}
}
#>
# 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
#==============================================================================================

Please let me know in case something will not work. I hope you will find this script useful in your environments.

18 thoughts on “Citrix XenApp Monitoring Script

  1. Hi
    Where, and how, exactly did you change the way to check if the app was launched.
    I’m not able to see that.

    Like

    • hi Stefan,

      you were completely right. I have pasted wrong script. Sorry for that. Please check now. I have changed the way it looks for launched app. Please check lines from 258 to 350. You should see now the difference.

      Thanks,
      Paweł

      Like

  2. Hi Pawelserwan,

    I just tried your script as we have some Problems with the original script. But your script don’t work. We are using a Windows 7 x64 machine that run the script. First of all I had to replace some text in your script, the text “&quot;” has to be replaced with “. Furhter when I run the script, I receive an error message from Citrix Receiver: Connection to XenApp Server not possible, Error in protocol Driver. In the script appears the message “There was no Window titled Citrix Receiver, the error is most likely due to the script”. Also after a reboot of the machine I have the same Errors.

    I am making something wrong?

    Regards,
    Roberto

    Like

    • hi Roberto,

      As I wrote above I pasted wrong script. Please check now.

      There is some kind of problem with formatting Powershell source code on WordPress and that is why you saw that “"”. Now should be OK.

      Please launch the script first to check if it works on Citrix XenApp 6.5 server. You must have Powershell SDK installed. And please do all the needed steps described in the comments in the script. Please remember to provide application name e.g. Notepad, user name, password, domain and then if you want to test then provide as well email configuration. And remember that you have to run the script with Powershell (x86) 🙂

      Let me know if that works now.

      Cheers,
      Paweł

      Like

  3. Hi Pawel Serwan,

    I would like to use this script but we get caught in the Windows 2008 R2 interactive logon message which needs manual intervention
    Manually clicking OK continues the launch how can this be included in the script?

    Regards Mark

    Like

    • hi Mark,

      You are right – problem is that from Windows Server 2008 there is a problem with Interactive Logon and Scheduled Tasks. Workaround is to:
      1. Create a Service Account for the Scheduled Task.
      2. Configure scheduled task with that account and set the task to run only when user is logged on.
      3. Enable Autologon for that Service Account on the server according to that MS KB article: https://support.microsoft.com/en-us/kb/310584
      You have to restart server after that and service account will log into Console session and will be able to interact with the Destkop.
      Btw – I have wrote a 2nd version of the script which works much better and faster (less than 2 minutes for about 20 servers) so you may want to check that one as well. It will have as well more options when it comes to checking servers availability.

      Hope it helps,
      Paweł

      Like

      • Hi Pawel Serwan

        We have XenApp 6 and Web Interface 5.3, I think the new script uses storefront or netscaler.
        When we launch the test the service account gets a standard company notification popup to say if you are not an authorized user please log off etc…I just wanted to know how I can press the enter key in the script so the logon continues.

        Regards Mark

        Date: Tue, 24 Mar 2015 08:42:29 +0000
        To: mark.daniels1@hotmail.co.uk

        Like

      • hey Mark,

        Use that part of the script then:

        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 YOUR WINDOW NAME” | LogMe -displaynormal
        $hwnd = (get-process YOUR PROCESS NAME).MainWindowHandle
        if ($hwnd -ne 0)
        {
        “Set Foreground Window to YOUR WINDOW” | LogMe -displaynormal
        [SFW]::SetForegroundWindow($hwnd)
        “Sending the Enter command to Window” | LogMe -displaynormal
        [System.Windows.Forms.SendKeys]::SendWait(“{ENTER}”)
        }

        Let me know if that works:)

        Like

      • Hi Pawelserwan

        I copy and paste the code and then when I run the script, I receive an error message from Citrix Receiver: Connection to XenApp Server not possible, Error in protocol Driver.

        It seems its not copying the code in the correct format can you please send me the correct format file by email?

        Like

      • hi Mark,

        Just to be sure the error shows when Citrix ICA connection starts? Then you get the Receiver window? And what happens?

        Like

      • Yes the error appears when the connection starts, Unable to launch your application cannot connect to the citrix senapp server protocol driver error. No other window opens

        Like

  4. Hi Now I have moved on and the connection starts but the next error is also from the client saying the inital application you are trying to open is currently unavaiable.

    Like

  5. hi Mark,

    Can you please try to debug the script in Powershell ISE (x86)? And let me know? Cause if you haven’t changed anything in the script inside it should work.

    Paweł

    Like

  6. hey Mark,
    The script I posted is working fine in my environment. strange you had to add that # at the beginning.

    I will send you email in the afternoon.

    Cheers,
    Paweł

    Like

  7. So I just grabbed the script to make sure that what I had grabbed before was not the issue. I am trying to utilize this on a Windows 7 64bit to connect to our Windows 2008 R2 Farm.

    I’m getting a very unusual error stating”Get-Process : Cannot find a process with the name “wfica32″. Verify the process name and call the cmdlet again.”

    This leads me to the fact that the script can not be run from anything other than the XenApp Servers, or am I missing something?

    I utilize this platform to perform all of my XenServer/XenApps PowerShell scripts with no problems. Now that I have been tasked with making sure we can actually connect to the apps, I thought this would be a great starting point (if not the total solution).

    Any possible resolution to this error would be helpful.

    Like

  8. hi William,

    I think I know where might be the problem. Can you please tell me how do you launch the script. Do you use PowerShell (x86) or do you use PowerShell 64 bit? You should launch the script with the first one. And I think that the 2nd version of the script is working much faster and is more reliant. Please check here:
    https://pawelserwan.wordpress.com/2015/03/26/powershell-citrix-xenapp-monitoring-script-ver-2-1/
    Let me know if you would still have the problem. We can talk on email then.

    Like

Leave a comment