Archive for July, 2007

Object, not Just Text (PowerShell)

Object, object, object. This is one word that must get into the head of anyone trying to learn how PowerShell really works. Although on the surface everything is presented textually, objects are the way to go all over PowerShell. Trivial but important point to understand as this can help transform a script that deals with a single item to multiple ones.

As an illustration, take a look at this simple example.

PS C:\> ping -a (get-content list.txt)
Bad parameter mypcname.

The text file contains the name of servers, one on each line, and the Get-Content cmdlet is returning a collection of string objects identifying the name of each server (see below), something that ping does not understand. In order to make this work, the objects must be sent down a pipe and processed individually.

#will not work as ping does not understand objects in this manner
PS C:\> get-content list.txt | ping -a $_
IP address must be specified.

PS C:\> get-content list.txt | foreach { ping -a $_ }

Pinging mypcname [127.0.0.1] with 32 bytes of data:

Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128

Ping statistics for 127.0.0.1:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

Pinging mypcname [192.168.100.66] with 32 bytes of data:

Reply from 192.168.100.66: bytes=32 time<1ms TTL=128
Reply from 192.168.100.66: bytes=32 time<1ms TTL=128
Reply from 192.168.100.66: bytes=32 time<1ms TTL=128
Reply from 192.168.100.66: bytes=32 time<1ms TTL=128

Ping statistics for 192.168.100.66:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

PS C:\> $c = get-content list.txt
PS C:\> $c
localhost
mypcname

PS C:\> $c.gettype()

IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Object[] System.Array

No Comments »

Watch out those PowerShell Boolean Objects

Comparing a Boolean object [bool] to any non-null string will always return True. This is due to type conversion in action where the right-hand item is silently converted to match that on the left-hand side (”best effort”). To avoid surprises, always verify the object type before making a one-to-one comparison.

Take for example:

PS C:\> $status = $true
PS C:\> $status -eq “true”
True

PS C:\> $status -eq “false”
True

PS C:\> $status -eq “1″
True

PS C:\> $status -eq “0″
True

PS C:\> $status.gettype()

IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True Boolean System.ValueType

To make sure that comparison works as as expected, always compare it to the same Boolean object type or the numeric equivalent:

PS C:\> $status -eq $null
False

PS C:\> $status -eq $true
True

PS C:\> $status -eq $false
False

PS C:\> $status -eq 1
True

PS C:\> $status -eq 0
False

No Comments »

Troubleshooting NDR in Exchange 200x

Have you ever tried to send email messages using Outlook to recipients both inside and outside of your Exchange organization (with/out attachments) and keep getting non-delivery reports (NDRs) like this:

Undeliverable: Delivery Status Notification (Failure)

System Administrator

To: your.name@company.etc

Your message did not reach some or all of the intended recipients.

Subject: This is a test

The following recipient(s) could not be reached:

Danüvo Casanovoé on 21.01.2006 11:49
Could not deliver the message in the time limit specified. Please retry or contact your administrator.

<destserver.destdomain.xyz #4.4.7>

If you digitally sign your email messages with a digital certificate that is not listed as one of the trusted root Certificate Authority (CA) in Windows, the message could be blocked by any of the intermediate gateways en-route for a number of reasons. For this particular scenario, replace with a digital certificate from a trusted root CA or do not digitally sign the message itself.

If you inspect the NDR email header, it would reveal something like the following. Important point to note is X-Content-Failure: 0×80040158 which indicates that the dispatched message remains in the local delivery queue. One often overlooked area is troubleshooting in Active Directory and DNS, as failures to resolve the SMTP names and domains are common causes of NDR.

Microsoft Mail Internet Headers Version 2.0
Received: from sourcemailboxserver.company.etc ([10.20.30.40]) by sourcemailboxserver.company.etc with Microsoft SMTPSVC(6.0.3790.3959);
Sat, 21 Jan 2006 11:23:19 +0200
Received: from destserver.destdomain.xyz ([20.30.40.50]) by destserver.destdomain.xyz over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959);
Sat, 21 Jan 2006 12:44:22 -0500
Received: from receiveserver.destdomain.xyz (receiveserver.destdomain.xyz [40.50.60.70])
by receiveserver.company.etc (10.20.30/1.2.3) with ESMTP id xxxxxxxxxxxxx
for Danüvo.Casanovoé@destdomain.xyz; Sat, 21 Jan 2006 13:44:22 -0800
Received: from mailboxserver.destdomain.xyz ([1.2.3.4]) by receiveserver.destdomain.xyz with Microsoft SMTPSVC(6.0.3790.0);
Sat, 21 Jan 2006 13:01:02 -0900
From: postmaster@destdomain.xyz
To: your.name@company.etc
Date: Tue, 21 Jan 2006 08:49:01 +0400
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
boundary=”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmailboxserver.destdomain”
X-DSNContext: xxxxxxxx - xxxx - xxxxxxxx - xxxxxxxx
Message-ID:
X-Content-Failure: 0×80040158
Subject: Delivery Status Notification (Failure)
X-OriginalArrivalTime: 21 Jan 2006 08:49:01.0000 (UTC) FILETIME=[xxxxxxxx:xxxxxxxx]
X-Proofpoint-Virus-Version: vendor=fsecure engine=4.65.5502:2.3.11,1.2.37,4.0.164 definitions=2007-07-24_03:2007-07-21,2007-07-23,2007-07-24 signatures=0
Return-Path: <>

–xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmailboxserver.destdomain
Content-Type: text/plain; charset=unicode-1-1-utf-7

–xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmailboxserver.destdomain
Content-Type: message/delivery-status

–xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmailboxserver.destdomain
Content-Type: text/rfc822-headers

–xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmailboxserver.destdomain–

No Comments »

Recovery Storage Group Error (Exchange 2003)

How do I solve the problem where an error emitted by Exchange 2003 during the creation of a Recovery Storage Group (RSG) returned no relevant hits at support.microsoft.com or via your favorite search engine?

This misleading message …

C:\Exchsrvr\RSGTL
The specified directory already contains a file with the same prefix

… is caused by the presence of the folder pointed to by the path entered by you, not the R00.log, res1.log, res2.log or R0000001.log files that actually reside inside the folder (each 5MB in size). The trick is to entirely remove or rename the folder itself; simply deleting or renaming the contents of the folder will not work.

No Comments »

Extract Date Components in PowerShell

Step 1 - get short date format and date separator

$dateShortPat = (Get-Culture).datetimeformat.ShortDatePattern
$dateSep = (Get-Culture).datetimeformat.DateSeparator

Step 2 - use regex to determine the short date format as supported by Windows. This is useful to extract the date components from a variety of formats correctly.

switch -regex ($dateShortPat) {
“^[yY]{1,4}.[mM]{1,}.[dD]{1,}$” {
$items = $dateShortPat.split($dateSep)
$dateDay = $items[2]
$dateMonth = $items[1]
$dateYear = $items[0]
break
}

“^[dD]{1,}.[mM]{1,}.[yY]{1,4}$” {
$items = $dateShortPat.split($dateSep)
$dateDay = $items[0]
$dateMonth = $items[1]
$dateYear = $items[2]
break
}
}

See if you can spot whether any of the supported Windows short date format can still slip through (please provide your comments to this post :)

Windows Short Date Format

No Comments »

Windows Server 2008 Virtualization Architecture Diagram

Interested to cover up that plain white wall in your office? Into the world of Microsoft virtualization (aka Viridian) in the upcoming Windows Server 2008? Then check out the cool official poster (among others) depicting the Windows Server 2008 virtualization architecture as reported here.

Technorati tags: Longhorn, Windows Server 2008, Windows Server Core 2008

No Comments »

Watch those Transaction Logs (Exchange 2003)

Do you know that there is a safety feature in Exchange 2003 to guard against data loss? If the accumulated number of transaction log files exceeds 1′000 as recorded in the checkpoint log file, Exchange 2003 will automatically dismount the storage group. This means that all information stores in that storage group will be affected since they share the same set of transaction logs.

Such a behavior could be attributed to a number of factors. The most common cause is due to failed or incomplete backups that went unnoticed by the IT operations team for extended periods of time. Updates to the checkpoint file will also appear to freeze which could lead to a hung store.exe service, potentially bringing down all other storage groups on the server. Additionally, taken together, a significant number of heavy messaging users could easily contribute to the fast growth in the number of transaction logs at any given time, thereby exceeding this threshold even before the next backup cycle hits. In this case, a simple workaround is to schedule additional on-line backups of Exchange information stores.

Other common causes include move mailbox and Mailbox Merge Wizard operations, M: drive and Exchange IFS file level anti-virus scanning, public folder replication traffic and differential backups (successful full and incremental backup will purge transaction logs).

See this and this at the Exchange Server TechCenter for more information.

No Comments »

Querying IIS7 Sites with PowerShell

Let us continue with the theme of getting started with IIS7 and PowerShell. It is often useful to retrieve basic information associated with web sites such as the name, physical path and protocols. In IIS7, this and other information are spread across a number of sub-classes under ConfiguredObject in the root\WebAdministration WMI namespace.

WMI subclasses of ConfiguredObject / Object (root\webAdministration)

