Powershell Script: ActiveSync Properties

2 04 2010

activesync-logo

Our good friend StevieMac over at The Scripting Guy wrote a nice powershell script that allows Exchange Administrators to view the ActiveSync properties of a user’s mailbox in a nice looking GUI window:

activesync1

function GenerateForm {

########################################################################

# Generated On: 12/22/2008 4:04 PM

# Generated By: StevieMac@thescriptingguy.com

########################################################################

Function getInfo()

{

Get-ActiveSyncDeviceStatistics -Mailbox $txtQNumber.text -ShowRecoveryPassword:$true | ForEach-Object{

if ($_.DeviceID -ne $null){$txtDeviceID.text = $_.DeviceID}

if ($_.FirstSyncTime -ne $null){$txtFirstSyncTime.text = $_.FirstSyncTime}

if ($_.DeviceModel -ne $null){$txtModel.text = $_.DeviceModel}

if ($_.DeviceIMEI -ne $null){$txtIMEI.text = $_.DeviceIMEI}

if ($_.LastPolicyUpdateTime -ne $null){$txtLastPolicyUpdate.text = $_.LastPolicyUpdateTime}

if ($_.LastSyncAttemptTime -ne $null){$txtLastSyncAttempt.text = $_.LastSyncAttemptTime}

if ($_.LastSuccessSync -ne $null){$txtLastSuccessfulSync.text = $_.LastSuccessSync}

if ($_.DevicePhoneNumber -ne $null){$txtPhoneNumber.text = $_.DevicePhoneNumber}

if ($_.DeviceOS -ne $null){$txtDeviceOS.text = $_.DeviceOS}

if ($_.RecoveryPassword -eq $null){$txtRecoveryPassword.text = 'No Password Set'}

if ($_.RecoveryPassword -ne $null){$txtRecoveryPassword.text = $_.RecoveryPassword}

}

}

 

#region Import the Assembles

[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null

[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null

#endregion

 

#region Generated Form Objects

$frmActiveSync = New-Object System.Windows.Forms.Form

$txtDeviceOS = New-Object System.Windows.Forms.TextBox

$lblDeviceOS = New-Object System.Windows.Forms.Label

$txtRecoveryPassword = New-Object System.Windows.Forms.TextBox

$txtLastPolicyUpdate = New-Object System.Windows.Forms.TextBox

$txtLastSuccessfulSync = New-Object System.Windows.Forms.TextBox

$txtLastSyncAttempt = New-Object System.Windows.Forms.TextBox

$txtFirstSyncTime = New-Object System.Windows.Forms.TextBox

$txtIMEI = New-Object System.Windows.Forms.TextBox

$txtDeviceID = New-Object System.Windows.Forms.TextBox

$txtPhoneNumber = New-Object System.Windows.Forms.TextBox

$txtModel = New-Object System.Windows.Forms.TextBox

$lblRecoveryPassword = New-Object System.Windows.Forms.Label

$lblLastPolicyUpdate = New-Object System.Windows.Forms.Label

$lblLastSuccessful = New-Object System.Windows.Forms.Label

$lblLastSyncAttempt = New-Object System.Windows.Forms.Label

$lblFirstSync = New-Object System.Windows.Forms.Label

$lblIMEI = New-Object System.Windows.Forms.Label

$lblDeviceID = New-Object System.Windows.Forms.Label

$lblPhoneNumber = New-Object System.Windows.Forms.Label

$lblModel = New-Object System.Windows.Forms.Label

$txtQNumber = New-Object System.Windows.Forms.TextBox

$btnList = New-Object System.Windows.Forms.Button

#endregion Generated Form Objects

 

#----------------------------------------------

#Generated Event Script Blocks

#----------------------------------------------

#Provide Custom Code for events specified in PrimalForms.

$btnList.Add_Click({getInfo})

 

#----------------------------------------------

#region Generated Form Code

$frmActiveSync.Text = 'List Active Sync User Information'

$frmActiveSync.Name = 'frmActiveSync'

$frmActiveSync.StartPosition = 1

$frmActiveSync.DataBindings.DefaultDataSourceUpdateMode = 0

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 464

$System_Drawing_Size.Height = 328

$frmActiveSync.ClientSize = $System_Drawing_Size

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 214

$System_Drawing_Size.Height = 20

$txtDeviceOS.Size = $System_Drawing_Size

$txtDeviceOS.DataBindings.DefaultDataSourceUpdateMode = 0

$txtDeviceOS.ReadOnly = $True

$txtDeviceOS.Name = 'txtDeviceOS'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 67

$txtDeviceOS.Location = $System_Drawing_Point

$txtDeviceOS.TabIndex = 21

 

$frmActiveSync.Controls.Add($txtDeviceOS)

 

$lblDeviceOS.TabIndex = 20

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 100

$System_Drawing_Size.Height = 23

$lblDeviceOS.Size = $System_Drawing_Size

$lblDeviceOS.Text = 'Operating System'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 70

$lblDeviceOS.Location = $System_Drawing_Point

$lblDeviceOS.DataBindings.DefaultDataSourceUpdateMode = 0

$lblDeviceOS.Name = 'lblDeviceOS'

 

$frmActiveSync.Controls.Add($lblDeviceOS)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtRecoveryPassword.Size = $System_Drawing_Size

$txtRecoveryPassword.DataBindings.DefaultDataSourceUpdateMode = 0

$txtRecoveryPassword.ReadOnly = $True

$txtRecoveryPassword.Name = 'txtRecoveryPassword'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 284

$txtRecoveryPassword.Location = $System_Drawing_Point

$txtRecoveryPassword.TabIndex = 19

 

$frmActiveSync.Controls.Add($txtRecoveryPassword)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtLastPolicyUpdate.Size = $System_Drawing_Size

$txtLastPolicyUpdate.DataBindings.DefaultDataSourceUpdateMode = 0

$txtLastPolicyUpdate.ReadOnly = $True

$txtLastPolicyUpdate.Name = 'txtLastPolicyUpdate'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 257

$txtLastPolicyUpdate.Location = $System_Drawing_Point

$txtLastPolicyUpdate.TabIndex = 18

 

$frmActiveSync.Controls.Add($txtLastPolicyUpdate)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtLastSuccessfulSync.Size = $System_Drawing_Size

$txtLastSuccessfulSync.DataBindings.DefaultDataSourceUpdateMode = 0

$txtLastSuccessfulSync.ReadOnly = $True

$txtLastSuccessfulSync.Name = 'txtLastSuccessfulSync'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 230

$txtLastSuccessfulSync.Location = $System_Drawing_Point

$txtLastSuccessfulSync.TabIndex = 17

 

$frmActiveSync.Controls.Add($txtLastSuccessfulSync)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtLastSyncAttempt.Size = $System_Drawing_Size

$txtLastSyncAttempt.DataBindings.DefaultDataSourceUpdateMode = 0

$txtLastSyncAttempt.ReadOnly = $True

$txtLastSyncAttempt.Name = 'txtLastSyncAttempt'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 203

$txtLastSyncAttempt.Location = $System_Drawing_Point

$txtLastSyncAttempt.TabIndex = 16

 

$frmActiveSync.Controls.Add($txtLastSyncAttempt)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtFirstSyncTime.Size = $System_Drawing_Size

$txtFirstSyncTime.DataBindings.DefaultDataSourceUpdateMode = 0

$txtFirstSyncTime.ReadOnly = $True

$txtFirstSyncTime.Name = 'txtFirstSyncTime'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 176

$txtFirstSyncTime.Location = $System_Drawing_Point

$txtFirstSyncTime.TabIndex = 15

 

$frmActiveSync.Controls.Add($txtFirstSyncTime)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtIMEI.Size = $System_Drawing_Size

$txtIMEI.DataBindings.DefaultDataSourceUpdateMode = 0

$txtIMEI.ReadOnly = $True

$txtIMEI.Name = 'txtIMEI'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 149

$txtIMEI.Location = $System_Drawing_Point

$txtIMEI.TabIndex = 14

 

$frmActiveSync.Controls.Add($txtIMEI)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtDeviceID.Size = $System_Drawing_Size

$txtDeviceID.DataBindings.DefaultDataSourceUpdateMode = 0

$txtDeviceID.ReadOnly = $True

$txtDeviceID.Name = 'txtDeviceID'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 122

$txtDeviceID.Location = $System_Drawing_Point

$txtDeviceID.TabIndex = 13

 

$frmActiveSync.Controls.Add($txtDeviceID)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtPhoneNumber.Size = $System_Drawing_Size

$txtPhoneNumber.DataBindings.DefaultDataSourceUpdateMode = 0

$txtPhoneNumber.ReadOnly = $True

$txtPhoneNumber.Name = 'txtPhoneNumber'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 93

$txtPhoneNumber.Location = $System_Drawing_Point

$txtPhoneNumber.TabIndex = 12

 

$frmActiveSync.Controls.Add($txtPhoneNumber)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 215

$System_Drawing_Size.Height = 20

$txtModel.Size = $System_Drawing_Size

$txtModel.DataBindings.DefaultDataSourceUpdateMode = 0

$txtModel.ReadOnly = $True

$txtModel.Name = 'txtModel'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 207

$System_Drawing_Point.Y = 40

$txtModel.Location = $System_Drawing_Point

$txtModel.TabIndex = 11

 

$frmActiveSync.Controls.Add($txtModel)

 

$lblRecoveryPassword.TabIndex = 10

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblRecoveryPassword.Size = $System_Drawing_Size

$lblRecoveryPassword.Text = 'Recovery Password'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 287

$lblRecoveryPassword.Location = $System_Drawing_Point

$lblRecoveryPassword.DataBindings.DefaultDataSourceUpdateMode = 0

$lblRecoveryPassword.Name = 'lblRecoveryPassword'

 

$frmActiveSync.Controls.Add($lblRecoveryPassword)

 

$lblLastPolicyUpdate.TabIndex = 9

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblLastPolicyUpdate.Size = $System_Drawing_Size

$lblLastPolicyUpdate.Text = 'Last Policy Update Time'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 260

$lblLastPolicyUpdate.Location = $System_Drawing_Point

$lblLastPolicyUpdate.DataBindings.DefaultDataSourceUpdateMode = 0

$lblLastPolicyUpdate.Name = 'lblLastPolicyUpdate'

 

$frmActiveSync.Controls.Add($lblLastPolicyUpdate)

 

$lblLastSuccessful.TabIndex = 8

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblLastSuccessful.Size = $System_Drawing_Size

$lblLastSuccessful.Text = 'Last Successful Sync Time'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 233

$lblLastSuccessful.Location = $System_Drawing_Point

$lblLastSuccessful.DataBindings.DefaultDataSourceUpdateMode = 0

$lblLastSuccessful.Name = 'lblLastSuccessful'

 

$frmActiveSync.Controls.Add($lblLastSuccessful)

 

$lblLastSyncAttempt.TabIndex = 7

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblLastSyncAttempt.Size = $System_Drawing_Size

$lblLastSyncAttempt.Text = 'Last Sync Attempt Time'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 206

$lblLastSyncAttempt.Location = $System_Drawing_Point

$lblLastSyncAttempt.DataBindings.DefaultDataSourceUpdateMode = 0

$lblLastSyncAttempt.Name = 'lblLastSyncAttempt'

 

$frmActiveSync.Controls.Add($lblLastSyncAttempt)

 

$lblFirstSync.TabIndex = 6

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblFirstSync.Size = $System_Drawing_Size

$lblFirstSync.Text = 'First Sync Time'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 179

$lblFirstSync.Location = $System_Drawing_Point

$lblFirstSync.DataBindings.DefaultDataSourceUpdateMode = 0

$lblFirstSync.Name = 'lblFirstSync'

 

$frmActiveSync.Controls.Add($lblFirstSync)

 

$lblIMEI.TabIndex = 5

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblIMEI.Size = $System_Drawing_Size

$lblIMEI.Text = 'IMEI'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 152

$lblIMEI.Location = $System_Drawing_Point

$lblIMEI.DataBindings.DefaultDataSourceUpdateMode = 0

$lblIMEI.Name = 'lblIMEI'

 

$frmActiveSync.Controls.Add($lblIMEI)

 

$lblDeviceID.TabIndex = 4

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblDeviceID.Size = $System_Drawing_Size

$lblDeviceID.Text = 'Device ID'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 125

$lblDeviceID.Location = $System_Drawing_Point

$lblDeviceID.DataBindings.DefaultDataSourceUpdateMode = 0

$lblDeviceID.Name = 'lblDeviceID'

 

$frmActiveSync.Controls.Add($lblDeviceID)

 

$lblPhoneNumber.TabIndex = 3

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblPhoneNumber.Size = $System_Drawing_Size

$lblPhoneNumber.Text = 'Phone Number'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 96

$lblPhoneNumber.Location = $System_Drawing_Point

$lblPhoneNumber.DataBindings.DefaultDataSourceUpdateMode = 0

$lblPhoneNumber.Name = 'lblPhoneNumber'

 

$frmActiveSync.Controls.Add($lblPhoneNumber)

 

$lblModel.TabIndex = 2

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 182

$System_Drawing_Size.Height = 23

$lblModel.Size = $System_Drawing_Size

$lblModel.Text = 'Model'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 12

$System_Drawing_Point.Y = 43

$lblModel.Location = $System_Drawing_Point

$lblModel.DataBindings.DefaultDataSourceUpdateMode = 0

$lblModel.Name = 'lblModel'

 

$frmActiveSync.Controls.Add($lblModel)

 

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 100

$System_Drawing_Size.Height = 20

$txtQNumber.Size = $System_Drawing_Size

$txtQNumber.DataBindings.DefaultDataSourceUpdateMode = 0

$txtQNumber.Text = 'Enter Users Alias'

$txtQNumber.Name = 'txtQNumber'

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 95

$System_Drawing_Point.Y = 15

$txtQNumber.Location = $System_Drawing_Point

$txtQNumber.TabIndex = 1

 

$frmActiveSync.Controls.Add($txtQNumber)

 

$btnList.TabIndex = 0

$btnList.Name = 'btnList'

$System_Drawing_Size = New-Object System.Drawing.Size

$System_Drawing_Size.Width = 75

$System_Drawing_Size.Height = 23

$btnList.Size = $System_Drawing_Size

$btnList.UseVisualStyleBackColor = $True

 

$btnList.Text = 'List Info'

 

$System_Drawing_Point = New-Object System.Drawing.Point

$System_Drawing_Point.X = 13

$System_Drawing_Point.Y = 13

$btnList.Location = $System_Drawing_Point

$btnList.DataBindings.DefaultDataSourceUpdateMode = 0

$btnList.add_Click($btnList_OnClick)

 

$frmActiveSync.Controls.Add($btnList)

 

#endregion Generated Form Code

 

#Show the Form

$frmActiveSync.ShowDialog()| Out-Null

 

} #End Function

 

#Call the Function

GenerateForm

[ The Scripting Guy ]





Script: Get time of Exchange last online defrag

19 03 2009

digging through the Application log can be a real pain sometimes.  Last night, I was asked by a Microsoft Engineer to give me the last online defrag of a server that we had a case opened on.  So, instead of opening up the Event Viewer, I went to Powershell:

# Script to return the date and time of the last online defrag of each Exchange 2007 Database
# Highly recommended to run this locally on the Exchange server, not remotely.
# Written by Dan Burgess
# nerd@EverydayNerd.com

$servername = read-host "Enter Exchange Mailbox Server Name"
$db = Get-StorageGroup -Server $servername | Get-MailboxDatabase

foreach ($objItem in $db)
{
$EventLogs = get-EventLog -Logname Application| Where-Object {$_.EventID -eq 703 -or $_.EventID -eq 701 -and $_.source -eq 'ESE' } | Where-Object {$_.ReplacementStrings -like $objItem.EdbFilePath} | select-object -first 1
write-host ' Mailbox store: ' $objItem.Identity
write-host ' Last Defrag completed: ' $EventLogs.TimeGenerated
write-host ' '
}

Works like a charm!  Next time you need to extract info from a computers log files, edit this script to match the EventID that you need, and slap it in Powershell!  Happy scripting!





Powershell Script: Display Exchange 2007 Queue by Site

18 03 2009

Working in a multi site Exchange 2007 environment can be cumbersome when trying to view queue information on the Hub servers.  I wrote this script to simplify this process.
The script queries the Exchange 2007 organization, finds the servers with the Hub Transport Roles, and grouping them into sites (you will have to define the sites yourself, based on your organizational configuration).  You can find the sites for your organization by entering this command:

Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true } | sort name

This will output a table of all the Hub Transport servers and list the Site for each.  Take these site names, and change the script with your values.  You can also modify the variable names to match each site’s name.

Script:

# Exchange 2007 Powershell Script
# Script to display queue information of Hub Transport Servers
# Dynamicly selects Exchange Hub Transport Servers from Exchange 2007 Organization
# Selects server's location by Site
# Output queue information
# Writen by Dan Burgess
# nerd@EverydayNerd.com

cls

# Set variables
$last = "begin"
$choice = 'start'

# Dynamicly set variables for each site's hub transport servers, and sort by server name
$usa = Get-ExchangeServer | where { $_.isHubTransportServer -eq $true -and $_.Site -like '*USA*' } | sort name
$eur = Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true -and $_.Site -like '*EUR*' } | sort name
$chi = Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true -and $_.Site -like '*CHI*' } | sort name
$aus = Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true -and $_.Site -like '*AUS*' } | sort name
$afr = Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true -and $_.Site -like '*AFR*' } | sort name
$allhub = Get-ExchangeServer | Where { $_.isHubTransportServer -eq $true } | sort name

