Powershell – Part 2: Check ICA response, Check for exiestence of file and uptime of multiple remote servers

P

As always over time scripts get updated and evolve – bring a bit of a powershell novice my scripts could probably do with a great deal of evolution but here’s version 2 of the script I posted previously

I imagine this will only really be interestng to me but I thoguht I’d post it anyway – no ones forcing you to read! (if someone is forcing you to read leave a comment and I’ll contact the authorities – I’m sure it counts as some form of torture).

decisions:

  • it seemed their were too many foreach statements in the previous script that essentially did the same thing
  • output was a mess
  • the customer could need to check servers the farm deeped offline (this to check for another potential issue that I’ll post again once our resolution is tested)
  • the code needed tidying up a bit

I would have liked to include powershell modules to call the test-port function but some machines the script ran on only have powershell 1.0 installed. I decided not to load the function as a PS1 script inline as their didnt seem alot of point.

Anyway here it is for those interested:

# ICAScan.ps1
# Script to check XenApp 5 farm for the existence of 3 service effecting issues that exist(ed) with the new XenApp 5 farm

function Test-Port{

[cmdletbinding(
DefaultParameterSetName = ”,
ConfirmImpact = ‘low’
)]
Param(
[Parameter(
Mandatory = $True,
Position = 0,
ParameterSetName = ”,
ValueFromPipeline = $True)]
[array]$computer,
[Parameter(
Position = 1,
Mandatory = $True,
ParameterSetName = ”)]
[array]$port,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[int]$TCPtimeout=1000,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[int]$UDPtimeout=1000,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[switch]$TCP,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[switch]$UDP

)
Begin {
If (!$tcp -AND !$udp) {$tcp = $True}
#Typically you never do this, but in this case I felt it was for the benefit of the function
#as any errors will be noted in the output of the report
$ErrorActionPreference = “SilentlyContinue”
$report = @()
}
Process {
ForEach ($c in $computer) {
ForEach ($p in $port) {
If ($tcp) {
#Create temporary holder
$temp = “” | Select Server, Port, TypePort, Open, Notes
#Create object for connecting to port on computer
$tcpobject = new-Object system.Net.Sockets.TcpClient
#Connect to remote machine’s port
$connect = $tcpobject.BeginConnect($c,$p,$null,$null)
#Configure a timeout before quitting
$wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout,$false)
#If timeout
If(!$wait) {
#Close connection
$tcpobject.Close()
Write-Verbose “Connection Timeout”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “False”
$temp.Notes = “Connection to Port Timed Out”
}
Else {
$error.Clear()
$tcpobject.EndConnect($connect) | out-Null
#If error
If($error[0]){
#Begin making error more readable in report
[string]$string = ($error[0].exception).message
$message = (($string.split(“:”)[1]).replace(‘”‘,””)).TrimStart()
$failed = $true
}
#Close connection
$tcpobject.Close()
#If unable to query port to due failure
If($failed){
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “False”
$temp.Notes = “$message”
}
#Successfully queried port
Else{
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “TCP”
$temp.Open = “True”
$temp.Notes = “”
}
}
#Reset failed value
$failed = $Null
#Merge temp array with report
$report += $temp
}
If ($udp) {
#Create temporary holder
$temp = “” | Select Server, Port, TypePort, Open, Notes
#Create object for connecting to port on computer
$udpobject = new-Object system.Net.Sockets.Udpclient($p)
#Set a timeout on receiving message
$udpobject.client.ReceiveTimeout = $UDPTimeout
#Connect to remote machine’s port
Write-Verbose “Making UDP connection to remote server”
$udpobject.Connect(“$c”,$p)
#Sends a message to the host to which you have connected.
Write-Verbose “Sending message to remote host”
$a = new-object system.text.asciiencoding
$byte = $a.GetBytes(“$(Get-Date)”)
[void]$udpobject.Send($byte,$byte.length)
#IPEndPoint object will allow us to read datagrams sent from any source.
Write-Verbose “Creating remote endpoint”
$remoteendpoint = New-Object system.net.ipendpoint([system.net.ipaddress]::Any,0)

Try {
#Blocks until a message returns on this socket from a remote host.
Write-Verbose “Waiting for message return”
$receivebytes = $udpobject.Receive([ref]$remoteendpoint)
[string]$returndata = $a.GetString($receivebytes)
}

Catch {
If ($Error[0].ToString() -match “bRespond after a period of timeb”) {
#Close connection
$udpobject.Close()
#Make sure that the host is online and not a false positive that it is open
If (Test-Connection -comp $c -count 1 -quiet) {
Write-Verbose “Connection Open”
Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “True”
$temp.Notes = “”
}
Else {
<#
It is possible that the host is not online or that the host is online,
but ICMP is blocked by a firewall and this port is actually open.
#>
Write-Verbose “Host maybe unavailable”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “False”
$temp.Notes = “Unable to verify if port is open or if host is unavailable.”
}
}
ElseIf ($Error[0].ToString() -match “forcibly closed by the remote host” ) {
#Close connection
$udpobject.Close()
Write-Verbose “Connection Timeout”
#Build report
$temp.Server = $c
$temp.Port = $p
$temp.TypePort = “UDP”
$temp.Open = “False”
$temp.Notes = “Connection to Port Timed Out”
}
Else {
$udpobject.close()
}
}
#Merge temp array with report
$report += $temp
}
}
}
}
End {
#Generate Report
$report
}
}

#Obtain Servers List from Farm
$farm = new-Object -com “MetaframeCOM.MetaframeFarm”
$farm.Initialize(1)
$All=$farm.servers | select ServerName | %{$_.ServerName} | sort-object
$Online=$farm.zones | %{$_.OnlineServers} |select ServerName | %{$_.ServerName} | sort-object

#Date variables
$date=(get-date (get-date) -uformat %m%d%Y)

#Files to Check for
$FilePath=”c$Program”

#Define Servers to check
write-host “Online – Only checks servers the XenApp farm has marked as online (Default)”
write-host “All – Checks servers the XenApp farm (will result in errors for servers that are powered down)”
$CheckLevel=Read-host “Set Check Level (Online/All):”

if ($Checklevel -match “Online”){$Check=$Online}
elseif ($Checklevel -match “All”){$Check=$All}
else {
$Check=$Online
}

foreach ($server in $Check)
{
$warning=”0″
if (test-port -computer $server -port 1494 | where {$_.open -match “False”})
{$ICA=”DOWN”
$warning=”1″}
else
{$ICA=”UP”}

if (Test-Path -path \$server$FilePath)
{$ProgramRenamed=”yes”
$warning=”1″
rename-item -path \$server$FilePath -newname Temp.$date
}
else
{$ProgramRenamed=”no”}

$wmi=Get-WmiObject -class Win32_OperatingSystem -computer $server
$LBTime=$wmi.ConvertToDateTime($wmi.Lastbootuptime)
[TimeSpan]$uptime=New-TimeSpan $LBTime $(get-date)

if ($uptime.days -lt 1-and $uptime.hours -lt 4){
$Rebooted=”yes”
$warning=”1″}
else
{$Rebooted=”no”}

if ($warning -eq “1”){

write-host -foregroundcolor “red” $Server “| ICA is:” $ICA “| File Renamed:” $ProgramRenamed “| Rebooted in last 4 hours:” $Rebooted
}
else {write-host -foregroundcolor “green” $Server “| ICA is:” $ICA “| File Renamed:” $ProgramRenamed “| Rebooted in last 4 hours:” $Rebooted}

if ($CheckLevel -match “Online”){
write-host “The following servers are marked as Offline:”
write-host $Offline}
}

 

About the author

Stu Carroll

Citrix CTA & Director of Enterprise Technologies @ Coffee Cup Solutions

By Stu Carroll

Stu Carroll

Citrix CTA & Director of Enterprise Technologies @ Coffee Cup Solutions

Get in touch

Need help? Get in touch

Secured By miniOrange