Powershell Needful Things put that in your pipeline


Display the last couple of lines in the crawler log

Posted by Jean Louw

From time to time you need to rebuild an Exchange server database search catalog, and you can monitor the progress using performance monitor. However, I have found it more useful to monitor the actual crawler log, and see which mailbox it is currently busy crawling.

The following script will display the last 25 lines of the last crawl log and refresh it every 15 seconds. This assumes you have Exchange installed in the default location. If not, you just need to update the path.

while (1 -eq 1)
import-csv (dir 'C:\Program Files\Microsoft\Exchange Server\V15\Logging\Search\Crawler' | sort -Descending | select -First 1).fullname -Header date-time,component,version,operationId,databaseName,mailboxGuid,operation | select -last 25 | ft -AutoSize
sleep 15


If you find this, I hope it can help you in your efforts to rebuild a corrupt search catalog.


Quickly find all deferred messages in Exchange

Posted by Jean Louw

Here is a quick little one liner to find all the deferred messages with FromAddress, Recipients and DeferReason.

Get-TransportServer | Get-Queue | ?{$_.Identity -like '*submission*'} | get-message -IncludeRecipientInfo | ?{$_.Status -eq 'Retry'} | select FromAddress,Recipients, DeferReason


I'm working now on a function to resolve ambigious recipients and loops from here if possible.


Exchange 2013 Audit Script

Posted by Jean Louw

I finally had time to finish the last little issues with this script.

As with the Exchange 2010 script, this script can be used to audit various aspects of Exchange servers in the organization. Some administrators may deploy it as a morning check script, to check the health of the environment, while others may use it at client sites, as a quick overview of the server health.


- Audit Exchange 2013 servers including all features of the Exchange 2010 script.
- Added DAG health (get-mailboxdatabasecopystatus).
- Added certificates check to alert about expiring certificates.
- Colour coded some of the alerts to make them more visual.
- Updated the script output to a more Exchange 2013 look and feel.
- Added a check for the CU version of Exchange.
- Reduced the Event Log checks to 4 hours to increase speed, and reduce output size.

I have decided to make this script a GitHub project, so that anyone with PowerShell / Exchange knowledge can contribute to the project.

This script is a project I maintain in my free time, and which I provide to the community at no cost. If you like this script and use it in production, please help me keep this project free by considering a small donation.

The latest version of the script can be downloaded at https://github.com/technologicza/testexchange2013


Exchange 2013 Audit Script

Posted by Jean Louw

It has been a long time since I have posted anything on this blog, and with good reason. I started my own company a while ago, and it has consumed most of my time for the last couple of years.

I know that Exchange 2013 is something of the past, but I also know that it is very much still deployed in many organisations. Many of the subscribers to the blog have asked for an Exchange 2013 version of the script, and I have finally decided to sit down and complete it.

It will be available for download soon, so for now, please see below a screenshot of the result file.

Exchange 2013 Audit Report


Windows 2008 R2 DHCP Scope Utilisation Report

Posted by Jean Louw

Just a quick little script I developed for a client this week. As you know Windows 2012 DHCP server has some pretty cool Powershell cmdlets built in, but sadly, in the case of Windows 2008 there are none.

My customer needed to know when scopes are starting to run out of addresses. I found that the DHCP server logs an event each hour after startup for all scopes that are at 80% utilisation or more.

My solution was the following script. The script is triggered by the 1020 event in the system log, and then finds the events for the last hour, and send an email to the guys to alert them.

You need to modify the script for your servers SMTP parameters and if you prefer to run the script remotely you can use -computername on the the get-eventlog cmdlet.

Admittedly, this is not the best way if you have something like SCOM in place, but as a rudimentary solution it does exactly what they need.