# Start WHILE loop, that allows the user to repeat or select the choice selection instead of exiting the script after completion
while ($choice -ne 'x')
{
write-host ""
write-host "0 - All Sites" -foregroundcolor Yellow
write-host "1 - America (USA)" -foregroundcolor Yellow
write-host "2 - Europe (EUR)" -foregroundcolor Yellow
write-host "3 - China (CHI)" -foregroundcolor Yellow
write-host "4 - Austrialia (AUS)" -foregroundcolor Yellow
write-host "5 - Africa (AFR)" -foregroundcolor Yellow
write-host "6 - All Queue with messages higher than 10" -foregroundcolor Green
write-host "X - Exit" -foregroundcolor Red
write-host ""


# If statement to see check if first selection, or sequencial
if($last -eq "begin")
{
[console]::ForegroundColor = "Green"
$choice = read-host "Select site to check Hub Queue's"
[console]::ResetColor()
}
else
{
[console]::ForegroundColor = "Green"
$choice = read-host "Select site to check Hub Queue's (Press Enter to repeat your last selection)"
[console]::ResetColor()
}

switch ($choice)
{
0 { $hub = $allhub }
1 { $hub = $usa }
2 { $hub = $eur }
3 { $hub = $chi }
4 { $hub = $aus }
5 { $hub = $afr }
6 { $hub = $allhub }
x { }
default { $choice = $last }
}

# For each server in the site selected, get the queue information, and list as a table
if($choice -eq "6")
{
"Begin Hub List" > HubQueueOutput.txt
"--------------------------------------" >> HubQueueOutput.txt
foreach ( $server in $hub )
{
get-exchangeserver $server -erroraction silentlycontinue | get-queue -erroraction silentlycontinue | where {$_.MessageCount -gt 10 } >> HubQueueOutput.txt
}
"--------------------------------------" >> HubQueueOutput.txt
"End Hub List" >> HubQueueOutput.txt
more HubQueueOutput.txt
}
elseif($choice -ne "x")
{
"Begin Hub List" > HubQueueOutput.txt
"--------------------------------------" >> HubQueueOutput.txt
foreach ( $server in $hub )
{
get-exchangeserver $server -erroraction silentlycontinue | get-queue -erroraction silentlycontinue >> HubQueueOutput.txt
}
"--------------------------------------" >> HubQueueOutput.txt
"End Hub List" >> HubQueueOutput.txt
more HubQueueOutput.txt
}
else
{
write-host ""
write-host "Script exiting" -foregroundcolor DarkCyan
write-host ""
write-host "Have a nice day..."
write-host ""
write-host ""
}
$last = $choice
# Go back to begining of WHILE loop, and do it again!
}

