Wednesday, April 16, 2014

Everyday Powershell - Part 19 - Migrate Transport Rules from Exchange 2007 to 2013

Today's script is a quick and dirty fix for a project we're in the middle of. Not really a script either, but it's the thought that counts.


#on a computer with exchange 2007 management tools
Add-PSSnapin *exchange*
export-transportrulecollection c:\scripts\exch2007transportrules.xml

#on a computer with exchange 2013 management tools
Add-PSSnapin *exchange*
[Byte[]]$Data = Get-Content -Path '\\someserver\c$\Scripts\exch2007transportrules.xml' -Encoding Byte -ReadCount 0
Import-TransportRuleCollection -FileData $Data
Export transport rules from Exchange 2007 and import them to 2013. 

To think our System Admin was going to copy these over by hand!

Full credit to Microsoft for this one it is all from http://support.microsoft.com/kb/2846555

Wednesday, March 26, 2014

Everyday Powershell - Part 18 - Set Address Details in Active Directory

Here's a request from one of our readers. He's tidying up a negelected AD he inherited and needed a way to apply consistent addresses to his AD User Objects.

Powershell is great at this stuff! We've decided to use group membership as a way to decide who should get what data, but this could be easily applied via OU.
<# For this to work setup a CSV in C:\Scripts call it Groups.csv
And fill it with data like this; 
SecurityGroup,Address,City,Zip,State,Country,Telephone
Group1,1 Some St,SomeTown,1122,SOMESTATE,AU,615551234
Group2,2 Some Other St,SomeOtherTown,2211,SOMESTATE,AU,615554321 #>

$csvdata =import-csv C:\Scripts\Groups.csv
foreach($row in $csvdata)
{
    $users= Get-ADGroupMember $row.securitygroup
    foreach($user in $users)
    {
        Set-ADUser $user -StreetAddress $row.Address -city $row.city -State $row.State -Postalcode $row.Zip -Country $row.Country -OfficePhone $row.Telephone
    }
}
Just a simple script with two loops, first one iterates through the rows in the CSV the second group steps through each user in the security group identified in the initial loop.

Nothing fancy but it fixed our readers problem. Such is the power of the shell!

Wednesday, March 19, 2014

Everyday Powershell - Part 17 - Using new-mailboxexportrequest with NON-US dates

Here's a crazy making problem!

The new-mailboxexportrequest commandlet will only accept dates in US formats. Roland Paix has made this post about the issue. The conclusion is switch your culture to EN-US before loading powershell. Sooo frustrating! But hey, something has to be the default datetime and Microsoft is an American company. No point getting emotional, let's just fix it.

Here's a neat trick you can use to set the Culture of the "Current Thread" you are running.

[System.Reflection.Assembly]::LoadWithPartialName("System.Threading")
[System.Reflection.Assembly]::LoadWithPartialName("System.Globalization")
[System.Threading.Thread]::CurrentThread.CurrentCulture = [System.Globalization.CultureInfo]::CreateSpecificCulture("en-us")

Add-PSSnapin *exchange*

$start = (get-date).adddays(-28)
$end = (get-date).adddays(-14)

$filter = "(Received -gt '"+$start+"') -and (Received -lt '"+$end+"')"
new-Mailboxexportrequest -mailbox SOMEMAILBOX -ContentFilter $filter -filepath C:\SOME.pst

This should trick new-mailboxexportrequest into believing that your dates are in the "correct" format!

Wednesday, March 12, 2014

Everyday Powershell - Part 16 - Monitoring Disk Performance in Powershell

Welcome back to another Everyday Powershell post. It's not powershell we POST every day, it's powershell you could USE everyday.

Today we look at get-counter which you should have a fiddle with if you get the chance. It does a lot more than what we've used it for here. But this may help you get the gist of running performance counters in powershell.

$disks = Get-WmiObject win32_logicaldisk | Where-Object {$_.DriveType -eq 3| select DeviceID
$report = @()
$i=1
foreach ($disk in $disks)
{
    Write-Progress -Activity "Mesuring disk performance" -Status $disk.DeviceID -PercentComplete (($i/$disks.Count)*100)
    $temp = "" | select Disk, Read, Write
    $temp.disk = $disk.deviceid
    $counter = "\LogicalDisk(" + ($disk.deviceid) + ")\Avg. Disk sec/Read"
    $temp.read = ((Get-Counter -Counter $counter).CounterSamples.cookedvalue)*1000
    $counter = "\LogicalDisk(" + ($disk.deviceid) + ")\Avg. Disk sec/Write"
    $temp.write = ((Get-Counter -Counter $counter).CounterSamples.cookedvalue)*1000
    $report += $temp
    $i++
}
$report

We've included the now ubiquitous write-progess to give a useful progress indicator. As well as the old $temp="" | select which sets up a hash table for us to dump data into.

Thursday, February 27, 2014

Everyday Powershell Returns! - Find exchange mailbox size

Fresh from an ass kicking at the Winter Scripting games we're back with another useful bit of Powershell!

We're building our Exchange 2013 environment now and have a burning need to see what our users mailboxes look like, in terms of the space they consume.

This little script did the trick for us and helped us plan our new information store layout.

Add-PSSnapin *exchange*

$users = Get-ADUser -searchbase "DC=somedomain,DC=com" -Filter * -Properties department

$report = @()
$count = $users.count
$i = 0
foreach ($user in $users)
{
    $i++
    $prog = ($i/$count* 100
    Write-Progress -Activity "Processing..." -percentcomplete $prog -CurrentOperation $user.samaccountname 
    $temp = ""| select Person, mailboxsize, itemcount, Team, Function
    $mailboxstats = Get-MailboxStatistics $user.samaccountname
    $temp.person = $user.samaccountname
    $temp.mailboxsize = $mailboxstats.totalitemsize.value.toMB()
    $temp.itemcount = $mailboxstats.itemcount
    $temp.team = $user.department
    $report += $temp
}
$report

Should be pretty self explanatory. Ask a question in the comments if you'd like clarification of anything. 

Wednesday, February 12, 2014

What I learnt at the Winter Scripting Games - Part 4

Great news!

We scored in the positives for event 2! Even got some good feeback from the judges. Great work Team Awesome...

Bad news!

We didn't get anything submitted for event 3. Missed an opportunity to capitalize on what we've learnt so far. Still there's event 4 to come.

We did get a decent function together for setting ACLs so event 3 wasn't a total write off.

For us it's more about have fun leaning challenges than the score anyway.

Wednesday, February 5, 2014

What I learned at the Winter Scripting Games - Part 3 - The Importance of Help

That’s what we learnt in event 1 of the scripting games. Our team of enthusiastic novices threw together a script that we thought met most of the requirements. It wasn't pretty and didn't include any comments or help.

Once the scoring was done we came out a -4. MINUS FOUR! Ouch.

Looking at the scoring criteria it became clear why. Much of the scoring seems to be around building the right kinds of good practice into your script.
We lost points on;
  • Appropriate use of Try/Catch
  • Appropriate use of verbose output including -Verbose support
  • Correct management of pipeline input
  • Appropriate use of parameter validation attributes
  • Comment- or file-based help
  • File names include date of production
  • Code shared between solutions
This is all pretty simple stuff that could almost be built into a script “template”. We’ll be working on that for future Events.

 So what we've learned is that the logic in your script isn't the best way to score points. I was pretty happy with our solution, give that it was produced by 3 novice scripters. OK 2 novices and me… A ‘Senior Novice’.


It was a great learning experience and the emotional kick of scoring NEGATIVE points made it clear how valuable it is to build this good practice stuff into our scripts.