WSUS Cleanup with Powershell

If you manage a Windows Server Update Services (WSUS) server, you probably run the Server Cleanup Wizard every once and a while. It removes old and superseded updates and computers that haven’t reported their status for more than 30 days. Wouldn’t it be nice to schedule such a cleanup to run every month? Too bad there’s no command line tool I know of that can help you out with this. Powershell to the rescue!
Powershell can not only run the built-in commandlets or even those added by snapins. It can leverage the full power of the .NET Framework. Browse the MSDN Library if you want to find more cool things you can do with it. Here’s a script that uses this information to run the cleanup wizard:

Continue reading “WSUS Cleanup with Powershell”


Translate Vml to LUN Path with Powershell

While checking the vmkernel logs on our VMware ESX Servers today, I ran into some errors referencing luns using a vml string. It looks something like this: vml.827149017315617. I would like to know what lun this error is referencing, but I prefer the LUN Path notation, e.g.: vmhba1:2:137. So I wrote this Powershell VI Toolkit function that can translate the vml into the lun path:

# Function: Translate a VML (e.g.: vml.9364839746917650) to a Lun Path (e.g.: vmhba1:2:137)
function Translate-VmlToLunPath
	Return (Get-VMHost $VMhostName | Get-ScsiLun | Where {$_.ConsoleDeviceName -match $Vml}).CanonicalName

Feed it a host name and a vml string and it will return the lun path. Here’s an example script that uses this function when looking for LUNs with SCSI Reservation Errors:

# Example use in a script: Get LUNs with SCSI Reservation Conflicts
$VIServerName = "myVIServer"
$NumLines = 1000
$VC = Connect-VIServer $VIServerName
ForEach ($VMHost in Get-VMHost)
	ForEach ($Log in ($VMHost | Get-Log -Key vmkernel -NumLines $NumLines))
		$MatchedEntries = $Log.Entries | Where {$_ -match "reservation" -and $_ -match "vml.\d*"}
		ForEach ($VmlId in $matches.values)
			$myObj = "" | Select VMHost, ErrorLun
			$myObj.VMHost = $VMHost.Name
			$myObj.ErrorLun = Translate-VmlToLunPath -VMHostName $VMHost.Name -Vml $VmlId
			Return $myObj
Disconnect-VIServer -Confirm:$False


Adding Script Repository to

In an attempt to make even better 😉 I am adding a Script Repository. It can be accessed through the button in the main navigation bar at the top of the site.

The Script Repository will soon hold all of my published Powershell scripts, formatted in a easy-to-use way, including a description, the syntax-highlighted code and a download link. This will not only allow you to more easily find and use my scripts, but will also leaves more room for the general blog section of to feature more in-depth explanations of how the scripts work.

I’m looking for your feedback to make this change a real improvement. So please comment either this post or the main Script Repository page. I always read your comments.

I hope to hear from you soon.

Hugo Peeters

Regular Expression Magic in Powershell

I have been looking at regular expressions in Windows Powershell recently. Although it seems very complex, the power of regular expressions (regex) is worth the effort! Think about server naming conventions for example. It’s easy for a human to recognise a server name that begins with a location code and contains a status (Development, Test, Acceptance or Production) amongst other things. RegEx allows you to learn Powershell to recognise the same things.

The attached script contains a function that finds matches for a regular expresion and converts the named matches to object properties. Sounds complex? Take a look at this example for server names:


If you can create the regular expression, this function does the matching and objectizing. It requires no modification at all for working with regular expressions that match other kinds of things, because you name the matching groups inside the regex definition. Cool stuff!

Obj-RegEx (Rename to .ps1)



Checking VMware NTP configuration with Powershell

Thanks to the VMware VI Toolkit 1.5, checking the NTP settings on all your VMware ESX Servers is as easy as a oneliner:

Get-VMHost | Sort Name | Select Name, @{N=”NTP”;E={Get-VMHostNtpServer $_}}

VI Toolkit 1.5 Getting Started and Undocumented Functions

0. Installing
Installing or upgrading the VI Toolkit 1.5 is as easy as Next, Next, Finish. And using the new VI Toolkit shortcut on your desktop allows quick and easy access to the Toolkit. But what about running these cmdlets from your scripts or integrating it with other snapins? Read on!

1. Setting up your profile
The new desktop shortcut does two things for you: it starts powershell with the VI Toolkit snapin loaded and it runs a script which modified the look of the Powershell window ánd adds some cool extra functions. If you want to have the same functionality in your normal Powershell window and your scripts, you have to copy some stuff to your Powershell profile. First, set up your profile:

a. Start a normal Powershell window.
b. Run the following command: Test-Path $profile
c. Did it return True? Then you already have a profile file. Did it return False, do step d.
d. Create a profile file by running: New-Item $profile -ItemType File

2. Adding the snap-in
a. Open your profile by running: Invoke-Item $profile
b. Add the following line to the profile file to load the snap-in: Add-PSSnapIn VMware.VimAutomation.Core -ErrorAction SilentlyContinue

