sus42

A Blog on Wndows Server and Microsoft Exchange by Thomas Pätzold

Archive for January 2011

The Powershell Foreach Loop

leave a comment »


Have you ever thought about what happens when the collection is empty through wich you want to step with the foreach loop in Powershell 2.0?

Ok, but let´s start at the beginning.
What happens when the collection contains objects?
Think about a loop witch counts the files with the extension .txt in a given folder. The Code looks like

$path = "C:\temp"
$filter = "*.txt"
$count = 0

$files = get-childitem -path $path -filter $filter

foreach ($file in $files) {
        $count ++
}
Write-Host "There are $count files with the pattern $filer in folder $path"

What happens when the collection is empty?
The second example runs on an empty collection. Now run the same code with a filter witch doesn´t match a file or foldername. So Object $files should be empty. But what looks the output like?
foreach look with empty collection
In this example one file is found but why?
The reason is very simple because $files is a NULL Object. And a NULL Object is an object so there will be one cycle in the loop and at the end $count contains the value “1”. The NULL Object is a scalar but not a collection. But the foreach loop operates on a collection. So the NULL object has to be casted to a collection and now the collections contains one element (the Null object)

This is a real problem if the further scripts depends on this result.

Now it gets very strange. If you generate the collection within the header of the foreach loop you will get the correct result. The code looks like

$path = "C:\temp"
$filter = "*.txt"
$count = 0

foreach ($file in (get-childitem -path $path -filter $filter)) {
        $count ++
}
Write-Host "There are $count files with the pattern $filer in folder $path"

This is the output in Powershell in contrast to the first example.
The two examples with their Output

Now we look for a solution for this Problem:
There are two possible solutions.
1) You have to check with an if-statement if the collection is empty before stepping through the loop.
The Code looks like

$path = "C:\temp"
$filter = "*.txt"
$count = 0

$files = get-childitem -path $path -filter $filter
If ($files -ne $null) {
        foreach ($file in $files) {
                $count ++
        }
}
Write-Host "There are $count files with the pattern $filer in folder $path"

2) The second solution is to generate the collection within the header of the foreach loop. So you will get the correct result. The code looks like

$path = "C:\temp"
$filter = "*.txt"
$count = 0

foreach ($file in (get-childitem -path $path -filter $filter)) {
        $count ++
}
Write-Host "There are $count files with the pattern $filer in folder $path"

And this is the output in Powershell in contrast to the first example.
The two examples with their Output

3) The third solution is to generate explicit an array (collection) with the @() statement. If now the command generates a NULL object then the collection (array) is empty and your code will generate the expected result.
The code looks like:

$path = "C:\temp"
$filter = "*.txt"
$count = 0

$files = @(get-childitem -path $path -filter $filter)
If ($files -ne $null) {
        foreach ($file in $files) {
                $count ++
        }
}
Write-Host "There are $count files with the pattern $filer in folder $path"

Conclusion
I think this is an error in the implementation of the foreach loop. Perhaps we have to wait for the next version of the Windows Powershell to get this problem solved.
On Microsoft Connect you will get further infromation on this topic.

Written by Thomas Pätzold

January 24, 2011 at 10:36 pm

Posted in Powershell, Scripting

Tagged with ,

Monitoring Microsoft Exchange 2010 with NAGIOS

with 2 comments


If you want to monitor your Microsoft Exchange 2010 environment you have to choose a client which communicates with the NAGIOS Server. A popular client application is NSCLIENT++. If you want to monitor your Exchange System it is necessary to write your own monitoring script which is executed on the monitored system. In order to do so you can use the NRPE (Nagios Remote Plugin Executor) Plugin which is supported by NSCLIENT++.

Each output of the script will be displayed by NAGIOS. So the first challenge is to start the Exchange Shell without any status output. After this you can script your monitoring algorithm. At the end of the script you have to exit this script with the exit code.

value description
0 no error
1 Warning
2 Error

The following script monitors the status of a mailbox database. If the status isn´t healthy or mounted the script will return an error and NAGIOS itsself will display this Service as not available or red.

# initialisiere Exchangeumgebung
$s = new-pssession -configurationname microsoft.exchange -connectionuri http://mbx.aixtest.de/PowerShell/ -authentication Kerberos
$warningpreference = "SilentlyContinue"
Import-PSSession $s 2>&1 | out-null

##### MAIN #####
# variabledeklaration
[system.string]$errortext=""
[system.Byte]$errorvalue=0
[System.string]$mounted=""
[System.string]$healthy=""

$MailboxDatabases = Get-MailboxDatabaseCopyStatus
foreach ($mailboxdatabase in $mailboxdatabases) {
	switch ($mailboxdatabase.Status) {
		Healthy {$healthy += " " + $mailboxdatabase.Identity}
		Mounted {$mounted += " " + $mailboxdatabase.Identity}
		Default {$errorvalue=2;	$errortext += "Not Mounted or Healthy: " + $mailboxdatabase.Identity}
	}
}
if ($mounted.length -eq 0) {$mounted="-"}
if ($healthy.length -eq 0) {$healthy="-"}
$errortext += "Mounted: "+$mounted + "Healthy: "+$healthy
write-output $errortext
exit $errorvalue

Written by Thomas Pätzold

January 6, 2011 at 9:31 pm

%d bloggers like this: