Pushing the Envelope in Messaging Development

Saturday, March 29, 2008

Default Calendar permission Powershell Gui for Exchange 2007

This is a sample script that uses the calendar permission helper class I posted here. This script basically presents a Winform that can be used to firstly enumerate all the default calendar permissions of all mailboxes on an Exchange Server and then you can do a multiple select and set a new default calendar permission level for one or more mailboxes. The script gives the option of specifying the authentication setting to use and the Cas Server you want to use. By default it tries to locate a cas server using the get- WebServicesVirtualDirectory cmdlet eg

[array]$calurls = Get-WebServicesVirtualDirectory
$strRootURI = $calurls[0].InternalUrl.AbsoluteUri
$strRootURI

Using EWS impersonation allows you to set the calendar setting on a mailbox that the account running the script doesn’t have permissions to access to setup impersonation in EWS have a look at this from the Exchange SDK. The Specify Credentials check box allows you to specify the user credential to use when running the EWS operations. This script does rely on the Exchange-cmdlet's get-mailbox and get-user so it needs to be run from within the Exchange Management Shell.

If you select to use Exchange Impersonation the script will check to see if the account its going to impersonate first is disabled if it is then impersonation will not be use because you can’t impersonate a disable account.

To use the script you need to download the library from the other post as I marked in that post this code itself is very untested and I don’t consider it stable and or safe for use in a production environment I can only recommend that you use it in a test/dev environment and as a guide to building your own applications. The library needs to be located in the directory referenced in the following line

[void][Reflection.Assembly]::LoadFile("c:\temp\EWSUtil.dll")

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

Warning this code may cause global warming if you use the Air con when you don't need to