Of course this has to be ran on a machine that hat the Exchange 2007 Powershell installed.  Hope this helps, and saves time!





Script to Find Whitespace on all Exchange 2007 Servers

23 01 2009

As an Exchange Admin, I’m sure you have had the need to find out how much whitespace is in each of your Exchange databases.  This can be a real pain to do, crawling through the Event Log, looking for Event ID 1221.  This script will query all Exchange 2007 Mailbox servers, crawl through the Event logs, and return the Whitespace for every Database you have.  This information can also be exported to a SQL database, if you un-comment the appropriate lines.

Hope this makes your job easier!

*** Special thanks to my co-worker Stephen M for writing this script, and suggesting that I post it to ExchangeStyle.EverydayNerd.com – Thanks!

# Script: Get-WhiteSpace.ps1 will return the Whitespace on every Mailbox Server in an Exchange 2007 Environment
# Author: EverydayNerd.com
# Contact: Nerd [at] everydaynerd.com

# Uncomment to write to a database

#$db = “Enter Server Name Here”
#$catalog = “Enter Database Catalog Here”
#$conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$db; Initial Catalog=$catalog; Integrated Security=SSPI")
#$conn.Open()

$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-1))
$servers = Get-ExchangeServer | Where{$_.ServerRole -eq 'None' -or $_.ServerRole -like '*Mailbox*'} | sort name
foreach ($server in $servers){
Write-Host $server
Get-WmiObject -computer $server -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'") |
ForEach-Object{
$time = [System.Management.ManagementDateTimeConverter]::ToDateTime($_.TimeGenerated).ToString()
$date = $time.split("' '")
$writedate = $date[0]
$mbnamearray = $_.message.split("' '")
$store = $mbnamearray[2]
$store = $store -replace '"', ''
$size = [math]::round(($mbnamearray[4]/1024),4)
$search = $server.ToString() + "\" + $store.ToString()

$test = Get-ExchangeServer $server
If ($server.ServerRole -eq 'None'){
$root =[ADSI]'LDAP://RootDSE'
$cfConfigRootpath = "
LDAP://" + $root.ConfigurationNamingContext.tostring()
$configRoot = [ADSI]$cfConfigRootpath
$searcher = New-Object DirectoryServices.DirectorySearcher($configRoot)
$searcher.Filter = '(&(objectCategory=msExchExchangeServer)(cn=' + $Server + '))'
$searchres = $searcher.FindOne()
$snServerEntry = New-Object System.DirectoryServices.directoryentry
$snServerEntry = $searchres.GetDirectoryEntry()


$adsiServer = [ADSI]('LDAP://' + $snServerEntry.DistinguishedName)
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($adsiServer)
$dfsearcher.Filter = "
(objectCategory=msExchPrivateMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$srnamearray = $_.message.split("
'\'")
$srstore = $mbnamearray[2]
$srstore = $srstore -replace '
"',''
If ($srstore.ToString() -like $store.ToString()){
$EDBFile = $msMailStore.msExchEDBFile
$EDBFilePath = "
\\" + $server.ToString() + "\" + $EDBFile.ToString()
$EDBFilePath = $EDBFilePath -replace ':', '$'
$EDBFileSize = Get-Item $EDBFilePath.ToString() | select Length
}
}
}
Else{
$EDBFile = Get-MailboxDatabase -Identity $search | select EDBFilePath
$EDBFile = $EDBFile -replace '@{EdbFilePath=', ''
$EDBFile = $EDBFile -replace '}', ''
$EDBFile = $EDBFile -replace ':', '$'
$EDBFilePath = "
\\" + $server.ToString() + "\" + $EDBFile.ToString()
$EDBFileSize = Get-Item $EDBFilePath.ToString() | select Length
}

$EDBFileSize = $EDBFileSize -replace '@{Length=', ''
$EDBFileSize = $EDBFileSize -replace '}', ''
$EDBFileSize = [math]::round(((($EDBFileSize/1024)/1024)/1024),2)

# Uncomment to write to a database
#$cmd = $conn.CreateCommand()
#$cmd.CommandText ="
INSERT EventLog1221 VALUES ('$writedate', '$server', '$store', '$size', '$EDBFileSize')"
#$cmd.ExecuteNonQuery()

Write-Host $writedate $server $store $size $EDBFileSize
}
}
# Uncomment to write to a database
#$conn.Close()





Auto Grow DPM Protection Groups by Percentage Thresholds

20 01 2009

Managing many DPM servers can turn into quite a time consuming activity, especially when it comes to allocating more disk space to Data Sources.  The Ctrl-P DPM blog has a real simple auto-grow script on their site, but I personally have had issues with it, as have many others on the Net.  It is also rather lacking in “bells and whistles” but for an everyday DPM admin, it sure would make life easier.  In my quest for ways to make my job easier, I found this absolutely AWESOME script that Owen Clashing wrote on his blog.

#This DPM powershell script helps automate the growing of replica and shadow copy volumes which need to be grown.
param([string] $DPMServerName, [string] $Mode, [int] $ReplicaThreshold, [int] $ReplicaGrowBy, [int] $RecoveryPointThreshold, [int] $RecoveryPointGrowBy)

###### Define variables for default values
$DefaultDPMServerName = $env:COMPUTERNAME # Assumes that the current computer is the DPM server
$DefaultMode = "A"
$DefaultReplicaThreshold = 90
$DefaultReplicaGrowBy = 5
$DefaultShadowCopyThreshold = 90
$DefaultShadowCopyGrowBy = 5
######

function Usage()
{
write-host
write-host "Usage::"
write-host "AutoGrowByPercentWithDefaults.ps1"
write-host "AutoGrowByPercentWithDefaults.ps1 -DPMServerName [DPMServername] -Mode [A|C]"
write-host
write-host "Run 'AutoGrowByPercentWithDefaults.ps1 -detailed' for detailed help"
write-host
write-host
}

if(("-?","-help") -contains $args[0])
{
Usage
exit 0
}

if(("-detailed") -contains $args[0])
{
write-host
write-host "Detailed Help : Use this script to automatically grow the replica and recovery point volume sizes"
write-host "Parameters:"
write-host "-DPMServerName [DPMServername] :: The name of the DPM server that is being targetted"
write-host "-Mode [A|C] :: A - Audit only (make no disk allocation changes); C - Change disk allocations"
write-host "-ReplicaThreshold [Replica Threshold %] :: Percentage usage above which disk space allocation for the replica volume will be triggered"
write-host "-ReplicaGrowBy [Replica Grow By %] :: Percentage by which to grow the replica volume"
write-host "-RecoveryPointThreshold [Recovery Point Threshold %] :: Percentage usage above which disk space allocation for the recovery point volume will be triggered"
write-host "-RecoveryPointGrowBy [Recovery Point Grow By %] :: Percentage by which to grow the recovery point volume"
write-host "Current default values:"
write-host "-DPMServerName $DefaultDPMServerName"
write-host "-Mode $DefaultMode"
write-host "-ReplicaThreshold $DefaultReplicaThreshold"
write-host "-ReplicaGrowBy $DefaultReplicaGrowBy"
write-host "-RecoveryPointThreshold $DefaultShadowCopyThreshold"
write-host "-RecoveryPointGrowBy $DefaultShadowCopyGrowBy"
write-host
exit 0
}

if(!$DPMServerName)
{
$DPMServerName = $DefaultDPMServerName
}

if(!$Mode)
{
$Mode = $DefaultMode
}
else
{
if (($Mode -ne "A") -or ($Mode -ne "C"))
{
Usage
exit 0
}
}

if(!$ReplicaThreshold)
{
$ReplicaThreshold = $DefaultReplicaThreshold
}

if(!$ReplicaGrowBy)
{
$ReplicaGrowBy = $DefaultReplicaGrowBy
}

# Note the inconsistency in the naming - Object model name Shadow Copy, GUI name Recovery Point
# We use the GUI names in naming the parameters to keep it familiar for the casual user.
if(!$RecoveryPointThreshold)
{
$ShadowCopyThreshold = $DefaultShadowCopyThreshold
}
else
{
$ShadowCopyThreshold = $RecoveryPointThreshold
}


if(!$RecoveryPointGrowBy)
{
$ShadowCopyGrowBy = $DefaultShadowCopyGrowBy
}
else
{
$ShadowCopyThreshold = $RecoveryPointGrowBy
}


switch ($Mode)
{
"A"
{
$ChangeHighlightColor = "Green"
write-host "In audit mode - No changes will be made to the disk allocations" -foregroundcolor $ChangeHighlightColor
}
"C"
{
$ChangeHighlightColor = "Red"
write-host "In change mode - Changes will be made to the disk allocations" -foregroundcolor $ChangeHighlightColor
}
}



$dpmserver = Connect-DPMServer $DPMServerName

if(!$dpmserver)
{
write-error "Unable to connect to $dpmservername"
exit 1
}

$PGList = @(Get-ProtectionGroup $DPMServerName)

foreach($PG in $PGList)
{
# Use a modifiable protection group only if we are in change mode
# A non-modifiable protection group object is significantly faster
if ($Mode -eq "C")
{
$MPG = Get-ModifiableProtectionGroup $PG
}
else
{
$MPG = $PG
}

$dslist=@(get-datasource $MPG)
foreach ($ds in $dslist)
{
$ReplicaUsedPercent = ($ds.ReplicaUsedSpace/$ds.ReplicaSize)
$ShadowCopyUsedPercent = ($ds.ShadowCopyUsedSpace/$ds.ShadowCopyAreaSize)
"------------------------------------------------------------------------"
#"Protection Group: $PG.Name"
"$ds"

# $ds.ReplicaSize = -1 when there is no replica component to the backup
# Only process if there is replica disk space allocated
if ($ds.ReplicaSize -ne -1)
{
"Replica Used % : {0:P2}" -f $ReplicaUsedPercent

if($ReplicaUsedPercent -gt $ReplicaThreshold/100)
{
$ReplicaGrowByActual = ($ReplicaGrowBy/100)*$ds.ReplicaSize
$NewReplicaSize = $ds.ReplicaSize + $ReplicaGrowByActual
"Replica Grow % : {0:P2}" -f $($ReplicaGrowBy/100)
write-host $("Replica Grow Actual (GB) : {0:N2}" -f $($ReplicaGrowByActual/1GB)) -foregroundcolor $ChangeHighlightColor
"Replica New Total (GB) : {0:N2}" -f $($NewReplicaSize/1GB)

if ($Mode -eq "C")
{
Set-DatasourceDiskAllocation -Manual -Datasource $ds -ProtectionGroup $MPG -ReplicaArea $NewReplicaSize
}
}
else
{
"Replica Grow % : 0.00 %"
"Replica Grow Actual (GB) : 0.00"
"Replica New Total (GB) : {0:N2}" -f $(($ds.ReplicaSize)/1GB)
}
}
else
{
"No disk space allocated for replica"
}

# $ds.ShadowCopyAreaSize = -1 when there is no shadow copy component to the backup
# Only process if there is shadow copy disk space allocated
if ($ds.ShadowCopyAreaSize -ne -1)
{
"Recovery Point Used % : {0:P2}" -f $ShadowCopyUsedPercent

if($ShadowCopyUsedPercent -gt $ShadowCopyThreshold/100)
{
$ShadowCopyGrowByActual = ($ShadowCopyGrowBy/100)*$ds.ShadowCopyAreaSize
$NewShadowCopySize = $ds.ShadowCopyAreaSize + $ShadowCopyGrowByActual
"Recovery Point Grow % : {0:P2}" -f $($ShadowCopyGrowBy/100)
write-host $("Recovery Point Grow Actual (GB): {0:N2}" -f $($ShadowCopyGrowByActual/1GB)) -foregroundcolor $ChangeHighlightColor
"Recovery Point New Total (GB) : {0:N2}" -f $($NewShadowCopySize/1GB)

if ($Mode -eq "C")
{
Set-DatasourceDiskAllocation -Manual -Datasource $ds -ProtectionGroup $MPG -ShadowCopyArea $NewShadowCopySize
}
}
else
{
"Recovery Point Grow % : 0.00 %"
"Recovery Point Grow Actual (GB): 0.00"
"Recovery Point New Total (GB) : {0:N2}" -f $($ds.ShadowCopyAreaSize/1GB)
}
}
else
{
"No disk space allocated for recovery point"
}
}

# Update the protection group if we are in change mode
if ($Mode -eq "C")
{
Set-ProtectionGroup $MPG
}
}

Disconnect-DPMServer $DPMServerName

"------------------------------------------------------------------------"

I LOVE the –MODE switch, allowing me to run the script, and see the results, without actually changing any disk allocations.  I’ve added this script to the DPM servers that I manage, and have the task scheduler run it twice a day.  No more failed jobs due to lack of disk space!  Yeah!





Script – Create Recovery Points

16 01 2009

In the environment that I work, DPM protects the Exchange 2007 servers.  I have only one Exchange server in each protection group.  Each Exchange server has between 10-20 Storage Groups (or Data Sources).  If I want to initiate a backup on the entire server, it is a pain to select each storage group, click Create Recovery Point, and select either Full or Incremental, then click Close. 

The script below does all that for me.  It connects to the DPM server, lists the Protection Groups, asks if you want to run an Express Full, or Incremental backup, then initiates the jobs for each Data Source in the Protection Group (each Storage Group on the Exchange Server).

# DPM 2007 Powershell Script
# Script to initiate a Recovery Point for each Data Source in a Protection Group
# Initial Script from Technet, but Modified to give more choices
# Edited by Dan Burgess
# nerd@EverydayNerd.com

param([string] $dpmname, [string] $pgname, [string] $backupoption)
# Clear the screen
cls
#Get name of Localhost
$CompStat = Get-WmiObject win32_computersystem
$Localhst = $CompStat.Name

# Notify that connected to Localhost
write-host ""
write-host "Script: Create-RecoveryPoint" -foregroundcolor Blue -backgroundcolor white
write-host ""
write-host ""
Write-host "Connected to Localhost: $Localhst" -foregroundcolor Blue -backgroundcolor white
write-host ""
write-host ""

# Set DPM Servername
$dpmname = read-host "DPM Server Name (Enter for $Localhst):"
if ($dpmname -eq "")
{
$dpmname = $Localhst
write-host "Using Localhost $dpmname " -foregroundcolor green
write-host ""
write-host ""
}

# List Protection Groups on DPM server
$pglist = get-protectiongroup -DPMServerName $dpmname
write-host "Protection Groups on $dpmname :" -foregroundcolor green
write-output $pglist
write-host ""
write-host ""

#Enter name of Protection Group you wish to create Recovery Point
$pgname = read-host "Enter Protection Group Name:"
write-host ""
write-host ""

#List choices for JobChoice1 Variable
write-host "1: Express Full"
write-host "2: Incremental"
write-host ""

$JobChoice1 = read-host "Enter Backup type - 1 or 2 [Default is 1: Express Full]:"

switch ($JobChoice1)
{
1 { $backupoption = 'ExpressFull' }
2 { $backupoption = 'Incremental' }
default { $backupoption = 'ExpressFull' }
}
write-host ""
Write-host "You selected $backupoption" -foregroundcolor Blue -backgroundcolor white
write-host ""

trap{"Error in execution... $_";break}

if($clipg -eq $abc)
{
write-host ""
Throw "No ProtectionGroup found"
write-host ""
}
else
{
write-host ""
write-host "Getting DataSource from Protection Group $pgname..." -foregroundcolor green
write-host ""

# Create variable of each Datasource from Protection Group
$backupds = @(Get-Datasource $clipg)

# Run the Job for each DataSource in Protection Group
foreach ($ds in $backupds)
{
write-host ""
write-host "Creating Recovery point for $ds..." -foregroundcolor Blue -backgroundcolor white
write-host ""

$job = New-RecoveryPoint -Datasource $ds -Disk -BackupType $backupoption
$jobtype = $job.jobtype
Write-host "$jobtype Job has been triggerred..." -foregroundcolor green
}
}
}

I’ve been playing around with this script for a while, and there is more that I want to do to it, but I figured I’d share it, and hope it helps someone out.  I’d love some input on how to make the script better!

One thing I’d really like to do, but have not been able to figure it out yet, is have a status update at the end, updating every 10 seconds showing the Server name, PGname, Status, and HasCompleted – until True.  Just a thought… would save me from having to RDP into all the DPM servers…





Powershell Script to list all Cluster Active Nodes

9 01 2009

If you have a medium to large infrastructure, it is helpful to know what node of your Exchange Clusters is the active node.  This can be done manually, but it is much easier if done with the following script:

 

$Clusters = Get-MailboxServer | Where-Object { $_.RedundantMachines } | Select Name
 
 foreach ($cluster in $clusters) {
    Get-ClusteredMailboxServerStatus -identity $Cluster.name | Select OperationalMachines,State 
 
    }





Script to remove all datasources in Inactive Protection

25 09 2008

After I moved several protected servers from one DPM server to another, I had a LOT of exchange storage groups left in the Inactive Protection that I wanted to get rid of.  Doing this  manually was very time consuming, and lots of clicks.  So, after a quick search, I found a script on the Ctrl P blog that does exactly what I needed to do!

Usage:

Remove-InactiveDatasource.ps1 -DPMServerName [DPMServername] -RemoveOption [Remove Options]

Run ‘Remove-InactiveDatasource.ps1 -detailed’ for detailed help

Attachment: Remove-InactiveDatasource.ps1








Design a site like this with WordPress.com
Get started