Thursday, January 11, 2007

Exchange 2007 diagnostic logging Powershell quick set winform script

One of the things that has been dropped from the GUI (Exchange Management Console) in Exchange 2007 is the ability to set the diagnostic level of different Exchange components. You now have to use the Exchange Management Shell cmdlets get-eventloglevel and set-eventloglevel. While functional if you have to enable a number of different categories if you are trying to diagnose certain problems it can be a little cumbersome to try and come up with a different command-line for each one of the possible 150 components you might want to change. Because I do tend to enable and disable these things a fair bit when trying to fix a problems or diagnose why a piece a code or script might not be working I thought I’d come up with a little Powershell winform that would give me a GUI to do this with and allow me to quickly set the diagnostic logging level on a number of components with a few clicks of the mouse.

The script first starts by presenting a Winform to the user with one combo box which is populated with all the names of the Exchange servers in the Org populated from the Get-Exchangeserver cmdlet. When a servername is selected the getdiagvalues function runs which uses the get-eventloglevel cmdlet to fill a datagrid with all the current log levels for all components on that server. To set a new log level just select the row (or rows if you want to do multiple) and then the new log level from the combo box at the top of the form and press the apply button. When the apply button is pressed the UpdateLogLevel function is run this function first checks to see if multiple row in the grid where selected or just one row and then builds and executes the set-eventloglevel commandlet. After this it reruns the getdiagvalues function which repopulates the datagrid with the updated values.

The script is designed to run from within the Exchange Management shell it should work for remote servers okay but I haven’t really tested this and the set-eventloglevel doesn’t take a server parameter (where get-eventloglevel does).

I’ve put a download copy of the script here the script itself looks like


[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
Function getdiagvalues{
$daTable.clear()
$dgDataGrid.DataSource = $daTable
get-eventloglevel -Server $snServerNameDrop.SelectedItem.ToString() | ForEach-Object{
$daTable.Rows.Add($_.Identity,$_.EventLevel)
}
$dgDataGrid.DataSource = $daTable
}

Function UpdateLogLevel{
if ($dgDataGrid.SelectedRows.Count -eq 0){
$idIdtoSet = $dgDataGrid.Rows[$dgDataGrid.CurrentCell.RowIndex].Cells[0].Value
set-eventloglevel -Identity $idIdtoSet -Level $llLoglevelDrop.Text
}
else{
$msgbox = new-object -comobject wscript.shell
$lcLoopCount = 0
while ($lcLoopCount -le ($dgDataGrid.SelectedRows.Count-1)) {
# [void]$msgbox.popup($dgDataGrid.SelectedRows[$lcLoopCount].Cells[0].Value,0,"Cant Do MX lookup",1)
set-eventloglevel -Identity $dgDataGrid.SelectedRows[$lcLoopCount].Cells[0].Value -Level $llLoglevelDrop.SelectedItem
$lcLoopCount += 1}
}
getdiagvalues
}

$form = new-object System.Windows.Forms.form

$llLableloc = 50
$VlLoc = 50

$Dataset = New-Object System.Data.DataSet
$daTable = New-Object System.Data.DataTable
$daTable.TableName = "Diag"
$daTable.Columns.Add("Identity")
$daTable.Columns.Add("Current Setting")


# Add Server DropLable
$snServerNamelableBox = new-object System.Windows.Forms.Label
$snServerNamelableBox.Location = new-object System.Drawing.Size(10,20)
$snServerNamelableBox.size = new-object System.Drawing.Size(100,20)
$snServerNamelableBox.Text = "ServerName"
$form.Controls.Add($snServerNamelableBox)

# Add Server Drop Down
$snServerNameDrop = new-object System.Windows.Forms.ComboBox
$snServerNameDrop.Location = new-object System.Drawing.Size(130,20)
$snServerNameDrop.Size = new-object System.Drawing.Size(130,30)
get-exchangeserver | ForEach-Object{$snServerNameDrop.Items.Add($_.Name)}
$snServerNameDrop.Add_SelectedValueChanged({getdiagvalues})
$form.Controls.Add($snServerNameDrop)

# Add New Log Level Drop Down
$llLoglevelDrop = new-object System.Windows.Forms.ComboBox
$llLoglevelDrop.Location = new-object System.Drawing.Size(350,20)
$llLoglevelDrop.Size = new-object System.Drawing.Size(70,30)
$llLoglevelDrop.Items.Add("Lowest")
$llLoglevelDrop.Items.Add("Low")
$llLoglevelDrop.Items.Add("Medium")
$llLoglevelDrop.Items.Add("High")
$llLoglevelDrop.Items.Add("Expert")
$form.Controls.Add($llLoglevelDrop)

# Add Apply Button

$exButton = new-object System.Windows.Forms.Button
$exButton.Location = new-object System.Drawing.Size(430,20)
$exButton.Size = new-object System.Drawing.Size(60,20)
$exButton.Text = "Apply"
$exButton.Add_Click({UpdateLogLevel})
$form.Controls.Add($exButton)

# New setting Group Box

$OfGbox = new-object System.Windows.Forms.GroupBox
$OfGbox.Location = new-object System.Drawing.Size(300,0)
$OfGbox.Size = new-object System.Drawing.Size(200,50)
$OfGbox.Text = "New Log Level Settings"
$form.Controls.Add($OfGbox)

# Add DataGrid View

$dgDataGrid = new-object System.windows.forms.DataGridView
$dgDataGrid.Location = new-object System.Drawing.Size(10,80)
$dgDataGrid.size = new-object System.Drawing.Size(500,500)
$dgDataGrid.AutoSizeColumnsMode = "AllCells"
$dgDataGrid.SelectionMode = "FullRowSelect"
$form.Controls.Add($dgDataGrid)


$form.Text = "Exchange 2007 Diagnostic Logging Form"
$form.size = new-object System.Drawing.Size(600,600)
$form.autoscroll = $true
$form.topmost = $true

$form.ShowDialog()

11 comments:

Anonymous said...

Great script. But is there a way to change it so that it does not go back to the top after applying a setting. Could be very handy when modifying a couple of settings from the same category, let's say transport. Now you have to scroll back down again everytime.

Thanks a lot

Glen said...

Yep sure is i've updated the download script to enable this thanks for the suggestion.

Cheers
Glen

Poul Wehner said...

Great work! thanks for the script.

Jeroen said...

Great tool..thanks

Anonymous said...

This is fantastic. Thank you thank you thank you!

Anonymous said...

Great tool, it saves me hours of time. Thanks a lot

Anonymous said...

Thanks heaps - Ive found your blogs invaluable over the years, and this is yet another very useful tool from you!

Anonymous said...

Thank you so much for this tool. Yesterday I had a major issue with an E2K7 server and it seemed inevitable that I would have to reboot but I wanted to capture as much in the way of diagnostics as possible before I did so. If I would have had this tool it would have made life sooooooooo much easier not to mention less downtime for affected users.

Richie Rich said...

This is awesome!

Here is my contribution back, easy- but useful. I like to keep a fixed # of users with specified quotas on each store. So I wrote a 5 line script. I will have it email out soon.

$userCount = 0
$userDatabase = Get-MailboxDatabase -identity mailsvr\store | Get-
Mailbox
Foreach ($user in $userDatabase) {
$userCount++
}
Write-Host There are $userCount users in store

Andrew Burt said...

Thank you very much for this - helps heaps with diagnosis!

Anonymous said...

why not just do

(Get-MailboxDatabase -identity mailsvr\store).count