3. Adding undocumented functions
a. Open the file C:\Program Files\VMware\Infrastructure\VIToolkitForWindows\Scripts\Initialize-VIToolkitEnvironment.ps1
b. Copy the following Function Blocks to your profile file: Get-VICommand, New-DatastoreDrive, New-VIInventoryDrive, Get-VIToolkitDocumentation, Get-VIToolkitCommunity

4. Undocumented Functions?
Ok, you can read about them in the Administrator’s Guide (, but you might overlook these functions because they are not cmdlets, so Get-Command won’t show them (nor will Auto-Complete work for them).
Here’s a short description of each of them:

  • Get-VICommand: Displays all VI Toolkit cmdlets (equal to: Get-Command -PSSnapIn VMware.VimAutomation.Core);
  • New-DatastoreDrive: Allows you to browse a datastore like a drive (Example Usage: New-DatastoreDrive -Name <DriveName> -Datastore (Get-Datastore <DatastoreName>); Then jump to the drive: cd <DriveName>: );
  • New-VIInventoryDrive: Allows you to browse your Virtual Infrastructure like a drive (Example Usage: New-VIInventoryDrive -Name <DriveName> -Location (Get-Inventory <Folder-/Cluster-/ResourcePool-/HostName>); Then jump to drive: cd <DriveName>: );
  • Get-VIToolkitDocumentation: Opens the VI Toolkit Command Reference Help File;
  • Get-VIToolkitCommunity: Opens the VI Toolkit Community website.

More examples and scripts here soon!


Just having a bit of fun with Powershell:

48 6F 6C 64 20 66 61 73 74 20 74 6F 20 64 72 65 61 6D 73 A 46 6F 72 20 69 66 20 64 72 65 61 6D 73 20 64 69 65 A 4C 69 66 65 20 69 73 20 61 20 62 72 6F 6B 65 6E 2D 77 69 6E 67 65 64 20 62 69 72 64 A54 68 61 74 20 63 61 6E 6E 6F 74 20 66 6C 79 2E A 48 6F 6C 64 20 66 61 73 74 20 74 6F 20 64 72 65 61 6D 73 A 46 6F 72 20 77 68 65 6E 20 64 72 65 61 6D 73 20 67 6F A 4C 69 66 65 20 69 73 20 61 20 62 61 72 72 65 6E 20 66 69 65 6C 64 A 46 72 6F 7A 65 6E 20 77 69 74 68 20 73 6E 6F 77 2E 20 A A 2D 2D 4C 61 6E 67 73 74 6F 6E 20 48 75 67 68 65 73


From HEX to DEC and back

Why do computer nerds mix up Halloween and Christmas? Because 31 OCT = 25 DEC 🙂

I always mix up the commands used to convert integers to and from decimal, hexadecimal and octal in Powershell. That’s why I wrote these functions and put them in my profile:

# Description: Coverts a decimal into a hexadecimal

function Convert-DECtoHEX
ForEach ($value in $DEC)
“{0:x}” -f [Int]$value

# Description: Coverts a hexadecimal into a decimal

function Convert-HEXtoDEC
ForEach ($value in $HEX)

# Description: Coverts an octal into a decimal

function Convert-OCTtoDEC
ForEach ($value in $OCT)

Here are some example uses:

Check VMware Configuration with Powershell

I have promised you I would post this script, so here it is!

This Powershell script generates an overview of any items that are not available to every ESX server in a VMware cluster. These items might prevent your vm’s being vmotioned by DRS or restarted by HA. Pretty serious business, I’d say!

The items involved are:
1. datastores
2. LUNs (important when using Raw Device Mappings)
3. port groups

The output is a nicely formatted HTML page showing not only which items are misconfigured, but also where the are available and where they are absent.

Here’s an example:
Compare Screenshot

And here’s the script:
Compare-Clusters (Rename to .ps1)


Compare Cluster Datastores with Powershell

I showed you before how to compare the datastores for two ESX Servers using the VI Toolkit. But ideally, one would like to compare all ESX servers in a cluster to ensure VMotion and HA compatibility.
So I started scripting and it turns out to be pretty simple: only 4 lines of code in Powershell! It does the comparison for all your clusters and returns clean little tables with datastores you should investigate.


ForEach ($Cluster in (Get-Cluster | Sort Name))
$VMHosts = Get-Cluster $Cluster.Name | Get-VMHost
$Datastores = $VMHosts | Get-Datastore
$VMHosts | ForEach {Compare-Object $Datastores ($_ | Get-Datastore)} | ForEach {$_.InputObject} | Sort Name | Select @{N=$Cluster.Name;E={$_.Name}} -Unique | Format-Table




Coming very soon: a full-blown script that compares datastores, LUNs and portgroups across your clusters ánd identifies exactly where the differences are! Stay tuned…