So far this week, we’ve taken a look at creating an inventory of a XenApp 6 farm and explored sending email reports of what we’ve gathered. We also took a look at checking out application consistency and publishing settings, one of the most common issues we find at customer sites. Now we’re going to jump into basic networking and logging with PowerShell, and how you can use it to make sure your servers are up. We’ll also touch on the topics of error catching and piping.

 The good news is that, if your health check tests are working well, this script shouldn’t uncover much new (it will alert you to servers that have logons disabled), but the concepts can be combined with other scripts or other server types.

Step 1. Starting the Script

One new thing that you’ll notice below is the section with “Out-File” and the pipe symbol ( “|” ). The pipe symbol essentially means: take the output from the left side, and send it to the cmdlet on the right. In this case, the output is pure text and it’s being sent to a cmdlet called “Out-File”, which writes the content to a file. We write the echo command twice so that we see the output in both the console and the log file.

$log_file=<span class="code-quote">"C:\logs\logfile.log"</span>
echo <span class="code-quote">"Checking server uptime..."</span>
echo <span class="code-quote">"Checking server uptime..."</span> | Out-File $log_file -width 240 -Append #logs the result
$servers=Get-XAServer 

Step 2. Pinging the Servers

We’ll start off with the easiest way to see if a server is up: the ping. We’ll test two methods – by IP and by DNS host name. If DNS isn’t properly resolving, then depending on how you have your environment set up you may run into issues.

foreach($server in $servers){
    echo <span class="code-quote">"`n**** $server ****"</span>
    echo <span class="code-quote">"`n**** $server ****"</span> | Out-File $log_file -width 240 -Append #logs the result
    $ping = <span class="code-keyword">new</span>-object <span class="code-object">System</span>.Net.NetworkInformation.Ping #creates a ping object
    $dns=$server.ServerName
    $ip=$server.IPAddresses

    $result=$ping.send($dns,100).Status.ToString()
    echo <span class="code-quote">"Ping $server by hostname: $result"</span>
    echo <span class="code-quote">"Ping $server by hostname: $result"</span> | Out-File $log_file -width 240 -Append #logs the result
    $result=$ping.send($ip,100).Status.ToString()
    echo <span class="code-quote">"Ping $server by IP: $result"</span>
    echo <span class="code-quote">"Ping $server by IP: $result"</span> | Out-File $log_file -width 240 -Append #logs the result
   

 
To ping the server, we create a Ping object, and we’ll grab the DNS and IP name from the server properties. We’ve set the second parameter for the $ping.send method to 100, which means that the script will wait 100 milliseconds before assuming it won’t receive a response. If your environment is latent, you might want to increase this. Please note that the script will wait that amount of time for a ping to return before continuing – setting it to ten seconds will mean that the script will either go as soon as it gets a response, or it will hold for 10 seconds and not do anything.

Step 3. Check for Enabled Logons

In this section of the code, lets make sure the server has logons enabled. We can do this by checking the server properties.

    <span class="code-keyword">if</span>($server.LogOnsEnabled -eq $<span class="code-keyword">false</span>){
        Write-Host <span class="code-quote">"Logons are disabled on <span class="code-keyword">this</span> server!"</span> -ForegroundColor Red
        echo <span class="code-quote">"Logons are disabled on <span class="code-keyword">this</span> server!"</span> | Out-File $log_file -width 240 -Append #logs the result
    }




If you’re paying close attention, you’ll notice I used a different command to output the information to console: Write-Host. This command gives us more control over the visuals of how text should appear – in this case, we’ve changed the text color to Red to make it more visible in the console.

Step 4. Port Check!

So now we’ve confirmed logons are enabled and the server is up. Let’s make sure the port is open:

    <span class="code-keyword">if</span>($result -eq <span class="code-quote">"Success"</span>){
        <span class="code-keyword">try</span> {
            $socket = <span class="code-keyword">new</span>-object <span class="code-object">System</span>.Net.Sockets.TcpClient($ip, $server.IcaPortNumber) #creates a socket connection to see <span class="code-keyword">if</span> the port is open
        } <span class="code-keyword">catch</span> {
            $socket = $<span class="code-keyword">null</span>
        }




We see a couple of things here – first off, we’ll only continue if the ping resulted in a success. We’ll then attempt to make a connection – if it fails, the script will throw an exception, so we want to make sure we catch it instead of just aborting the script as would normally occur. We check to see if the port is open by creating a new TcpClient object with the IP of the server and the ICA port number.

Step 5. ICA Listener?

Now, if it manages to connect, we’ll almost definitely be in the clear, but just to make sure let’s check to see whether it’s actually ICA listening on that port and not some other service.

        <span class="code-keyword">if</span>($socket -ne $<span class="code-keyword">null</span>) {
            echo <span class="code-quote">"Socket Connection Successful."</span>
            echo <span class="code-quote">"Socket Connection Successful."</span> | Out-File $log_file -width 240 -Append #logs the result
            $stream = $socket.GetStream() #gets the output of the response
                   
            $buffer = <span class="code-keyword">new</span>-object <span class="code-object">System</span>.<span class="code-object">Byte</span>[] 1024
            $encoding = <span class="code-keyword">new</span>-object <span class="code-object">System</span>.Text.AsciiEncoding

            Start-Sleep -Milliseconds 500 #records data <span class="code-keyword">for</span> half a second
            <span class="code-keyword">while</span>($stream.DataAvailable)
            {
                $read = $stream.Read($buffer, 0, 1024)  
                $response=$encoding.GetString($buffer, 0, $read)
                <span class="code-keyword">if</span>($response -like '*ICA*'){
                    Write-Host <span class="code-quote">"ICA protocol  found."</span> -ForegroundColor Green
                    echo <span class="code-quote">"ICA protocol  found."</span> | Out-File $log_file -width 240 -Append #logs the

result
                } <span class="code-keyword">else</span> {
                    echo <span class="code-quote">"Something <span class="code-keyword">else</span> responded."</span>
                    echo <span class="code-quote">"Something <span class="code-keyword">else</span> responded."</span> | Out-File $log_file -width 240 -Append #logs

the result
                }
            }
           
        } <span class="code-keyword">else</span> {
            echo <span class="code-quote">"Socket connection failed."</span>
            echo <span class="code-quote">"Socket connection failed."</span> | Out-File $log_file -width 240 -Append #logs the result
        }
    }
}

Looks scary! Let’s break it down. First off, if the socket did connect, we’ll get the stream of what’s happening. First we set $stream to the socket stream, $buffer to act as a holder, and $encoding to help us translate the text. Then we’ll wait a half second for a response from the port. If we get any kind of a response, $stream will be storing the data and we can pass that to a temporary variable called $read. We can then translate the response using $encoding to a regular string. Phew.

Now the fun stuff – we’ve seen “-eq” and “-ne” before to compare variables, but now we see “-like”. This operator allows us to grab partial strings, which we want to do in this case. If ‘ICA’ appears anywhere in the string (the asterisks act as wildcards), we’ll get a true response. Notice we output that to the console in green text.

Step 6. Check the Log File

If we take a look at the log file, we’ll see the same output as we saw in the console. This is useful for tracking linear information, but it’s also great for creating tabular data (.csv’s, for example) that we can then analyze in something like Excel. This is where PowerShell can become extremely powerful – the possibilities become vast for things like analytics or inventories.

Step 7. Get the Code

Get the code at the XenApp Code Share site or download it at the direct link here.

Step 8. Find Out More!

More posts are going up the rest of the week – if you want to learn more, keep watch on the Citrix blogs, follow me on Twitter (@mcbogo), and sign up for next week’s TechTalk that will go over both XenApp and XenDesktop programming. Go sign up for the Essentials for using Windows PowerShell with XenApp and XenDesktopset for Tuesday, August 24 from 2pm to 3pm EST. And if you’re interested in PowerShell scripting for XenDesktop, make sure you check out Ed York’s XenDesktop blog series. It’s great!