I recently was helping a customer with a migration to Exchange 2007, and I had created several PowerShell scripts for them to help automate their migration. Unfortunately, like most directories out there, they had some dirty data to contend with. I ran into three distinct problems:
- I was having the user input a date for migration of specific users, the problem was, the date was not valid, and sometimes the users would put in "n/a" or "unknown". The script really required a valid date input.
- For another value, I needed to check to see if a input was numeric or not.
- And lastly, some of the SMTP addresses I was given to apply to accounts were not valid. They contained invalid characters (spaces, etc) which are not permitted in SMTP addresses.
Validating Dates:
After doing some digging, I found that the "standard" Powershell for converting a string to a date is:
$datevalue = [datetime] $stringvalue
The problem with this, is that if $stringvalue is not really a good date, then your script will error that "it's not a valid date". While that may seem logical, I really wanted a way to test this without having to do standard error trapping. I remembered that when using VB scripting, I had the nifty "IsDate" function. The benefit of "IsDate" is that you can feed it a string, and it will return whether or not the string can be a possible date (true or false). This really is what I was looking for, but could really not find an equivalent function in PowerShell that was native. However, I found you could call the VB script function by loading the VB Script assembly as such:
$migdate = "12/01/2008"
[reflection.assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
$IsDate = [Microsoft.VisualBasic.Information]::isdate($migdate)
If (!$IsDate) {
Write-host "Value entered for MigrationDate is not a date, $migdate"
} else {
#continue processing with date
}
This allows you to do testing of dates before trying to convert them.
Validating Numbers:
Similar to "IsDate", VB script also had an "IsNumeric" function. Rather than having to custom code an "IsNumeric" function for PowerShell, I decided to use the same VB Script assembly to test numbers as well:
$value = "not a number"
[reflection.assembly]::LoadWithPartialName("'Microsoft.VisualBasic")
$IsNumber = [Microsoft.VisualBasic.Information]::isnumeric($value)
If (!$IsNumber) {
Write-host "$value is not numeric"
}
Validating SMTP Addresses:
Now comes the tricky part. Determining if an SMTP address meets the RFC can be tricky. No matter what script language you use, you pretty much have to write an extensive amount of rules in order to check every possible variation. Luckily, if you have Exchange 2007 in the environment, you can actually ask Exchange to use its own functionality to check the address for you, rather than writing yet another custom function.
Function Validate-EmailAddress {
param([string]$valemail)
[Microsoft.Exchange.Data.SmtpAddress]::IsValidSmtpAddress($valemail);
}
$PrimarySMTP = "This is not a valid SMTP address@contoso.com"
$ValidAddr = Validate-EmailAddress $PrimarySMTP
If ($ValidAddr) {
Write-host "$Primary SMTP is valid"
}
This function actually sends the email address to Exchange to check validity. It makes it a lot easier than writing your own custom parsing function.
Always Check Your Input:
When doing scripting it is always important to do validation on the data coming in, primarily if that data will be user entered. These functions provide some quick shortcuts to validating your input data for those all important PowerShell scripts.
Eric Gentry
Senior Consultant
Project Leadership Associates