Help with Exchange Mailbox Permissions Script

I’m trying to get a script working that will go through certain mailboxes and find the permissions for each folder and output it as a file (Not fussy about csv/txt really) and it seems to work fine for finding the data required and outputting it to the screen but when it outputs to a file, it always creates an empty file. I’ve fiddled with it a fair bit and can’t work out why. One thing I’ve noticed is that during the GetMailboxFolderPermission some mailboxes are producing the below error message. I’m not sure why, but it seems like the output to file may not be working because some mailboxes (a fairly insignificant amount) are returning this error. The script continues through the rest of the mailboxes and outputs to display easily though.

The operation couldn't be performed because 'EDD, Strategic Finance:\Inbox\EDD Finance\Staffing?Salaries' couldn't be f ound. + CategoryInfo : NotSpecified: (:) [Get-MailboxFolderPermission], ManagementObjectNotFoundException + FullyQualifiedErrorId : 9BC8DC6D,Microsoft.Exchange.Management.StoreTasks.GetMailboxFolderPermission

Here is my code for the script:

$Report = @()

$Mailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -OrganizationalUnit ‘domain/EDD/Resources’

ForEach ($Mailbox in $Mailboxes)
{
$SharedMailbox = $Mailbox.PrimarySmtpAddress.ToString()
$Permissions = Get-MailboxFolderPermission -Identity $Mailbox

  ForEach($f in (Get-MailboxFolderStatistics $mailbox | where{$_.foldertype -like "calendar" -or $_.foldertype -like "contacts" -or $_.foldertype -like "user created" -or $_.foldertype -like "deleteditems" -or $_.foldertype -like "sentitems" -or $_.foldertype -like "inbox" -or $_.foldertype -like "tasks" })) {
	$fname = $mailbox.DisplayName + ":" + $f.FolderPath.Replace("/","\");
	$permission = ""
	 ForEach($g in (Get-MailboxFolderPermission $fname | select User,AccessRights)){
		$permission | Add-Member -MemberType NoteProperty -Name "SharedMailbox" -value $fname
		$permission | Add-Member -MemberType NoteProperty -Name "User" -value $g.User
		$permission | Add-Member -MemberType NoteProperty -Name "AccessRights" -value $g.AccessRights
		
		#I also attempted using the method in the block below to output to file with no results either.
		$fname | Out-File -filePath .\TopLevelMBPermsNewPermsPiped.txt -append -encoding utf8
		$g.User | Out-File -filePath .\TopLevelMBPermsNewPermsPiped.txt -append -encoding utf8
		$g.AccessRights | Out-File -filePath .\TopLevelMBPermsNewPermsPiped.txt -append -encoding utf8
		"testing123" | Out-File -filePath .\TopLevelMBPermsNewPermsPiped.txt -append -encoding utf8
		
		
		$Report = $Report + $permission
		
		#these write-hosts all seem to work flawlessly
		write-host "fname: " $fname
		write-host "user: " $g.User
		write-host "AccessRights: " $g.AccessRights
		
		
	 }
  
  }
 }

$Report | Select-Object SharedMailbox,User,@{label=“AccessRights”;expression={$_.AccessRights}} | Export-Csv -Path “.\TopLevelMBPermsNew$(Get-Date -f ‘MMddyy’).csv” -NoTypeInformation

Any help you guys could give would be much appreciated. I’m fairly new to powershell.

Give this a shot. First make sure the Exchange Snap-in is loaded (the example below is loading the PowerShell snap-in for Exchange 2010), dot source the function, and then call the function. This is written to be compatible with PowerShell version 2. This is something I whipped up so it’s not fine tuned and does not contain error handling, but the logic should be a lot easier to follow than the script you were using and this function is a reusable tool.

Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.E2010

function Get-EmailFolderPermission {

    [CmdletBinding()]
    param (
        [string]$OrganizationalUnit = 'domain/EDD/Resources',
        [string]$MailboxType = 'SharedMailbox'
    )
    
    $Mailboxes = Get-Mailbox -RecipientTypeDetails $MailboxType -OrganizationalUnit $OrganizationalUnit

    foreach ($Mailbox in $Mailboxes){    
    
        $Folders = Get-MailboxFolderStatistics -Identity $mailbox |
                   Where-Object {$_.foldertype -eq 'Calendar' -or
                                 $_.foldertype -like 'Contacts' -or
                                 $_.foldertype -like 'User Created' -or
                                 $_.foldertype -like 'DeletedItems' -or
                                 $_.foldertype -like "SentItems" -or
                                 $_.foldertype -like "Inbox" -or
                                 $_.foldertype -like "Tasks" }

        foreach ($Folder in $Folders) {
        
            $FolderName = "$($Mailbox):$($Folder.FolderID)"
            $Permissions = Get-MailboxFolderPermission -Identity $FolderName

            foreach ($Permission in $Permissions){
             
                $Results = @{
                    Mailbox = "$($Mailbox.DisplayName)$($Folder.FolderPath)"
                    User = $Permission.User
                    AccessRights = $Permission.AccessRights
                }
                    
                New-Object PSObject -Property $Results

            }

        }

    }
}

You were receiving the error because special characters in the folders path show up as some sort of unicode character in the folderpath property value (like this: ). The easiest way to work around that problem is to use the folderid property instead. Some of the other problems you were experiencing were because of using the Write-Host cmdlet. Using the Write-Host cmdlet is almost always the wrong choice: http://www.jsnover.com/blog/2013/12/07/write-host-considered-harmful/.

When you call the function pipe it to whatever output type you want. Piping it to the Export-CSV cmdlet like you previously were is fine. I don’t hard code that stuff into functions because I like to keep them as flexible as possible.

µ

Although the previous version of this function that I posted earlier worked, all of the “-like” operators should have been replaced with the “-eq” operator. Looks like I forgot to finish changing them after copying and pasting from your script. There’s no reason to use the like operator unless you using doing some sort of wildcard matching (-like allows the use of *). Here’s an updated version of the function that’s been corrected:

Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.E2010

function Get-EmailFolderPermission {

    [CmdletBinding()]
    param (
        [string]$OrganizationalUnit = 'domain/EDD/Resources',
        [string]$MailboxType = 'SharedMailbox'
    )
    
    $Mailboxes = Get-Mailbox -RecipientTypeDetails $MailboxType -OrganizationalUnit $OrganizationalUnit

    foreach ($Mailbox in $Mailboxes){    
    
        $Folders = Get-MailboxFolderStatistics -Identity $mailbox |
                   Where-Object {$_.foldertype -eq 'Calendar' -or
                                 $_.foldertype -eq 'Contacts' -or
                                 $_.foldertype -eq 'User Created' -or
                                 $_.foldertype -eq 'DeletedItems' -or
                                 $_.foldertype -eq 'SentItems' -or
                                 $_.foldertype -eq 'Inbox' -or
                                 $_.foldertype -eq 'Tasks'}

        foreach ($Folder in $Folders) {
        
            $FolderName = "$($Mailbox):$($Folder.FolderID)"
            $Permissions = Get-MailboxFolderPermission -Identity $FolderName

            foreach ($Permission in $Permissions){
             
                $Results = @{
                    Mailbox = "$($Mailbox.DisplayName)$($Folder.FolderPath)"
                    User = $Permission.User
                    AccessRights = $Permission.AccessRights
                }
                    
                New-Object PSObject -Property $Results

            }

        }

    }
}

µ