Last active
March 14, 2025 16:01
-
-
Save noahpeltier/0b8e4548accdd2faa3adebbdcb9c1c17 to your computer and use it in GitHub Desktop.
Winforms GUI that displays Exchange Online public folders in a tree view with options for adding and/or modifying existing permissions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Optionally, connect to Exchange Online if not already connected: | |
# Import-Module ExchangeOnlineManagement | |
if (-not (get-command get-mailbox -ErrorAction SilentlyContinue) ) { | |
Connect-ExchangeOnline | |
} | |
# Load required .NET assemblies for WinForms | |
Add-Type -AssemblyName System.Windows.Forms | |
Add-Type -AssemblyName System.Drawing | |
# Define permission options based on Microsoft's public folder permission levels | |
$permissionOptions = @("Owner", "PublishingEditor", "Editor", "PublishingAuthor", "Author", "NonEditingAuthor", "Reviewer", "Contributor", "None") | |
# Global variable to hold the current folder path | |
$Global:currentFolder = $null | |
# Function to refresh the permissions ListView for the currently selected folder | |
function Refresh-Permissions { | |
if (-not $Global:currentFolder) { return } | |
$listView.Items.Clear() | |
try { | |
$permissions = Get-PublicFolderClientPermission -Identity $Global:currentFolder | |
foreach ($perm in $permissions) { | |
$user = $perm.User.ToString() | |
$access = $perm.AccessRights -join ", " | |
$item = New-Object System.Windows.Forms.ListViewItem($user) | |
$item.SubItems.Add($access) | |
$listView.Items.Add($item) | |
} | |
} | |
catch { | |
[System.Windows.Forms.MessageBox]::Show("Error retrieving permissions for folder: $Global:currentFolder","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | |
} | |
} | |
# Create the main form | |
$form = New-Object System.Windows.Forms.Form | |
$form.Text = "Exchange Online Public Folders Manager" | |
$form.Size = New-Object System.Drawing.Size(900,600) | |
$form.StartPosition = "CenterScreen" | |
# Create left panel for the TreeView (fixed width) | |
$panelLeft = New-Object System.Windows.Forms.Panel | |
$panelLeft.Dock = [System.Windows.Forms.DockStyle]::Left | |
$panelLeft.Width = 250 | |
$panelLeft.Padding = New-Object System.Windows.Forms.Padding(10) | |
# Create right panel for controls (fixed width) | |
$panelRight = New-Object System.Windows.Forms.Panel | |
$panelRight.Dock = [System.Windows.Forms.DockStyle]::Right | |
$panelRight.Width = 250 | |
$panelRight.Padding = New-Object System.Windows.Forms.Padding(10) | |
# Create center panel for the ListView (fills remaining space) | |
$panelCenter = New-Object System.Windows.Forms.Panel | |
$panelCenter.Dock = [System.Windows.Forms.DockStyle]::Fill | |
$panelCenter.Padding = New-Object System.Windows.Forms.Padding(10) | |
# --------------------------- | |
# Left Panel - TreeView for Public Folders | |
# --------------------------- | |
$treeView = New-Object System.Windows.Forms.TreeView | |
$treeView.Dock = [System.Windows.Forms.DockStyle]::Fill | |
$panelLeft.Controls.Add($treeView) | |
# --------------------------- | |
# Center Panel - ListView for Permissions | |
# --------------------------- | |
$listView = New-Object System.Windows.Forms.ListView | |
$listView.Dock = [System.Windows.Forms.DockStyle]::Fill | |
$listView.View = [System.Windows.Forms.View]::Details | |
$listView.FullRowSelect = $true | |
$listView.GridLines = $true | |
$listView.Columns.Add("User",150) | Out-Null | |
$listView.Columns.Add("Permission Level",130) | Out-Null | |
$panelCenter.Controls.Add($listView) | |
# --------------------------- | |
# Right Panel - Controls for Modifying Permissions | |
# --------------------------- | |
# Note: Use relative positioning within the right panel. | |
# The panel's width is fixed (250), so set control widths to fill (minus padding). | |
$controlWidth = $panelRight.Width - 20 # subtracting left/right padding | |
$btnRemove = New-Object System.Windows.Forms.Button | |
$btnRemove.Location = New-Object System.Drawing.Point(10,20) | |
$btnRemove.Size = New-Object System.Drawing.Size($controlWidth,30) | |
$btnRemove.Text = "Remove Selected User" | |
$btnRemove.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($btnRemove) | |
$lblUpdate = New-Object System.Windows.Forms.Label | |
$lblUpdate.Location = New-Object System.Drawing.Point(10,70) | |
$lblUpdate.Size = New-Object System.Drawing.Size($controlWidth,20) | |
$lblUpdate.Text = "New Permission (Update):" | |
$lblUpdate.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($lblUpdate) | |
$cmbUpdatePermission = New-Object System.Windows.Forms.ComboBox | |
$cmbUpdatePermission.Location = New-Object System.Drawing.Point(10,95) | |
$cmbUpdatePermission.Size = New-Object System.Drawing.Size($controlWidth,25) | |
$cmbUpdatePermission.DropDownStyle = 'DropDownList' | |
$cmbUpdatePermission.Items.AddRange($permissionOptions) | |
$cmbUpdatePermission.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($cmbUpdatePermission) | |
$btnUpdate = New-Object System.Windows.Forms.Button | |
$btnUpdate.Location = New-Object System.Drawing.Point(10,130) | |
$btnUpdate.Size = New-Object System.Drawing.Size($controlWidth,30) | |
$btnUpdate.Text = "Update Selected User" | |
$btnUpdate.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($btnUpdate) | |
$lblAddHeader = New-Object System.Windows.Forms.Label | |
$lblAddHeader.Location = New-Object System.Drawing.Point(10,180) | |
$lblAddHeader.Size = New-Object System.Drawing.Size($controlWidth,20) | |
$lblAddHeader.Text = "Add New User:" | |
$lblAddHeader.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($lblAddHeader) | |
$lblNewUser = New-Object System.Windows.Forms.Label | |
$lblNewUser.Location = New-Object System.Drawing.Point(10,210) | |
$lblNewUser.Size = New-Object System.Drawing.Size(80,20) | |
$lblNewUser.Text = "User:" | |
$lblNewUser.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left | |
$panelRight.Controls.Add($lblNewUser) | |
$txtNewUser = New-Object System.Windows.Forms.TextBox | |
$txtNewUser.Location = New-Object System.Drawing.Point(100,210) | |
$txtNewUser.Size = New-Object System.Drawing.Size(($controlWidth - 90),25) | |
$txtNewUser.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($txtNewUser) | |
$lblNewPerm = New-Object System.Windows.Forms.Label | |
$lblNewPerm.Location = New-Object System.Drawing.Point(10,245) | |
$lblNewPerm.Size = New-Object System.Drawing.Size(80,20) | |
$lblNewPerm.Text = "Permission:" | |
$lblNewPerm.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left | |
$panelRight.Controls.Add($lblNewPerm) | |
$cmbNewPermission = New-Object System.Windows.Forms.ComboBox | |
$cmbNewPermission.Location = New-Object System.Drawing.Point(100,245) | |
$cmbNewPermission.Size = New-Object System.Drawing.Size(($controlWidth - 90),25) | |
$cmbNewPermission.DropDownStyle = 'DropDownList' | |
$cmbNewPermission.Items.AddRange($permissionOptions) | |
$cmbNewPermission.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($cmbNewPermission) | |
$btnAdd = New-Object System.Windows.Forms.Button | |
$btnAdd.Location = New-Object System.Drawing.Point(10,280) | |
$btnAdd.Size = New-Object System.Drawing.Size($controlWidth,30) | |
$btnAdd.Text = "Add New User" | |
$btnAdd.Anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Left -bor [System.Windows.Forms.AnchorStyles]::Right | |
$panelRight.Controls.Add($btnAdd) | |
# --------------------------- | |
# Add panels to the form | |
# Order is important when docking. The Fill-docked panel should be added first. | |
$form.Controls.Add($panelCenter) | |
$form.Controls.Add($panelRight) | |
$form.Controls.Add($panelLeft) | |
# --------------------------- | |
# Populate the TreeView with Public Folders | |
# --------------------------- | |
try { | |
$publicFolders = Get-PublicFolder -Identity "\" -Recurse -ResultSize Unlimited | |
} | |
catch { | |
[System.Windows.Forms.MessageBox]::Show("Error retrieving public folders. Please ensure you are connected to Exchange Online.","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | |
return | |
} | |
# Hashtable to store folder path => TreeNode mappings | |
$treeNodes = @{} | |
$sortedFolders = $publicFolders | Sort-Object { ($_.Identity.ToString().TrimEnd("\") -split "\\").Count } | |
foreach ($folder in $sortedFolders) { | |
$folderPath = $folder.Identity.ToString() | |
if ($folderPath -eq "\") { | |
$node = New-Object System.Windows.Forms.TreeNode("Public Folders") | |
$node.Tag = $folderPath | |
$treeView.Nodes.Add($node) | Out-Null | |
$treeNodes[$folderPath] = $node | |
} | |
else { | |
$folderName = $folder.Name | |
$index = $folderPath.LastIndexOf("\") | |
if ($index -le 0) { | |
$parentPath = "\" | |
} | |
else { | |
$parentPath = $folderPath.Substring(0, $index) | |
if ($parentPath -eq "") { $parentPath = "\" } | |
} | |
$node = New-Object System.Windows.Forms.TreeNode($folderName) | |
$node.Tag = $folderPath | |
if ($treeNodes.ContainsKey($parentPath)) { | |
$treeNodes[$parentPath].Nodes.Add($node) | Out-Null | |
} | |
else { | |
$treeView.Nodes.Add($node) | Out-Null | |
} | |
$treeNodes[$folderPath] = $node | |
} | |
} | |
# When a node is selected, update the current folder and refresh permissions | |
$treeView.Add_AfterSelect({ | |
param($sender, $e) | |
$Global:currentFolder = $e.Node.Tag | |
Refresh-Permissions | |
}) | |
# --------------------------- | |
# Button Event Handlers | |
# --------------------------- | |
# Remove Selected User | |
$btnRemove.Add_Click({ | |
if (-not $Global:currentFolder) { | |
[System.Windows.Forms.MessageBox]::Show("No folder selected.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
if ($listView.SelectedItems.Count -eq 0) { | |
[System.Windows.Forms.MessageBox]::Show("No user selected in the permissions list.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
$selectedUser = $listView.SelectedItems[0].Text | |
try { | |
Remove-PublicFolderClientPermission -Identity $Global:currentFolder -User $selectedUser -Confirm:$false | |
[System.Windows.Forms.MessageBox]::Show("User '$selectedUser' removed successfully.","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | |
Refresh-Permissions | |
} | |
catch { | |
[System.Windows.Forms.MessageBox]::Show("Error removing user '$selectedUser'.","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | |
} | |
}) | |
# Update Selected User's Permissions | |
$btnUpdate.Add_Click({ | |
if (-not $Global:currentFolder) { | |
[System.Windows.Forms.MessageBox]::Show("No folder selected.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
if ($listView.SelectedItems.Count -eq 0) { | |
[System.Windows.Forms.MessageBox]::Show("No user selected in the permissions list.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
$newPermission = $cmbUpdatePermission.Text.Trim() | |
if ([string]::IsNullOrEmpty($newPermission)) { | |
[System.Windows.Forms.MessageBox]::Show("Please select a new permission level from the dropdown.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
$Script:selectedUser = $listView.SelectedItems[0].Text | |
try { | |
# Remove and then re-add with the new permission level | |
Remove-PublicFolderClientPermission -Identity $Global:currentFolder -User $selectedUser -Confirm:$false | |
Add-PublicFolderClientPermission -Identity $Global:currentFolder -User $selectedUser -AccessRights $newPermission | |
[System.Windows.Forms.MessageBox]::Show("User '$selectedUser' updated to '$newPermission'.","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | |
Refresh-Permissions | |
} | |
catch { | |
[System.Windows.Forms.MessageBox]::Show("Error updating user '$selectedUser' permission to $($newPermission).`n$($_.Exception.Message)","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | |
} | |
}) | |
# Add New User | |
$btnAdd.Add_Click({ | |
if (-not $Global:currentFolder) { | |
[System.Windows.Forms.MessageBox]::Show("No folder selected.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
$newUser = $txtNewUser.Text.Trim() | |
$newPermission = $cmbNewPermission.Text.Trim() | |
if ([string]::IsNullOrEmpty($newUser) -or [string]::IsNullOrEmpty($newPermission)) { | |
[System.Windows.Forms.MessageBox]::Show("Please enter both a user and select a permission level.","Warning",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Warning) | |
return | |
} | |
try { | |
Add-PublicFolderClientPermission -Identity $Global:currentFolder -User $newUser -AccessRights $newPermission | |
[System.Windows.Forms.MessageBox]::Show("User '$newUser' added with '$newPermission'.","Info",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Information) | |
Refresh-Permissions | |
} | |
catch { | |
[System.Windows.Forms.MessageBox]::Show("Error adding user '$newUser'.","Error",[System.Windows.Forms.MessageBoxButtons]::OK,[System.Windows.Forms.MessageBoxIcon]::Error) | |
} | |
}) | |
# Ensure the form gets focus when shown and run the form | |
$form.Add_Shown({ $form.Activate() }) | |
[System.Windows.Forms.Application]::EnableVisualStyles(); | |
[void] $form.ShowDialog() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment