PowerShell script to check permissions on mailbox folders (also recursively).

Hey there!

Some time ago I posted script that is checking general permissions of a mailbox like “FullAccess”, “ReadOnly” etc.:


Here is another one that is checking permissions on particular folders 🙂

Worth mentioning is that script is also checking groups recursively, and has – let me call it – anti-loop protection :] so if someone creates “Group_A” and “Group_B” and put A in B and B in A the script will notice that particular group has been already reported in that particular cycle, and won’t go deeper.

Parameters and examples:

MailboxFolderPermissions.ps1 – Mailbox folder permissions report generation script.

Generates a report of permissions that have been set on a folder

Single mailbox reports are output to the console, while all other
reports are output to a CSV file.

Generates a report for all mailboxes in the organization.

Generates a report for all mailboxes on the specified server.

.PARAMETER database
Generates a report for all mailboxes on the specified database.

Generates a report for mailbox names listed in the specified text file.

.PARAMETER mailbox
Generates a report only for the specified mailbox.

.PARAMETER filename
(Optional) Specifies the CSV file name to be used for the report.
If no file name specificed then a unique file name is generated by the script.

.\MailboxFolderPermissions.ps1 -database HO-MB-01
Returns a report with the mailbox statistics for all mailbox users in
database HO-MB-01

.\MailboxFolderPermissions.ps1 -file .\users.txt
Returns a report with the mailbox statistics for all mailbox users in
the file users.txt. Text file should contain names in a format that
will work for Get-Mailbox, such as the display name, alias, or primary
SMTP address.

.\MailboxFolderPermissions.ps1 -server ex2010-mb1
Generates a report with the mailbox statisitcs for all mailbox users
on ex2010-mb1

.\MailboxFolderPermissions.ps1 -server ex2010-mb1 -filename ex2010-mb1.csv
Generates a report with the mailbox statisitcs for all mailbox users
on ex2010-mb1, and uses the custom file name of ex2010-mb1.csv

Script can be downloaded from Technet and GitHub.

Remove cancelled Outlook meetings using PowerShell and EWS.



Recently there was a business demand for removal of meetings that were canceled in our resource mailboxes. Thought it was some sort of  a bug but then saw that problem was “AutomateProcessing” attribute on these was set to “AutoUpdate” not “AutoAccept” (This can be checked using Get-CalendarProcessing cmdlet).


So when someone is scheduling a meeting form his own mailbox and is picking up room – creates a meeting, and later changes his mind and removes it, it still is hanging there visible as “Canceled: Subject of the meeting“. And each time (because of that “AutoUpdate”) someone manually needs to go there and remove it.



After reading a bit about that topic, I realized that PowerShell script I was about to write needs to use EWS and impersonation in Exchange.

There are few things you need before running the script:

  • AD account used by the script
  • Security Group that will contain people who will have impersonation rights (admns/service accounts)
  • Distribution List that will contain room mailboxes – managed by admins/service accounts from Security Group
  • Management Scope in Exchange – narrowing scope for members of the Distribution List
  • Management Role Assigment – glue all that crap together – permission Security Group to Distribution List with “Application Impersonation” rights.

In commands it can look like:

1. Creating Distibution Group

New-DistributionGroup -Name ‘RoomImpersonationGroup‘ -Type ‘Distribution’ –OrganizationalUnit ‘contoso.com/Distribution Lists’ -SamAccountName ‘RoomImpersonationGroup’ -Alias ‘RoomImpersonationGroup’ –managedBy ‘PawelJarosz’

2. Creation of Exchange Management Scope:

$Grupa = Get-DistributionGroup -Identity “RoomImpersonationGroup”
New-ManagementScope “Room Mailboxes Impersonation” -RecipientRestrictionFilter “MemberOfGroup -eq ‘$($Grupa.DistinguishedName)'”

3. Creation of security group “ExchangeRoomImpersonation” in Active Directory

NEW-ADGroup –name “ExchangeRoomImpersonation” –groupscope Universal –path “OU=Offices,DC=Contoso,DC=local” -GroupCategory Security

4. Creation of new Exchange Assigment Role:

New-ManagementRoleAssignment -Name “Room Mailboxes Impersonation Assigment” -Role “ApplicationImpersonation” -CustomRecipientWriteScope “RoomImpersonationGroup” -SecurityGroup “ExchangeRoomImpersonation”


If you have all of that or you do not need to configure it as there are some service accounts you will use that are permissioned to impersonate globally – omit all these steps.

Some details about the script:

DeleteCanceledMeetings.ps1 - Cancelled meetings removal script.

.PARAMETER SearchStartDay
(OPTIONAL) Specifies START date from which sript should start searching of 
If not specified the today's date is used.

(MANDATORY) Specifies END date till which sript should start searching of 

(MANDATORY) Specifies mailboxes from which cancelled meetings should be removed.
As this is an array it accepts many mailboxes given after coma.

(OPTIONAL) Triggers HardDelete action on cancelled meetings if equal "True". 
Without it it generates a on screen report.

.\Get-MailboxPermissions.ps1 -SearchStartDay 10 -SearchEndDay 30 -Room Room1,Room2
Starts searching of meetings 10 days back and 30 days in front 
for 3 rooms Room1,Room2.
Returns a on screen report.

.\Get-MailboxPermissions.ps1 -SearchEndDay 90 -Room Room1,Room2,Room3 `
 -HardDetele True
Starts searching of meetings starting from current day and 90 days in front 
for 3 rooms Room1,Room2,Room3 and hard deletes them.
Reruns a CSV report and a log file.

You need to modify these lines in order to get logging working:


And you are ready to go! 🙂

Please remember that when runnig the script:


Script can be found on my Technet and GitHub

Have fun with IT!

VENI -Event psconf.eu | { $_.speech -VIDI $true; $global:State =+ VICI}

PowerShell Conference EU 2016


Being at the PowerShell conference in Hannover this Spring was a refreshing experience.

Met a lot of people that few days back I could only dream to meet. Starting from left picture with Bartek Bielawski, Bruce Payette and Jeffrey Snover, but I guess no one from them requires a real introduction 🙂

Talking about how great it was would take too much time (briefly: lots of inspirational speeches, great party in zoo with amazing food! :D, perfect opportunity to connect) so just encouraging those from you who are still hesitating to join PSConf next year! It is worth not only because of the technical factor but maybe even more because of people who are really open, friendly and full of incredible positive energy!


>> http://www.psconf.eu <<



Easy-Peasy zipping PowerShell script.



Many of us might be/have been asked a similar question:


And the answer is…


🙂 So, intentionally my colleague asked me to write that under PowerShell 2.0 – to use zipping assembly we need to change/create PawerShell.exe.config file, here is well described what needs to be done:


Otherwise we will get following error in the PS console:


Add-Type : Could not load file or assembly ‘Drive_Or_ShareName\Path\To\The\System.IO.Compression.FileSystem.dll’ or one of its dependencies. This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded.


So remedy for that is simply create/change PowerShell.exe.config, for me I needed to create it (was not there)  with content like below:

<?xml version=”1.0″?>
    <startup useLegacyV2RuntimeActivationPolicy=”true”>
        <supportedRuntime version=”v4.0.30319″/>
        <supportedRuntime version=”v2.0.50727″/>

Like even the script name implies – the script is very simply. It checks source directory (specified under Search_Folder parameter) for any files older than given period in days (Age_Of_Backuped_Data param). It moves all found files to the staging folder (Staging_Folder param), creates zip file in destination folder (Destination_Folder param), ensures that zip has been created and clears the staging area. All operations are being logged (LogFile param).

 Few words about the script itself:

EasyPeasyZippingScript.ps1 – Easy script zipping files.

Easy script for wrapping files into the archive older than given period, deleting them from the source folder and saving the .zip file into the destination folder.

Output is the .zip file with name that is set by current date/time.

.\EasyPeasyZippingScript.ps1 -Age_Of_Backuped_Data 90 -Search_Folder D:\Search_here -Destination_Folder D:\Archives_here -Staging_Folder D:\Staging_here -LogFile logfile.log

In the above example EasyPeasyZippingScript.ps1  script moves items from “D:\Search_here” with creation date older than 90 days to the  “D:\Staging_here” staging folder, zips that staging folder. Moves archive to “D:\Archives_here” and clears the “D:\Staging_here” folder. Also logs everything to the logfile.log file.

I’ve put the script on my Technet and GitHub 🙂

Have fun with IT!