Some great free scripting tools.

PrimalScript_box Sapien make, what I think is the best script editor available.  It’s called PrimalScript.  Not cheap, but it was the only way I know to step though a PowerShell script.  That’s changed with PowerShell 2, with it’s ISE.  But I’m still sticking with PrimalScript.

Sapien make a number of free tools available, and since I believe they preserve a wider audience, see below.

Continue reading

Check the health of your SMS 2003 & 2007 servers

I run a PowerShell script which checks the health of my 20 SMS 2003 servers.

Sure, I could install Microsoft Operations Manager (Microsoft MOM).  But there is the cost for the physical server, and Microsoft licensing to be considered.

So, instead I make do with the PowerShell script.  It’s saved me from having several server problems becoming noticeable to the customers.  (the latest example is here)

It’s crude, but it checks each of the SMS servers for:

  1. the server is alive, aka “pingable”.
  2. it’s CPU utilisation is <= 20%, and that no individual processor is running at greater than 20%.
  3. that the assorted SMS directories (inbox, Offersum etc.) are being processed.
    If a directory has greater than x files, this may be an problem.
    Curiously enough, Microsoft suggests a 10,000 file threshold.  I set it at 200 files.
  4. enough disk space exists on the SMS package shares.

Future plans?

  1. Write each check out to a log, for availability reporting.
  2. Check for “older than x days” files in the SMS directories.
  3. Make it’s output pretty, most likely via WPF.

You can download the script, and the sample server list file here.

Bookmark and Share

Getting CPU Utilisation with PowerShell

PowerShell logoI use the following piece of code in my “Check SMS Server are healthly” PowerShell scripts.  I had a case recently where the SQL Server process decided to use 80% of one CPU.  This script would have detected that problem.

$server_name = “WISEFAQDC”
$percentage_warn = 50

$cpuinfo = Get-WmiObject -ComputerName $server_name Win32_Processor

$count = 0
$cpu_utilisation_total = 0
$cpu_utilisation_average = 0
$cpu_utilisation_maximum_single_processor = 0

foreach ($cpu in $cpuinfo)
    $cpu_utilisation_total = $cpu_utilisation_total + $cpu.LoadPercentage
    $count = $count + 1
    if ($cpu.LoadPercentage -gt $cpu_utilisation_maximum_single_processor)
        $cpu_utilisation_maximum_single_processor = $cpu.LoadPercentage
$cpu_utilisation_average = $cpu_utilisation_total / $count

if ($cpu_utilisation_average -gt $percentage_warn)
    Write-Host "Server: $server_name - CPU load $cpu_utilisation_average %"
if ($cpu_utilisation_maximum_single_processor -gt $percentage_warn)
    Write-Host "Server: $server_name - Single CPU load, highest percentage is: $cpu_utilisation_maximum_single_processor %"

The output is:
Server: WISEFAQDC - CPU load 54 %
Server: WISEFAQDC - Single CPU load, highest percentage is: 82 %

There is a bug though, with Windows 2000 servers always reporting 98% utilisation.  Microsoft released hotfix KB 880086 to fix the problem.

Bookmark and Share

And here’s the PowerShell: Pinging a computer script

PowerShell logo

The first thing you might notice is that the PowerShell version is a bit shorter. 3 lines of VBscript code, compared to 1 line of PowerShell script. That is, 1 line of code to do the actual ping.

And here is a short program which demonstrates how to use PowerShell to ping a computer:

$computer_name = "WISEFAQDC"

$address_string = "Address=" + "'" + $computer_name +"'"
$ping = Get-WmiObject -Class Win32_PingStatus -Filter $address_string
if ($ping.StatusCode -ne 0)
    # the check -ne 0 means the ping check failed.
    Write-Host Server: $computer_name - Not pingable
    # the computer is visible on the network.
    Write-Host Server: $computer_name - is alive

Bookmark and Share

PowerShell: Reboot remote computers

PowerShell logo

It looks like it’s going to be a week of scripting blog posts.  Today’s script is used to reboot a list of remote computers.  Sometimes, when deploying security patches, the computers fails to reboot.  So I use this script to force reboots.  It would be a piece of cake to modify the script, so that it turns off the computers instead.

One of my customers should find that useful.  Out of 2000 computers, about 150 computers get left powered on over the weekend.

What the script does:

  • reads the list of computers to be reset from C:\computer_lists\reboot_target_list.txt
    the format of the list is COMPUTERNAME,Reboot Reason
  • “Pings” the computer to see if it’s on the network.
  • checks to see if someone is logged on.  If someone is, don’t reboot.
  • reboots the computer.

Check and reboot computers.ps1

Continue reading

PowerShell: count of files in a directory

PowerShell logoWith PowerShell, I needed to get a count of files in a particular directory.  This is what I came up with.

# Get a count of files in a directory.
$directory_file_count = "0"
$server_directory_string = "\\WISEFAQDC\c$\downloads"

# check that the directory exists.
$does_directory_exist = (Test-Path $server_directory_string)

# if it does, then continue
if ($does_directory_exist)
# file count does include directories but not a count of their contents.
$directory_file_count = (get-childitem $server_directory_string -name).count
Write-Host "Directory file count: $directory_file_count"
# directory doesn't exist
Write-Host "Directory $server_directory_string - DOES NOT EXIST"

The only problem with this code is that file count does include directories, but not their contents,  in it’s count of files.

Bookmark and Share

Reading the end of a log file with PowerShell

PowerShell logo I needed to read the last line of a log file.  PowerShell made it very, very, easy.

All you need to do is Get-Content the file, and then pipe it to Select-Object with the –last parameter set to 1.

Here is the code snippet which does that:

$failure_reason = (Get-Content $file_txt | Select-Object -last 1)

And here is a (simple) version of the PowerShell script I wrote to read though a list of computers, and dump the last line to the screen:

$windows2000_PCs = (Get-Content c:\temp\pc-list.txt)
foreach ($computer in $windows2000_PCs)
$file_txt = "\\"+ $computer + "\c$\log\install.txt"
$install_result = (Get-Content $file_txt | Select-Object -last 1)
Write-Host $computer has install result of: $install_result
Write-Host Done!

Which outputs:

BROOMFONDLE has install result of: Program installed successfully on 21 DEC 2010 – 1000hrs
MAGICTHIGHS1 has install result of: Program failed to install – Error code 1603 on 11 DEC 2010 - 1321hrs

Things to note:

  • c:\temp\pc-list.txt contains the list of computer names you wish to scan.
  • the script is not idiot-proofed error-trapped.
    ie. in a production version of this you would check that the computer being scanned is online, the install.txt file exists, and so on.
  • the Get-Content cmdlet will read though the entire file.  Select-Object will retain the –last x lines you asked for.  (for the technically minded, on my Windows 7 system, it opened the file with the following options “Desired Access: Generic Read, Disposition: Open, Options: Synchronous IO Non-Alert, Open No Recall, ShareMode: Read, Write”

Bookmark and Share