$eventList = @()
Get-EventLog -LogName System -After (get-date).AddHours(-1) -Source DhcpServer -InstanceId 1020 `
| foreach-Object {
$row = "" | Select ScopeAddress, Utilization, FreeIPAddresses
$row.ScopeAddress = $_.ReplacementStrings[0]
$row.Utilization= $_.ReplacementStrings[1]
$row.FreeIPAddresses = $_.ReplacementStrings[2]
$eventList += $row

$messageParameters = @{
Subject = "DHCP Scope Utilisation Report - $((Get-Date))"
Body = $eventList | Sort Utilization -Descending |
ConvertTo-Html |
From = "Scope Alert <scopealert@xyz.com>"
To = "group@xyz.com"
SmtpServer = "xxx.xxx.xxx.xxx"

Send-MailMessage @messageParameters -BodyAsHtml
Filed under: powershell, script 3 Comments

Bulk Export Exchange Calendar data to Excel

Posted by Jean Louw


The previous version of this script, proved far more popular than I could have ever imagined. It was however very complex, which caused numerous failures during execution.

I have recently spent some time streamlining the script at a client, to a point where it is now running fully automated on a schedule.

The new script has the following requirements:

  • The script assumes that it is running in C:\Scripts\CalX - if this path is not possible you have to manually update the script to reflect the location.
  • The script should be executed in the Exchange 20xx management shell.
  • The script requires that Outlook 2007 or above is installed on the computer.
  • The script requires texprof.exe to create the profiles.
  • The script requires MAPILab Advanced Outlook Security to control the security popups.
  • The script requires a file called rooms.txt in the same folder that the script is executed from.

If any exported calendar CSV data files exist from a prior runs, the script will backup these files. The script runs thought each room, in the rooms.txt file and creates / updates a profile on the local machine.  The script assigns full mailbox permissions to the current user, for the calendar to be exported. The script logs onto Outlook using that profile, and exports the calendar data to a CSV.

When it is complete, it combines all of the calendar export files into a single CSV containing all the exported data. As always, your comments and suggestions are always welcome.

The script and texprof.exe can be downloaded below:


Find missing subnets in Active Directory

Posted by Jean Louw

I was doing an Active Directory health check for a customer, and one of the things I normally include, is to review the netlogon.log to find IP addresses or machines which are not linked to any subnet / site in Active Directory. These entries are listed as NO_CLIENT_SITE in the log.

This is a very manual task of logging onto each domain controller and copying the file to a central location, and then sifting through the data to remove any duplicate IP addresses etc. This task becomes very time consuming if you have a large number of domain controllers.

I decided to write a Powershell script to do the work for me. The advantage of the script, is that the data is stored in a CSV which can be imported to be sorted and manipulated to find recent entires, or remove duplicate computer names and / or IP addresses.

The code doesn't currently look for the no_client_site error specifically, it will import the entire file. The script does not rely on the Microsoft Active Directory module so you can use it with Windows 2003 domain controllers.

I hope you find this script useful and your comments and suggestions are always welcome.

$dom = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
Write-Host '..current domain is' $dom

Write-Host '..getting all domain controllers in domain'
$dcs = $dom | % { $_.DomainControllers } | Select Name
$at = ($dcs | Measure-Object).count

foreach ($dc in $dcs)
        $path = '\\' + $dc.name + '\admin$\debug\netlogon.log'
        if ((test-path $path) -eq $true)
                Write-Host "..collecting logfile from ($at)" $path
                [array]$colLogs += gc $path
            $at --

Write-Host '..combining logs'
$outFile = '.\expFile.txt'
$colLogs | Out-File $outFile

Write-Host '..importing combined log as csv'
$importString = Import-Csv $outFile -Delimiter ' ' -Header Date,Time,Domain,Error,Name,IPAddress

Write-Host '..exporting results'
$importString | select Date, Name, IPAddress | sort IPAddress -Unique | Export-Csv .\expDB.csv

Update: Exchange 2010 Audit Script

Posted by Jean Louw

I have posted an update to the Exchange 2010 Audit script.

This update now includes a fix for a server list from the pipeline and the image is now properly embedded into the HTML report.

The updated script can be downloaded from:


Your comments and suggestions are always welcome.

Filed under: Uncategorized 4 Comments

Updated: Exchange 2010 Mailbox cleanup utility

Posted by Jean Louw

Some users reported that the mailbox server field or the mailbox database field would be empty.

This was a problem with variable that stored the contents. I have patched this, and the new file can be downloaded from here:


Filed under: Uncategorized 2 Comments

Exchange 2010 stale & unused mailbox cleanup tool

Posted by Jean Louw

I have finally completed the testing of the User Mailbox Cleanup tool for Exchange 2010.

Although this script is run from the EMS, it opens as a GUI utility which Exchange Administrators can use to cleanup stale or old Exchange mailboxes from Exchange 2010 mailbox servers.
The utility has a couple of preset search queries to help locate stale or old mailboxes, and once complete, administrators have various options they can use to remove or cleanup these mailboxes.

The script obviously does not care about the significance of the individual mailboxes, although certain system mailboxes are excluded from the search. You still have to verify your selection before you take action against any items.

The script can be downloaded for free from here:


Your comments and feedback with regards to these items are always welcome.