To find out the names and IDs of available web sites via the Site class:

Get name & ID of IIS7 web sites

To retrieve properties such as path of the web site, application pool and enabled protocols, connect to the Application class:

Get path, app pool & enabled protocols of IIS7 web sites

The physical path of a web site is found as a property in the VirtualDirectory class:

Get physical path of IIS7 web site

The web sites as seen from Internet Information Services (IIS) Manager in a graphical front-end:

IIS Manager

Tested on Windows Server 2008 June 2007 CTP

Technorati tags: PowerShell, Longhorn, Windows Server 2008, Windows Server Core 2008, IIS7

No Comments »

Getting Started with IIS7 and PowerShell

If you simply installed the Web Server (IIS) server role using the default settings on Windows Server 2008, you will encounter an error when you try to connect to the IIS7 WebAdministration namespace via PowerShell WMI.

PowerShell IIS7 Invalid namespace via WMI

The missing role service that you must have is called IIS Management Scripts and Tools (IIS7 WMI provider). You cannot use the Add Roles Wizard to modify a server role once it has been installed; it will be grayed out and shown as Web Server (IIS) (Installed). Instead, use Add Role Services in Server Manager or the IIS MMC snap-in to accomplish this.

With the successful installation of this optional role service, you can now use PowerShell to manage and administer IIS7 in Windows Server 2008. For instance to work with web sites in IIS7, use the statement:

Get-WmiObject -namespace “root\WebAdministration” -class Site

PowerShell IIS7 Invalid namespace via WMI Resolved

The output indicates that only one web site is available which goes by the name Default Web Site on a freshly installed IIS7 machine.

Tested on Windows Server 2008 June 2007 CTP

Technorati tags: PowerShell, Longhorn, Windows Server 2008, Windows Server Core 2008, IIS7

No Comments »

Handling Large Files in PowerShell

Adding more RAM memory to your computer system may indeed be fairly affordable nowadays*. So does loading the entire contents of an innocent looking file of a few hundred megabytes into computer memory. This seems fairly trivial if Windows is reporting the availability of plenty of free space (uncommitted memory) to handle the file and maybe more .

Unfortunately, not all applications can handle loading a large-size file from a physical disk into memory all at one go. This could be due to the design of the product, limitations or algorithm constraints. For example, I have a log file (plain text) that is over 280MB in size. Excel 2003 failed to completely load the file as it exceeds the maximum number of supported rows per sheet (65′536).

With Notepad, the application itself consumes roughly 3MB of RAM memory on Windows XP SP2. Loading this file bumped up RAM consumption to over 550MB during which disk I/O hovers around 400KB (page reads) and CPU utilization constantly went over 90%. And yes, Notepad managed to load the complete file eventually although it needed a couple of minutes to do it.

Using the following construct in PowerShell to load the same file …

$line = Get-Content “2007-07-10.log”

… is certainly a great idea as each line read will be inserted as an unique element in a collection of string objects. This allows you to work on the object through the use of excellent string handling methods in PowerShell. Not so great news is the whopping amount of RAM memory that PowerShell has to take up in order to properly store the full representation of the object, on top of the time needed to load and process the file contents (in fact, it took longer than Notepad, not unexpectedly). Starting PowerShell with no extra PSSnap-in uses about 30MB of memory; with this file it shot up to over 1.6GB (hogging the CPU >90% consistently)!

So how do I avoid hitting the memory brick wall? One way is to pipe the object down to a filter while loading the file and store only found items into a variable:

$line = Get-Content “2007-07-10.log” | Where-Object -FilterScript { $_ -ilike “*remote ip*” }

Besides avoiding potential memory issues, this is a much improved and efficient approach as each object is inspected to find a match to the criteria while it is being retrieved (as more objects continue to come down the pipeline). Best of all, the penalty of using this method incurs only a few extra megabytes of RAM memory usage on your computer system! Obviously, your mileage will vary depending on the number of returned hits. Compare to the previous approach, that calls for the entire file to be loaded before the next line of code to search for an item can even execute.

Although Get-Content has the -totalCount and -readCount parameters, which by default reads and passes all objects down the pipeline, these are not the same as the classic file seek or positioning routines in C/C++. This means that you can always limit the number of lines of contents to retrieve starting from the beginning of the file but you cannot start from an arbitrary point in the file to continue from where you last left off. Perhaps this will change in PowerShell v2?

* hopefully you do not need to throw out every single RAM modules particularly on previous generations of notebook computers with maximum capacities capped to 2GB or less.

See also:
The Official Scripting Guys Forum!

Technorati tags: PowerShell

No Comments »

Next »