[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
[void][Reflection.Assembly]::LoadFile("c:\temp\EWSUtil.dll")
[array]$calurls = Get-WebServicesVirtualDirectory
$strRootURI = $calurls[0].InternalUrl.AbsoluteUri
$strRootURI

function GetPerms(){
$logTable.clear()


get-mailbox -server $snServerNameDrop.SelectedItem.ToString() -ResultSize Unlimited | foreach-object{$colnum
$defperm = ""
$unUsername = ""
$pnPpassword = ""
$dnDomainName = ""
$inInpersonate = $false
if ($seAuthCheck.Checked -eq $true){
$unUsername = $unUserNameTextBox.Text
$pnPpassword = $unPasswordTextBox.Text
$dnDomainName = $unDomainTextBox.Text
}
if ($seImpersonationCheck.Checked -eq $true){
$uoUser = [ADSI]("LDAP://" + $_.DistinguishedName.ToString())
if ($uoUser.PSBase.InvokeGet("AccountDisabled") -ne $true){$inInpersonate = $true }

}
$calutil = new-object EWSUtil.CalendarUtil($_.WindowsEmailAddress,$inInpersonate,$unUsername,$pnPpassword,$dnDomainName,$unCASUrlTextBox.text)
for ($cpint=0;$cpint -lt $calutil.CalendarDACL.Count; $cpint++){
if ($calutil.CalendarDACL[$cpint].UserId.DistinguishedUserSpecified -eq $true){
if ($calutil.CalendarDACL[$cpint].UserId.DistinguishedUser -eq [EWSUtil.EWS.DistinguishedUserType]::Default){
write-host "Processing : " + $_.WindowsEmailAddress
$defperm = $calutil.enumOutlookRole($calutil.CalendarDACL[$cpint])
}

}
}
$logTable.rows.add($_.DisplayName,$_.WindowsEmailAddress,$defperm)
}
$dgDataGrid.DataSource = $logTable

}


Function UpdatePerms{
$unUsername = ""
$pnPpassword = ""
$dnDomainName = ""
$inInpersonate = $false
if ($seAuthCheck.Checked -eq $true){
$unUsername = $unUserNameTextBox.Text
$pnPpassword = $unPasswordTextBox.Text
$dnDomainName = $unDomainTextBox.Text
}
if ($seImpersonationCheck.Checked -eq $true){
$mbchk = get-mailbox $dgDataGrid.Rows[$dgDataGrid.CurrentCell.RowIndex].Cells[1].Value
$uoUser = [ADSI]("LDAP://" + $mbchk.DistinguishedName.ToString())
if ($uoUser.PSBase.InvokeGet("AccountDisabled") -ne $true){$inInpersonate = $true }

}
if ($dgDataGrid.SelectedRows.Count -eq 0){
$mbtoSet = $dgDataGrid.Rows[$dgDataGrid.CurrentCell.RowIndex].Cells[1].Value
$calutil = new-object EWSUtil.CalendarUtil($mbtoSet,$inInpersonate,$unUsername,$pnPpassword,$dnDomainName,$unCASUrlTextBox.text)
switch ($npNewpermDrop.Text){
"None" {$calutil.CalendarDACL.Add($calutil.NonePermissions("default"))}
"FreeBusyTimeOnly" {$calutil.CalendarDACL.Add($calutil.FreeBusyTimeOnly("default"))}
"FreeBusyTimeAndSubjectAndLocation" {$calutil.CalendarDACL.Add($calutil.FreeBusyTimeAndSubjectAndLocation("default"))}
"Reviewer" {$calutil.CalendarDACL.Add($calutil.Reviewer("default"))}
"Contributer" {$calutil.CalendarDACL.Add($calutil.Contributer("default"))}
"Author" {$calutil.CalendarDACL.Add($calutil.AuthorPermissions("default"))}
"NonEditingAuthor" {$calutil.CalendarDACL.Add($calutil.NonEditingAuthorPermissions("default"))}
"PublishingAuthor" {$calutil.CalendarDACL.Add($calutil.PublishingAuthorPermissions("default"))}
"Author" {$calutil.CalendarDACL.Add($calutil.AuthorPermissions("default"))}
"Editor" {$calutil.CalendarDACL.Add($calutil.EditorPermissions("default"))}
"PublishingEditor"{$calutil.CalendarDACL.Add($calutil.PublishingEditorPermissions("default"))}
}
$calutil.update()
write-host "Permission updated" + $npNewpermDrop.Text
}
else{
$lcLoopCount = 0
while ($lcLoopCount -le ($dgDataGrid.SelectedRows.Count-1)) {
$mbtoSet = $dgDataGrid.SelectedRows[$lcLoopCount].Cells[1].Value
$calutil = new-object EWSUtil.CalendarUtil($mbtoSet,$inInpersonate,$unUsername,$pnPpassword,$dnDomainName,$unCASUrlTextBox.text)
switch ($npNewpermDrop.Text){
"None" {$calutil.CalendarDACL.Add($calutil.NonePermissions("default"))}
"FreeBusyTimeOnly" {$calutil.CalendarDACL.Add($calutil.FreeBusyTimeOnly("default"))}
"FreeBusyTimeAndSubjectAndLocation" {$calutil.CalendarDACL.Add($calutil.FreeBusyTimeAndSubjectAndLocation("default"))}
"Reviewer" {$calutil.CalendarDACL.Add($calutil.Reviewer("default"))}
"Contributer" {$calutil.CalendarDACL.Add($calutil.Contributer("default"))}
"Author" {$calutil.CalendarDACL.Add($calutil.AuthorPermissions("default"))}
"NonEditingAuthor" {$calutil.CalendarDACL.Add($calutil.NonEditingAuthorPermissions("default"))}
"PublishingAuthor" {$calutil.CalendarDACL.Add($calutil.PublishingAuthorPermissions("default"))}
"Author" {$calutil.CalendarDACL.Add($calutil.AuthorPermissions("default"))}
"Editor" {$calutil.CalendarDACL.Add($calutil.EditorPermissions("default"))}
"PublishingEditor"{$calutil.CalendarDACL.Add($calutil.PublishingEditorPermissions("default"))}
}
$calutil.update()
write-host "Permission updated" + $npNewpermDrop.Text
$lcLoopCount += 1
}
}
write-host "end PermUpdate"
write-host "Refresh Perms"
GetPerms
}


$form = new-object System.Windows.Forms.form
$form.Text = "Calender Permission Enum Tool"
$Dataset = New-Object System.Data.DataSet
$logTable = New-Object System.Data.DataTable
$logTable.TableName = "ActiveSyncLogs"
$logTable.Columns.Add("DisplayName");
$logTable.Columns.Add("EmailAddress");
$logTable.Columns.Add("Default-Permissions");



# 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(70,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(80,20)
$snServerNameDrop.Size = new-object System.Drawing.Size(130,30)
get-exchangeserver | ForEach-Object{$snServerNameDrop.Items.Add($_.Name)}
$form.Controls.Add($snServerNameDrop)


# Add Get Perms Button

$gpgetperms = new-object System.Windows.Forms.Button
$gpgetperms.Location = new-object System.Drawing.Size(220,20)
$gpgetperms.Size = new-object System.Drawing.Size(85,23)
$gpgetperms.Text = "Enum Perms"
$gpgetperms.Add_Click({GetPerms})
$form.Controls.Add($gpgetperms)

# Add New Permission Drop Down
$npNewpermDrop = new-object System.Windows.Forms.ComboBox
$npNewpermDrop.Location = new-object System.Drawing.Size(350,20)
$npNewpermDrop.Size = new-object System.Drawing.Size(190,30)
$npNewpermDrop.Items.Add("None")
$npNewpermDrop.Items.Add("FreeBusyTimeOnly")
$npNewpermDrop.Items.Add("FreeBusyTimeAndSubjectAndLocation")
$npNewpermDrop.Items.Add("Reviewer")
$npNewpermDrop.Items.Add("Contributer")
$npNewpermDrop.Items.Add("Author")
$npNewpermDrop.Items.Add("NonEditingAuthor")
$npNewpermDrop.Items.Add("PublishingAuthor")
$npNewpermDrop.Items.Add("Editor")
$npNewpermDrop.Items.Add("PublishingEditor")
$form.Controls.Add($npNewpermDrop)

# Add Apply Button

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

# New setting Group Box

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

# Add Impersonation Clause

$esImpersonationlableBox = new-object System.Windows.Forms.Label
$esImpersonationlableBox.Location = new-object System.Drawing.Size(10,50)
$esImpersonationlableBox.Size = new-object System.Drawing.Size(130,20)
$esImpersonationlableBox.Text = "Use EWS Impersonation"
$form.Controls.Add($esImpersonationlableBox)

$seImpersonationCheck = new-object System.Windows.Forms.CheckBox
$seImpersonationCheck.Location = new-object System.Drawing.Size(140,45)
$seImpersonationCheck.Size = new-object System.Drawing.Size(30,25)
$form.Controls.Add($seImpersonationCheck)

# Add Auth Clause

$esAuthlableBox = new-object System.Windows.Forms.Label
$esAuthlableBox.Location = new-object System.Drawing.Size(10,70)
$esAuthlableBox.Size = new-object System.Drawing.Size(130,20)
$esAuthlableBox.Text = "Specify Credentials"
$form.Controls.Add($esAuthlableBox)

$seAuthCheck = new-object System.Windows.Forms.CheckBox
$seAuthCheck.Location = new-object System.Drawing.Size(140,65)
$seAuthCheck.Size = new-object System.Drawing.Size(30,25)
$seAuthCheck.Add_Click({if ($seAuthCheck.Checked -eq $true){
$unUserNameTextBox.Enabled = $true
$unPasswordTextBox.Enabled = $true
$unDomainTextBox.Enabled = $true
}
else{
$unUserNameTextBox.Enabled = $false
$unPasswordTextBox.Enabled = $false
$unDomainTextBox.Enabled = $false}})
$form.Controls.Add($seAuthCheck)

# Add UserName Box
$unUserNameTextBox = new-object System.Windows.Forms.TextBox
$unUserNameTextBox.Location = new-object System.Drawing.Size(230,70)
$unUserNameTextBox.size = new-object System.Drawing.Size(100,20)
$form.Controls.Add($unUserNameTextBox)

# Add UserName Lable
$unUserNamelableBox = new-object System.Windows.Forms.Label
$unUserNamelableBox.Location = new-object System.Drawing.Size(170,70)
$unUserNamelableBox.size = new-object System.Drawing.Size(60,20)
$unUserNamelableBox.Text = "UserName"
$unUserNameTextBox.Enabled = $false
$form.Controls.Add($unUserNamelableBox)

# Add Password Box
$unPasswordTextBox = new-object System.Windows.Forms.TextBox
$unPasswordTextBox.PasswordChar = "*"
$unPasswordTextBox.Location = new-object System.Drawing.Size(400,70)
$unPasswordTextBox.size = new-object System.Drawing.Size(100,20)
$form.Controls.Add($unPasswordTextBox)

# Add Password Lable
$unPasswordlableBox = new-object System.Windows.Forms.Label
$unPasswordlableBox.Location = new-object System.Drawing.Size(340,70)
$unPasswordlableBox.size = new-object System.Drawing.Size(60,20)
$unPasswordlableBox.Text = "Password"
$unPasswordTextBox.Enabled = $false
$form.Controls.Add($unPasswordlableBox)

# Add Domain Box
$unDomainTextBox = new-object System.Windows.Forms.TextBox
$unDomainTextBox.Location = new-object System.Drawing.Size(550,70)
$unDomainTextBox.size = new-object System.Drawing.Size(100,20)
$form.Controls.Add($unDomainTextBox)

# Add Domain Lable
$unDomainlableBox = new-object System.Windows.Forms.Label
$unDomainlableBox.Location = new-object System.Drawing.Size(510,70)
$unDomainlableBox.size = new-object System.Drawing.Size(50,20)
$unDomainlableBox.Text = "Domain"
$unDomainTextBox.Enabled = $false
$form.Controls.Add($unDomainlableBox)

# Add CASUrl Box
$unCASUrlTextBox = new-object System.Windows.Forms.TextBox
$unCASUrlTextBox.Location = new-object System.Drawing.Size(70,100)
$unCASUrlTextBox.size = new-object System.Drawing.Size(500,20)
$unCASUrlTextBox.text = $strRootURI
$form.Controls.Add($unCASUrlTextBox)

# Add CASUrl Lable
$unCASUrllableBox = new-object System.Windows.Forms.Label
$unCASUrllableBox.Location = new-object System.Drawing.Size(10,100)
$unCASUrllableBox.size = new-object System.Drawing.Size(60,20)
$unCASUrllableBox.Text = "CASUrl"
$form.Controls.Add($unCASUrllableBox)


# Add DataGrid View

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


$form.Text = "Exchange 2007 Default Calendar Permissions Form"
$form.size = new-object System.Drawing.Size(700,730)

$form.autoscroll = $true
$form.topmost = $true
$form.Add_Shown({$form.Activate()})
$form.ShowDialog()

9 comments:

Elan Shudnow said...

Excellent! Thanks for this Glen. I've seen the question come up several times on how we can go about modifying all mailboxes Default permission to Reviewer so users can open up each other's calendar. This is really easy now with your script.

jerry said...

Thanks Glen! i have one issue though, what if i just want my resource mailboxes to be able to be reviewed domain wide? so every user in the domain will have "reviewer" status to all the resource mailboxes? any further help would be awesome.

Don Vecchioni said...

Very nice job Glen. Thanks for the guidance. This got me over a big hump in picking through all of these methods!

Anonymous said...

Really awesome - thanks a lot.

Christian Wickham said...

This is fantastic. But, is there a way that I can use this as just a command? We have a script that creates new resource mailboxes, assigns Calendar Attendant properties etc - but I want to set the default permission on the calendar to be "Default Reviewer" on the new resource mailbox.
What you have here is great for administration, but I need something for creation of mailboxes - can you help?

Glen said...

Have a look at http://gsexdev.blogspot.com/2008/03/class-library-helper-for-setting.html which goes through using this from a more single mailbox level. Bascially after the mailbox is created you need to write a script that will logon and then set the folder permissions. You have to be carefull if you have users using a language other then english.

Cheers
Glen

Steve McNutt said...

Thanks for the script, it was a big help with my permissions which had apparently been mangled through years of regular use.

I had to make one minor change though. In order to pull up the mailboxes for the entire forest I had to change line 12 from:
get-mailbox -server...
to:
get-mailbox -IgnoreDefaultScope -server...

Not sure if that's the way it's supposed to work if the command was just covering for a misconfiguration on my part...

Anonymous said...

Glen

Many thanks for this article great post! I have a question and I would be grateful if you could answer I have followed through the script and I am at Exchange 2007 default calender permission form i see all my users when i select all and give reviewer rights I can not open another shared calender in OWA by doing:

https://server.owa/user@company.com?cmd=contents&f=Calendar&view=Weekly

It says I do not have permission what am I doing wrong? And is th permission change instant? I have just changed the permissions and I am attempting to try straight away

Glen said...

It should work pretty much straight away could be a negative caching issue ?

Cheers
Glen