Skip to content

Instantly share code, notes, and snippets.

@bill-long
Last active May 15, 2020 03:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bill-long/9441617 to your computer and use it in GitHub Desktop.
Save bill-long/9441617 to your computer and use it in GitHub Desktop.
Find Exchange Server public folder directory objects that are not linked to any existing folder. See also: https://gist.github.com/bill-long/e1de3ea480837e1a2742 and http://bill-long.com/2014/03/08/cleaning-up-microsoft-exchange-system-objects-part-2/
$gcRootDSE = [ADSI]"GC://RootDSE"
$gcRoot = [ADSI]("GC://" + $gcRootDSE.dnsHostName)
"Using " + $gcRoot.Path
# Find all the PF proxies
"Finding all public folder directory objects..."
$pfProxyFinder = new-object System.DirectoryServices.DirectorySearcher($gcRoot, "(objectClass=publicFolder)")
$pfProxyFinder.PageSize = 100
$allPfProxies = $pfProxyFinder.FindAll()
"Found " + $allPfProxies.Count.ToString() + " public folder directory objects."
# Make a dictionary with the GUID to DN mapping of each PF proxy
$pfProxyDictionary = new-object 'System.Collections.Generic.Dictionary[string, string]'
foreach ($pfProxy in $allPfProxies)
{
$guid = new-object Guid(,$pfProxy.Properties["objectguid"][0])
$pfProxyDictionary.Add($guid.ToString(), $pfProxy.Properties["distinguishedname"][0].ToString())
}
# Don't need the search results anymore, so give back that memory
$allPfProxies = $null
# Find all the mail-enabled PFs using Exchange Management Shell
"Finding all mail-enabled public folders..."
$mailEnabledPFs = Get-PublicFolder -recurse -resultsize unlimited | WHERE { $_.MailEnabled -eq $true }
"Found " + $mailEnabledPFs.Count.ToString() + " mail-enabled public folders."
# Is this Exchange 2013? If so, we can just look at MailRecipientGuid, which is faster
$pfobjectMembers = Get-PublicFolder | get-member
$hasRecipientGuid = ($pfobjectMembers | WHERE { $_.Name -eq "MailRecipientGuid" }).Length -gt 0
# Now figure out which directory objects aren't being used
"Determining which directory objects are not linked to a folder..."
foreach ($pf in $mailEnabledPFs)
{
"Checking folder: " + $pf.ParentPath + $pf.Name
$guidString = $null
if ($hasRecipientGuid)
{
$guidString = $pf.MailRecipientGuid.ToString()
}
else
{
$guidString = ($pf | Get-MailPublicFolder).Guid.ToString()
}
$mailPF = ($pf | Get-MailPublicFolder)
if ($pfProxyDictionary.ContainsKey($mailPF.Guid.ToString()))
{
$pfProxyDictionary.Remove($mailPF.Guid.ToString()) | Out-Null
}
}
# The only stuff left in the dictionary at this point is unlinked directory objects
""
"There are " + $pfProxyDictionary.Count.ToString() + " public folder directory objects not linked to any folder. They are:"
foreach ($value in $pfProxyDictionary.Values)
{
$value
}
"Done!"
@tinojr
Copy link

tinojr commented May 14, 2020

In troubleshooting this issue i came across your scripts and blogs. I see a few issues with this script.

  • $guidString is never used, instead you run get-mailpublicfolder twice, so i'm confused why lines 37-45 are needed.
  • line 60 you just display the value. wouldn't it be better to export both keys and values to csv, with headers (objectguid and distinguishedname)?

@bill-long
Copy link
Author

No idea about $guidString. I was probably doing something else with it in a different version of the script. Feel free to delete those lines.

You could certainly export to CSV, but there's no need to. Typically you are just going to delete these, and you don't need both the GUID and the DN for that. One or the other will do.

@tinojr
Copy link

tinojr commented May 15, 2020

Ah ok, thanks Bill. I initially ran this script to see what was affected, then i used your other script that resolves issues using the exfolders output and it resolved about 75% of issues found from this script. I emailed a couple of the unresolved ones and received ndr's, seems those can be deleted. I may have questions for your other scripts, but will comment on their github page. thanks for the reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment