Category Archives: Software

Server QA Scripts – Settings Configuration Tool


Following on from my Server QA Scripts post, I have since created a GUI form to make the configuration a lot easier to do.  The tool is fully written in PowerShell and is uploaded to my GitHub page.

To Use


To use, just open a PowerShell windows and start the `QA-Settings-Configurator.ps1` script.

You’ll be presented with the following window.

QA GUI Page 1

Click the Set Check Location button and location the folder where your scripts are located.  Once done, you will be able to change the language (if any) and a base settings file (if any others exist).  Click Import Settings when done.

The script will then scan the scripts folder and load the selected settings file.

Select Required Checks

The next page lists all the checks available and automatically selects all the checks enabled in the settings file.

QA GUI Page 2

You can select or deselect any check that you feel best suits your environment.  For example, if you don’t use McAfee Antivirus in your environment, you wouldn’t want to check for the McAfee Antivirus agent, therefore, you would deselect the COM01 check.

Once you have finished your selections, click the Next > button.

QA Check Values

The third page has several tabs, one tab for each of the check sections.  Within each of the these tabs is a list of the checks you selected, as well as the required settings for each check.

QA GUI Page 3

Double-click each of the settings and change the values that you require for your environment, remembering to check the settings in each of the tabs.

When you are happy with your settings, select the final page.

Generate QA

QA GUI Page 4

Now that you have completed your changes, enter a short code for your QA script file.  This will be the unique code that the QA compiler will use to name your QA script file.  For example, a short code of “ACME” will generate a QA script called “QA_ACME_v3.xx.xxxx.ps1“.  Also enter a company name for the HTML reports that are generated.

Click Save Settings when you are ready, and enter a filename to save your settings as.  Generate a compiled QA script from this page too by clicking the Generate QA Script button.


Other functions

If you happen to loose your settings file, you can restore them by clicking the Restore Settings File button.  Select the location of a compiled QA script and the function will recreate the settings INI file for you.


Server QA Scripts


At the start of 2015 my company was still building a lot of new Windows servers manually (physical and virtual).  Each of these servers had a check sheet of what was completed and what wasn’t.  Sometimes stuff would be missed for one reason or another, which is why the servers typically went through a process of QA (Quality Assurance).

This QA check was a time consuming manual process that involved someone logging into each server and checking that everything was built and configured as it should be, as well as making sure all the correct tooling was installed (AV, SCOM and SCCM agents, etc).  This typically took a good 2 hours per server.  Results were filled in to an Excel spreadsheet and filed away somewhere as an audit trail.


My Solution

Fast forward to today, and those servers are now mostly built via our in-house automation process, however there is still some manual configuration that is required.  The QA process has also improved.  I have taken the manual spreadsheet and converted it into separate PowerShell scripts that are ‘compiled’ into one large script, that is just shy of 8000 lines.!

This script takes less than a minute to complete over 70 checks and write a HTML report for each viewing

My scripts are currently at version 3 and have been released into the wild so that other people can take advantage of the hard work I  put in to create them.


The Scripts

I have spent the best part of 18 months creating and tweaking these scripts.  I started with a broken system of about 40 QA checks and got them working.  I then expanded and enhanced the number and quality of the scripts as well as the underlying engine.

As of today (2016-09-06) there are 75 checks.  Hopefully with some community input and help we can increase that.


GitHub Repository

All the code is available for anyone to play with on my GitHub repository:


Screen Shot


A full QA scan against one server









Out-FancyHTML Function


For a larger project of mine, I needed to produce some fancy looking HTML reports from the data I collected.  An example of this output can be seen below.:



The screen shot shows the results of the code below running on my local laptop:

Get-Process | Select Name, CPU, Handles, Path, Company, FileVersion | Sort Name



The code takes the results of any table based output, formats it as a HTML table, then runs various colour highlighting on specific cells depending on the rules you specify.

