PowerShell

Simple one liner...

 I recently ran into an internal virus outbreak at my place of work. We were receiving a lot of virus/worm messages during the outbreak many, many, times the normal message volume, lucky enough all the virus messages had a subject line of “Here you have”.  As soon as we realized what was going on a transport rule was put into place to block the messages on the Hub Transport servers. After several days we were still seeing infected end point on our network sending these messages. We needed a way to identify the infected users, here comes the simple PowerShell one-liner for the day:

Get-TransportServer | % { get-messagetrackinglog -Server "$_" -EventID "FAIL" -MessageSubject "Here you have" -Start "9/12/2010 12:00:01 AM" -ResultSize Unlimited } | Select Sender, Timestamp, MessageSubject | Export-Csv C:\09122010-current.csv

It gets all the Hub Transport Servers then on each HT servers gets the message tracking logs for any messages with match the EventID FAIL. This EvenID is used when a messages matches a transport rule and is dropped. Since we only need the senders Select is used to limit the output to only the senders SMTP address, time and messages subject then send it all to a CSV file.  This CSV file can be opened in Excel and you can see how many messages have been dropped and who your top senders are. Once you have that it’s time to go look at their workstations, scan and clean or reimage.

 

Exchange 2003 EAS info

The other day my boss came over and asked me how many users are using Exchange Active Sync (EAS) for mobile email. Since we are in the process of moving to Exchange 2010 I tried to see if he could wait a few months since Get-ActiveSyncDevice or Get-ActiveSyncDeviceStatistics would have the info I was looking for, but he wanted it by the end of the week, so I got to work. 

 
My first thoughts were to query AD for users enabled to use EAS with a LDAP query for something like "msExchOmaAdminWirelessEnable=*" but the problem with this is it does not tell me who is actually using the service or what devices they have. As far as I could tell the only place the data was available was in the IIS logs on our Exchange2003 Front-end OWA servers. I checked a sample log file, I was in luck it contained the info I needed.
2010-06-25 00:00:00 W3SVC1 OWAServerName x.x.x.x POST /Microsoft-Server-ActiveSync User=UserSAMAccountName&DeviceId=ApplXXXXXXXXXX&DeviceType=iPad&Cmd=MoveItems&Log=V4TNASNC:0A0C0D0FS:0A0C0D0SP:1C7I18230S462834R0S0L0H0P 443 domain\samaccountname x.x.x.x HTTP/1.1 Apple-iPad/702.367 - - ourwebmailaddress m 200 0 0 436 542 156
Note: I have removed my company specific info like User Names, server names and, IP Addresses
 
You can see the Users SAMAccountName, their DeviceID and DeviceType . Since we want to extract text from within a string the perfect tool for this is regular expression. We can use PowerShell to extract this info from a string with the -match " User=(.+)&DeviceID=(.+)&DeviceType=(.+)&Cmd" I won't get into the details of regular expression as it could be a whole series of posts by itself, but more details can be found all via your favorite search engine and at http://regexlib.com/
 
My environment generates about a 1GB of logs per day per OWA server (we have 5 OWA Servers and keep several weeks of IIS logs!) so I did not want to spend the time searching through all the files. I figured if they were actively using their EAS device then it should appear with in a few days of logs at least once. I copied a few days of IIS logs from each server locally to my workstation. If you want to search the logs on the servers with out copying them locally first you can set the path to search all the servers IIS log directories by using:
 
$searchdir = "\\Server1\c$\WINDOWS\system32\LogFiles\W3SVC1\", "\\Server2\c$\WINDOWS\system32\LogFiles\W3SVC1\"
 
My first attempt stored all matches of the regex expression in an array but I quickly exhausted the 8GB of RAM I have installed in my workstation since each device is continually talking with our webmail servers generating lines in the log files. A better approach is to use a PowerShell Hash Table; in VBS these were called Dictionary Objects. You may have also heard them referred to as Associative Arrays. An excellent primer on Hash Tables is available at http://technet.microsoft.com/en-us/library/ee692803.aspx  The main strength is that a Hash Tables uses key-value pairs where the key has to be unique. The EAS DeviceId is a unique value per handheld. All we need to do is store the DeviceID as the key and the value as who it belongs to and what type it is.
 
The file that is set by $outfile generates a CSV file that is easily opened by Excel so you can gather any statics from it that you need.

 

############################################################################# 
# Filename: CollectEASInfo.ps1 
# Searches Exchange 2003 IIS log files for EAS user and Device info and 
#  writes it to a CSV
# 
# Created by Chad Manzer
#   phillyexug.org
#
# Version 1.0 
#           (7/15/2009) - CM Inital relase
#
# DISCLAIMER 
# ========== 
# THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE  
# RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. 
#############################################################################  

$startTime = Get-Date
$outfile = "e:\APPL.csv" #Where to save the results
$searchdir = "e:\OWAIIS\" #Directories to search for Exchange 2003 IIS logs
$Files = get-childitem $searchdir |%{$_.FullName}
[Hashtable]$Hash = @{} #defining the Hash table for use later

#Write-Progress -activity "Processing" -status "Getting content of the files..."
Get-Content $Files|%{
	if ($_ -match " User=(.+)&DeviceID=(.+)&DeviceType=(.+)&Cmd")
	{
		$User = $Matches[1]
		$DeviceID = $Matches[2]
		$DeviceType = $Matches[3]
		
		#if the item is already in the hash table do not try to add it again
		if ($Hash.ContainsKey("$DeviceID,") -eq $False)
			# adding commas between items so we can export as a CSV later on
			{$Hash.Add("$DeviceID,", "$User, $DeviceType")}
		
		#Show some type of progress, it drives me nuts staring at a blinking cursor
		if ($i -lt 100) 
			{$i++
			Write-Progress -activity "Reading in Files" -status "User: $User DeviceType $DeviceType DeviceID $DeviceID" -percentcomplete $i
			}
		else {$i=0}
	}
}

#Write the hash file to out output file
Write-Progress -activity "Processing" -status "Writing to $outfile "
$Hash | out-file $outfile -Encoding ascii

#Clean up the output file since the hash table add's extra spaces in the csv we don't need 
Write-Progress -activity "Processing" -status "Cleaning up output file $outfile "
(Get-Content $outfile) -replace ' ','' | Set-Content $outfile

#All done.
Write-Progress -Activity "Processing" -Completed -Status "All done."
Write-Host "Output file is located at: $outfile"
$Endtime = Get-Date
$RunTime = $Endtime - $startTime
Write-Host "Run time: "
$RunTime

July 13, 2010 User Group Meeting Video

We would all like to thank Ed Wilson (The Scripting Guy) for sharing PowerShell best practices with all of us.  We have the video of the presentation up for anyone who may have missed it or would like to refer back to it. Enjoy.

If you would like to view this on your mobile device, for watching on the go, you can go to the viemo page at http://vimeo.com/13395119


PowerShell Best Practices by Ed Wilson on July 13

As many of you know, PowerShell is not only a powerful language that changes how you script and automate, it is essential when it comes to managing Exchange 2007, Exchange 2010 and if you are not familiar with PowerShell, you can't ignore it anymore.

Since PowerShell is such a key for Exchange Administrators, we would like to invite Ed Wilson (The Scripting Guy) to share best practices with us in July 13th session.

This is absolutely amazing opportunity for the User Group members but before we extend our invite to Ed we want to make sure we will have good participation as after all not making best of the session like Ed's is terrible thing to do.

We have opened a poll to guage your interest in the session and we invite you to please take the poll or reply to us using contact form so we can decide in coming weeks if Ed should be invited to share valuable insight on PowerShell with us in July 13th meeting.

We look forward to your valuable participation.

Upcoming Events