For example, the following code will find any cell in the “Handles” column and checks the values found.  If the value is between 50 and 100, it will be coloured in pale yellow (#FFFFC0)

$html = Set-CellColour -InputObject $html -Filter 'Handles -lt 100 -and Handles -gt 50' -Colour '#ffffc0'

Several colour filters can be applied as shown in the code below.



The following code will produce something similar, and will get you on your way, you can also download it below…

# Need to set some variables first....
[string]$dt1    = (Get-Date -Format 'yyyy/MM/dd HH:mm')
[string]$un     = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name.ToLower()
[string]$server = '[server/report name here]'
[string]$report = '[report name here]'

# Vaguely based on 
Function Set-CellColour
    Param ( [Object[]]$InputObject, [string]$Filter, [string]$Colour, [switch]$Row )
        $Property = ($Filter.Split(' ')[0])
        If ($Filter.ToUpper().IndexOf($Property.ToUpper()) -ge 0)
            $Filter = $Filter.ToUpper().Replace($Property.ToUpper(), '$value')
            Try { [scriptblock]$Filter = [scriptblock]::Create($Filter) } Catch { Exit }
        } Else { Exit }

        ForEach ($input In $InputObject)
            [string]$line = $input
            If ($line.IndexOf('<tr><th') -ge 0)
                [int]$index = 0
                [int]$count = 0
                $search = $line | Select-String -Pattern '<th>(.*?)</th>' -AllMatches
                ForEach ($match in $search.Matches)
                    If ($match.Groups[1].Value -eq $Property) { $index = $count }
                If ($index -eq $search.Matches.Count) { $index = -99; Break }

            If ($line -match '<tr><td')
                $line = $line.Replace('<td></td>','<td> </td>')
                $search = $line | Select-String -Pattern '<td(.*?)</td>' -AllMatches
                If (($search -ne $null) -and ($search.Matches.Count -ne 0) -and ($index -ne -99))
                    $value = ($search.Matches[$index].Groups[1].Value).Split('>')[1] -as [double]
                    If ($value -eq $null) { $value = ($search.Matches[$index].Groups[1].Value).Split('>')[1] }
                    If (Invoke-Command $Filter)
                        If ($Row -eq $true) { $line = $line.Replace('<td>', ('<td style="background:{0};">' -f $Colour)) }
                        Else {
                            [string[]]$arr = $line.Replace('><','>■<').Split('■')
                            If ($arr[$index + 1].StartsWith('<td'))
                                $arr[$index + 1] = $arr[$index + 1].Replace($search.Matches[$index].Value, ('<td style="background:{0};">{1}</td>' -f $Colour, $value))
                                $line = [string]::Join('', $arr)
            Write-Output $line

    { }

# CSS for the output table...
[string]$css = @'
    html body       { font-family: Verdana, Geneva, sans-serif; font-size: 12px; height: 100%; margin: 0; overflow: auto; }
    #header         { background: #0066a1; color: #ffffff; width: 100% }
    #headerTop      { padding: 10px; }
    .logo1          { float: left;  font-size: 25px; font-weight: bold; padding: 0 7px 0 0; }
    .logo2          { float: left;  font-size: 25px; }
    .logo3          { float: right; font-size: 12px; text-align: right; }
    .headerRow1     { background: #66a3c7; height: 5px; }
    .serverRow      { background: #000000; color: #ffffff; font-size: 32px; padding: 10px; text-align: center; text-transform: uppercase; }
    .sectionRow     { background: #0066a1; color: #ffffff; font-size: 13px; padding: 1px 5px!important; font-weight: bold; height: 15px!important; }
    table           { background: #eaebec; border: #cccccc 1px solid; border-collapse: collapse; margin: 0; width: 100%; }
    table th        { background: #ededed; border-top: 1px solid #fafafa; border-bottom: 1px solid #e0e0e0; border-left: 1px solid #e0e0e0; height: 45px; min-width: 55px; padding: 0px 15px; text-transform: capitalize; }
    table tr        { text-align: center; }
    table td        { background: #fafafa; border-top: 1px solid #ffffff; border-bottom: 1px solid #e0e0e0; border-left: 1px solid #e0e0e0; height: 55px; min-width: 55px; padding: 0px 10px; }
    table td:first-child   { min-width: 175px; text-align: left; }
    table tr:last-child td { border-bottom: 0; }
    table tr:hover td      { background: #f2f2f2; }
    table tr:hover td.sectionRow { background: #0066a1; }

# Page header rows...
[string]$body = @"
<div id="header"> 
    <div id="headerTop">
        <div class="logo1">ACME</div>
        <div class="logo2">$report</div>
        <div class="logo3">&nbsp;<br/>Generated by $un on $dt1</div>
        <div style="clear:both;"></div>
    <div style="clear:both;"></div>
<div class="headerRow1"></div>
<div class="serverRow">$server</div>
<div class="headerRow1"></div>

# Get a list of processes, and convert to HTML... 
[string[]]$html = Get-Process | Select Name, CPU, Handles, Path, Company, FileVersion | Sort Name | ConvertTo-Html -Head $css -Body $body

# Colour some  cells depending on the filters, filters can contain any valid forumla...
$html = Set-CellColour -InputObject $html -Filter 'Handles -lt 100 -and Handles -gt 50' -Colour '#ffffc0'
$html = Set-CellColour -InputObject $html -Filter 'Handles -gt  99'                     -Colour '#ffc0c0'
$html = Set-CellColour -InputObject $html -Filter 'Handles -lt  51'                     -Colour '#c0ffc0'
$html = Set-CellColour -InputObject $html -Filter 'Name    -eq "ccmexec"'               -Colour 'Gray' -Row
$html = Set-CellColour -InputObject $html -Filter 'Name    -eq "chrome"'                -Colour '#c0c0ff'

# Output the entire HTML to a text file...
$html += '<table><tr><td class="sectionRow">&nbsp;</td></tr></table>'
$html | Out-File .\Out-FancyHTML_Result.html


Have a play, see what you think.  Either leave a comment below, or on the Reddit thread here.




‘New’ Item Cleaner


The ‘New >‘ item on the right-click menu is quite handy.  It can list a huge amount of document types for you to create new documents.  Most of the time these work, other times they don’t.



As this list grows when new applications are installed, it rarely shrinks when an application is removed.  This can lead to dead links.

Another issue with this list is custom desktops for Citrix XenApp users, or other users on locked down, permissions based terminal servers.  There may be links in the list that a particular user doesn’t have access to.



One solution is to just ignore it.  Users may log tickets sayinIg they can’t access an application they are not allowed to have, causing you to waste time and effort on chasing your tails.

While I was working with a particular Citrix XenApp install quite a few years ago, I created a script in KIX that would remove the entire list of applications, except for “Text Document”  I have recently updated this script for PowerShell and thought that I would share it with you.


 As you can see from the screen shots, all the new document links have gone except for the only one we want.


The Script

The script is listed below…

# Get all keys under the root branch...
$RegKeyItems = Get-ChildItem
ForEach ($RegKey in $RegKeyItems)
    # Check if it starts with a full stop "."
    If ($RegKey.PSChildName.StartsWith('.'))
        # Get all keys under current branch...
        $RegSubKeyItems = Get-ChildItem -Path $RegKey.PSChildName
        ForEach ($RegSubKey in $RegSubKeyItems)
            # Looking for "ShellNew"...
            If ($RegSubKey.PSChildName -eq 'ShellNew')
                # Make sure not to remove Shortcut Links or Text Documents
                If (($RegKey.PSChildName -ne '.lnk') -and ($RegKey.PSChildName -ne '.txt'))
                    # Display and delete key...
                    write-host "Deleting: $RegSubKey"
                    Remove-Item -Path \$RegSubKey -Recurse -ErrorAction SilentlyContinue
                # Same as above, checking one level deeper...
                $RegSubSubKeyItems = Get-ChildItem -Path $RegSubKey.PSChildName -ErrorAction SilentlyContinue
                ForEach ($RegSubSubKey in $RegSubSubKeyItems)
                    # Looking for "ShellNew"...
                    If ($RegSubSubKey.PSChildName -eq 'ShellNew')
                        # Make sure not to remove Shortcut Links or Text Documents
                        If (($RegSubKey.PSChildName -ne '.lnk') -and ($RegSubKey.PSChildName -ne '.txt'))
                            # Display and delete key...
                            write-host "Deleting: $RegSubSubKey"
                            Remove-Item -Path \$RegSubSubKey -Recurse -ErrorAction SilentlyContinue
# Also remove that annoying Briefcase link...
Remove-Item -Path '\Briefcase\ShellNew' -Recurse -ErrorAction SilentlyContinue


If you have any suggestions for improvements, or want to share your tweaks, leave a comment below.



download-fileNew Item Cleaner.ps1


Server Application Matrix


Please Note: This is an old application I wrote in 2011.  It is no longer updated or supported.

This tool allows you to view exactly which applications are published on which servers within your Citrix Metaframe/Presentation Server/XenApp farm. Applications are shown in tree format as shown in the management console, and servers can be shown either alphabetically or grouped in their zones

Applications can also be published or unpublished from the farm with a simple click of the mouse – as long as editing is enabled first.
It should work with all versions of Citrix Presentation Server and XenApp prior to XenApp 6.

Please note, this will only shown what’s published, not installed.



Most Microsoft Windows 2003 Servers should already have the required files installed by default. However, if this is not the case, the following links will help you download and install the pre-requisites…



  1. Download the ZIP file below and extract the file onto one of your Citrix farm servers or a network share,
  2. From one of your Presentation/XenApp servers, execute the extracted file,
  3. The following window will appear, with the current server name already filled in…


  1. Click the Build Matrix button and wait.
    Depending on the size of your farm, this could take a while. A progress counter will inform you of its status.
    Once complete, the window will change, and once resized it should show you something that looks like this…




You can also filter the list or applications and servers that are shown…



There are also a couple of options too…




If you are interested in this tool, please download it from the link below…


VMware Mobile Monitoring


If you want to quickly check on your virtual infrastructure and you’re not next to your PC/Laptop, what do you do.?

Well, VMware have released a tool that will allow you to monitor you hosts and guests.


watchlistVMware Mobile Watchlist

(Description taken directly from Google Play Store)

vSphere Mobile Watchlist enables secure vSphere infrastructure monitoring and remediation directly from your smartphone. With Watchlist, VMware administrators will be able to log in to a vCenter Server or ESXi host directly and choose virtual machines and hosts from inventory to create targeted views of objects and their properties. Remediate directly from the device with power and management operations, and delegation of tasks to onsite colleagues with linked relevant Knowledge Base (KB) articles.vSphere Mobile Watchlist brings the following key capabilities to vSphere administrators on the go:

    Search for and select a subset of VMs and hosts from your VMware vCenter Server and/or ESXi inventory to monitor in one or multiple watchlists.
    Review the status of selected Watchlist VMs and hosts from your device including state, configuration details, resource usage, health alerts, view of the VM console, and related objects.
    Alerts are linked to pertinent diagnostic information from the VMware Knowledge Base, as well as articles from the Web.
    Remediate problems directly from the device by powering on/off, resuming/suspending, connecting/disconnecting, or restarting VMs and/or hosts — or for situations where on-site remediation is required, share alert(s) along with recommended solutions in an email to team members back at the datacenter.

vSphere Mobile Watchlist is compatible with Android 4+.


Screen Shots

Below are some screen shots of my setup, showing my three hosts a a few of my running VMs…

Login Screen   Main Watchlist Screen (List View)   Main Watchlist Screen (Grid View)   ESX1 - Overview   ESX1 - Command Options   ESX1 - Task List



You can download and install it from the Google Play Store using the link below…




PRTG Network Monitor

Paessler PRTG Network MonitorIntroduction

If you want to monitor your home lab, and the devices connected to it, printers, switches, routers, etc, you can’t go wrong with the monitoring solution from Paessler, called PRTG Network Monitor.



The PRTG software has a few licencing levels, one of which is a free 3o sensor licence.  Not a free time limited demo, a free forever licence.

30 sensors might sound like a small amount when you find out what a sesnor is…

The licensing options are based on the number of sensors (not on the number of devices or IPs). We define one (1) sensor as any particular, individual monitoring entity. One sensor monitors one network service, one URL, one network connection, one port of a switch, one NetFlow export stream, one CPU load, one disk drive, etc. Please have a look at the list of supported sensor types. Monitoring one item from this list counts as one sensor.

Taken From

…however, I find that 30 is enough for what I want to monitor on my network.  There are some sensors that “bundle” more that one metric into them.  I could use more if I had them though  🙂

Network Port Monitoring

For example: monitoring a single network port counts as one sensor, but that port could return several metrics.  The HP switch I use returns the following information: Downtime, Transmitted, Packets, Broadcast Packets, Multicast Packets, CRC Errors, Undersize Packets, Oversize Packets, Fragments, Jabbers, Collisions, Packets <= 64 Byte, Packets 65 – 127 Bytes, Packets 128 – 255 Bytes, Packets 256 – 511 Bytes, Packets 512 – 1023 Bytes, Packets 1024 – 1518 Bytes, Drop Events.

That’s a lot of information from one sensor, but expected for a network port.

ESX Performance Monitoring

Another type of “bundled” sensor is the ESX Performance Monitoring one.  This gives much more useful and varied information: CPU usage, Datastore total ReadLatency, Datastore total WriteLatency, Disk read, Disk usage, Disk write, disk.deviceLatency, disk.kernelLatency, Downtime, Memory active, Memory consumed, Memory consumed, Memory swap used, Network received, Network transmitted, Network usage, Power

This is a varied collection of useful information, all collected in one sensor.  It covers the four main metrics: CPU, Memory, Disk, Network.  All of these metrics are available in graph form too, so you can see the history of this information over various time periods, from as little as the last two hours, up to a year ago.

You don’t even need to see all these metrics either.  If you are not interested in the “Power” metric for example, a few clicks later and it’s gone from all your graphs.  The data is still being collected, just not shown to you.


My Home Network Monitoring

I use it on my home network to monitor and graph the throughput of my internet router, my wireless router, and my Synology Diskstation 1813+ NAS.  I also have monitors for my three NUC ESXi hosts.

With all the data, this tool collects, you might think it’s hard to find what you are looking for, or just want a way of displaying the data to make it easier to look at.  For this, PRTG has Network Maps.  Below is my network map for my home network…


The data shown in the graphs are updated every 30 seconds or so (depending on your settings).  You can see that one of my ESXi hosts is offline at the moment, and that some of my critical virtual machines are listed.

The network map layout can be in almost any layout you can think of.  It doesn’t have to be as pretty as mine.


SCOM Maintenance Mode


Putting servers into maintenance mode within the Microsoft SCOM console is a long and tedious task, especially if you have lots of servers that need to be done all at once.

In very large environments, open the SCOM management console can take a long time, you then have to search for one of your many servers, right-click, enter maintenance mode, fill out the details required (length, reason), click OK.  Rinse and repeat for your list of servers.

My Solution

I have created an application that allows administrators to import lists of servers, and put them all into maintenance mode, with just a few clicks.  My application makes it quick and easy to search for and find the exact servers you need, add them to a list and export that list for future use.

It was written out of the need of putting large numbers of servers into maintenance mode every week for scheduled and staggered Windows patching.  Looking after 300+ servers (a small deployment), it was a pain to find the required servers and put them in to maintenance every week.

The application starts simply enough, just waiting for a list of servers to be entered.  Either by manually typing, copy/paste a list, or drag and drop and existing text file.


Main Screen

If you just want to search SCOM, you can do that too.  Click the “Search SCOM” button.  There are several special search options too.  For example, to find all servers currently in an error state, enter !e into the search field.  The full list is shown below…

!e – servers in an error state
!w – servers in a warning state
!o – servers marked as OK
!m – servers in maintenance mode
!n – servers not being monitored

Once you have found the servers you need, select them and click “Add”.  You can also right-click a server and choose Show Maintenance History to open a new window and see the maintenance history for the selected server.


Search SCOM

Searching for any Citrix servers that are currently in an error state: “CTX !E


Filtering Search Results

Clicking “Next >” from the main screen will take you to the maintenance options page where you can enter the reason for putting the selected servers into maintenance.

These options, can be exported along with the server names for reuse.

The WhatIf.? option allows you to test the maintenance procedure, without making any changes to your infrastructure.

When you are ready, click “Start/Update


Maintenance Options

In the screen shot below, I selected two Citrix Data Collector servers, and put them into maintenance mode.


Successful Operation

If your environment has any cluster services, this application will handle putting all the cluster resources into maintenance mode too, a difficult and long winded task in the SCOM console.


Change Log

Date Description
2015-03 Added: Show Maintenance History option.  Right click a server from the Search SCOM list.
2015-02 Fixed: Scheduled Task GUI
Fixed: Other GUI Issues
Added: Excluded Servers Option
2014-12 Initial Public Release



If you are interested in this tool, please download it from the link below…

download-fileSCOM Maintenance Mode.7z