<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.technet.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Bill Long's Exchange Blog</title><link>http://blogs.technet.com/b/bill_long/</link><description>Exchange Server stuff, focusing on Public Folders, PFDAVAdmin, ExFolders, and Powershell scripting.</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>New Version Of ExFolders Adds A Clear Permissions Bulk Operation</title><link>http://blogs.technet.com/b/bill_long/archive/2012/06/04/new-version-of-exfolders-adds-a-clear-permissions-bulk-operation.aspx</link><pubDate>Mon, 04 Jun 2012 20:29:58 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3501985</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3501985</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2012/06/04/new-version-of-exfolders-adds-a-clear-permissions-bulk-operation.aspx#comments</comments><description>&lt;p&gt;In October of last year, I updated ExFolders with a new &lt;strong&gt;Clear Permissions&lt;/strong&gt; option in order to fix folders with non-canonical ACLs. I described that update in an old blog post you can find here: &lt;a title="http://blogs.technet.com/b/bill_long/archive/2012/05/03/3460823.aspx" href="http://blogs.technet.com/b/bill_long/archive/2012/05/03/3460823.aspx"&gt;http://blogs.technet.com/b/bill_long/archive/2012/05/03/3460823.aspx&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Since then, one of the most requested features has been a way to run this on a whole subtree of folders. Unfortunately, it appears that customers are seeing ACL problems more often than I expected. So today, I’ve released a new build of ExFolders that includes a way to do this. In the latest version, when you go to Tools-&amp;gt;Custom Bulk Operation and you hit Add, you’ll find an option to &lt;strong&gt;Clear Folder Permissions&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;One of the reasons I didn’t add this feature initially is that it is such a destructive operation. Clearing the permissions on a whole tree of folders is not something to do casually without considering the consequences. In a mailbox, you are taking away permissions on folders that users have purposely shared out. In public folders, you are literally removing all access rights for everyone, making it impossible for your clients to access the public folders.&lt;/p&gt;  &lt;p&gt;However, when you add the &lt;strong&gt;Clear Folder Permissions&lt;/strong&gt; bulk operation, you’ll notice it has a checkbox, which is selected by default, called &lt;strong&gt;Restore previous permissions after clearing&lt;/strong&gt;. When this is selected, ExFolders will clear the permissions and save those changes, and then it will attempt to set the permissions that were present before and save the changes again. This should allow it to fix non-canonical ACLs without requiring the administrator to set all the permissions back the way they were before.&lt;/p&gt;  &lt;p&gt;Of course, as with any bulk permissions change, it’s a good idea to take a permissions export first just in case something goes wrong. However, I expect this option will make importing after a mass Clear Permissions unnecessary in most cases. And because this option is selected by default, I’m hoping that if someone accidentally runs this against a set of folders, the impact will be minimal.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3501985" width="1" height="1"&gt;</description></item><item><title>How To Access System Folders From EWS Managed API</title><link>http://blogs.technet.com/b/bill_long/archive/2011/11/30/how-to-access-system-folders-from-ews-managed-api.aspx</link><pubDate>Wed, 30 Nov 2011 15:37:40 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3468121</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3468121</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/11/30/how-to-access-system-folders-from-ews-managed-api.aspx#comments</comments><description>&lt;p&gt;The EWS Managed API provides a simple way to get to the Public Folders – you simply bind to the Microsoft.Exchange.WebServices.Data.WellKnownFolderName.PublicFoldersRoot, like so:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$pfRootName = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot     &lt;br /&gt;$pfRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $pfRootName)&lt;/font&gt;    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;But what if you want to access the Free Busy folder, or the Offline Address Book folders? How do you get to the System Folders? The WellKnownFolderName enumeration doesn’t have a value for the System Folders Root.&lt;/p&gt;  &lt;p&gt;Fortunately, there’s a relatively simple trick you can use to get there. EWS gives you the option of binding to a folder by ID. The ID of the Public Folders Root will always end with the number 1, and the ID of the System Folders Root will always end with the number 2. So you can simply bind to the Public Folders Root, get the ID, swap out the number 1 with a number 2, and voila! You have the ID of the System Folders root. Here’s how you do it:&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$pfRootName = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot     &lt;br /&gt;$pfRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $pfRootName)      &lt;br /&gt;$pfRootIdString = $pfRoot.Id.ToString()      &lt;br /&gt;$pfRootIdBytes = [System.Convert]::FromBase64String($pfRootIdString)      &lt;br /&gt;$pfRootIdBytes[$pfRootIdBytes.Length - 4] = [byte]0x02      &lt;br /&gt;$systemRootIdBase64String = [System.Convert]::ToBase64String($pfRootIdBytes)      &lt;br /&gt;$systemRootId = new-object Microsoft.Exchange.WebServices.Data.FolderId($systemRootIdBase64String)      &lt;br /&gt;$systemRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service, $systemRootId)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#000000"&gt;At that point you have the System Folders root in $systemRoot, and you can proceed from there. Hopefully this saves some of you some time. It was interesting trying to figure out how to do this!&lt;/font&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3468121" width="1" height="1"&gt;</description></item><item><title>Removing Unresolved SIDs in Exchange 2010</title><link>http://blogs.technet.com/b/bill_long/archive/2011/10/23/removing-unresolved-sids-in-exchange-2010.aspx</link><pubDate>Sun, 23 Oct 2011 08:20:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3460826</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3460826</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/10/23/removing-unresolved-sids-in-exchange-2010.aspx#comments</comments><description>&lt;p&gt;In this post, I'm going to describe how to remove unresolved SIDs from public folders in Exchange 2010. But first, let&amp;rsquo;s talk about what they are and why we care about them.&lt;/p&gt;
&lt;h2&gt;What are unresolved SIDs?&lt;/h2&gt;
&lt;p&gt;When you view the permissions on a file in Windows or an object in Active Directory, you get a nice friendly list of names, each one with its associated access rights displayed. However, the security descriptor does not actually contain the names of the users &amp;ndash; it only contains their SIDs. When an application such as Explorer or ADUC displays the permissions, it attempts to resolve each SID to a name, so when you look at it you can make some sense of what you&amp;rsquo;re seeing.&lt;/p&gt;
&lt;p&gt;An unresolved SID is a SID that no longer resolves, usually because the user has been deleted. If you look at an object in ADUC, it looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-82-55-metablogapi/3225.sec1_5F00_52F60DE9.jpg"&gt;&lt;img style="display: inline; background-image: none;" title="sec1" border="0" alt="sec1" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-82-55-metablogapi/5282.sec1_5F00_thumb_5F00_3921D7BA.jpg" width="416" height="245" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In Exchange, folders have security descriptors that are very similar to the ones in Windows, except that things are ordered differently. But you still have SIDs and rights, and when a SID doesn&amp;rsquo;t resolve anymore, you&amp;rsquo;ll see that in Outlook:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-82-55-metablogapi/0083.sec2_5F00_117B5B90.jpg"&gt;&lt;img style="display: inline; background-image: none;" title="sec2" border="0" alt="sec2" src="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-82-55-metablogapi/8424.sec2_5F00_thumb_5F00_3E90485E.jpg" width="359" height="179" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Why do we care about them?&lt;/h2&gt;
&lt;p&gt;Unresolved SIDs don&amp;rsquo;t cause a problem; they just look ugly. Some customers want to remove them for that reason alone, and some customers have other reasons. A lot of customers used PFDAVAdmin for this, but there was a specific reason PFDAVAdmin removed these.&lt;/p&gt;
&lt;p&gt;Back in Exchange 2000 and Exchange 2003, it was possible to expose the Information Store database as a drive in Windows. This was the infamous M: drive. It became infamous because applications that were not Exchange-aware would access folders through the M: drive and mess up the permissions. Above, I briefly mentioned that things are ordered differently in an Exchange ACL than a Windows ACL. Applications that looked at the folders in M: and thought they were plain old Windows folders would reorder the stuff in the security descriptor to fit the Windows format. This meant it no longer matched the Exchange canonical format, and the permissions wouldn&amp;rsquo;t work as expected.&lt;/p&gt;
&lt;p&gt;After an application had run through the M: drive and made all the ACLs non-canonical, it was a huge pain to go through and manually correct them. This was one of the main reasons I wrote the PFDAVAdmin tool. PFDAVAdmin provided an easy way to put all the ACLs back in canonical order.&lt;/p&gt;
&lt;p&gt;One thing about Exchange canonical order is that the SIDs need to go in a particular order based on the object type. Users need to be at the top of the ACL, followed by groups. If you&amp;rsquo;re trying to reorder the ACL to make it canonical again, and you run into an unresolved SID, this presents a problem. Since you can&amp;rsquo;t resolve the SID, you don&amp;rsquo;t know what type of object it is, so where should it go?&lt;/p&gt;
&lt;p&gt;There are a few ways you could approach this problem. For instance, you could just pretend it&amp;rsquo;s a user SID. If the object has been deleted, then the SID will never again resolve, so it won&amp;rsquo;t matter. If the SID is only unresolvable because of a temporary issue with a DC or something, then this could result in the ACL becoming non-canonical once the SID resolves again.&lt;/p&gt;
&lt;p&gt;However, the approach I took with PFDAVAdmin was to have it remove the unresolved SIDs. I couldn&amp;rsquo;t be sure what they were and why they were unresolvable, and the whole point was to force the ACL into a canonical state, so this seemed like a sensible approach.&lt;/p&gt;
&lt;h2&gt;Why doesn&amp;rsquo;t ExFolders remove them?&lt;/h2&gt;
&lt;p&gt;When I rewrote the guts of PFDAVAdmin for Exchange 2010, I renamed it ExFolders. While the GUI looks almost identical, the code underneath is not the same and required a lot of rewriting. When it came time to look at the &amp;ldquo;Fix Folder DACL&amp;rdquo; code and decide whether to move it into ExFolders, I just didn&amp;rsquo;t see any need for it. The widespread non-canonical ACL issues from the Exchange 2000/2003 days were gone, so I left this functionality out of ExFolders entirely. Unresolved SID removal was a side-effect of fixing the DACL, so it likewise fell by the wayside.&lt;/p&gt;
&lt;h2&gt;How can I remove them now?&lt;/h2&gt;
&lt;p&gt;OK, so you want to remove them from your public folders in Exchange 2010, but there&amp;rsquo;s no tool to do that anymore. Fortunately, it&amp;rsquo;s easy to remove them with a simple script. I&amp;rsquo;ve included one below. This script will be far slower than PFDAVAdmin was, but it will get the job done.&lt;/p&gt;
&lt;p&gt;If you run it with the following syntax, it will only report the unresolved SIDs:&lt;/p&gt;
&lt;p&gt;.\Check-UnresolvedSIDs.ps1 -Server MyPFServer&lt;/p&gt;
&lt;p&gt;If you want it to actually remove them, you must add the &amp;ndash;Remove parameter:&lt;/p&gt;
&lt;p&gt;.\Check-UnresolvedSIDs.ps1 -Server MyPFServer -Remove $true&lt;/p&gt;
&lt;p&gt;The output will look something like this:&lt;/p&gt;
&lt;p&gt;\Folder1: Checking folder &lt;br /&gt;\Folder2: Checking folder &lt;br /&gt;\Folder2 has unresolved SIDs: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT User:S-1-5-21-1016452943-3003584382-490080582-2161 &lt;br /&gt;\Folder3: Checking folder &lt;br /&gt;\MyNewFolder: Checking folder &lt;br /&gt;\SomeOtherFolder: Checking folder &lt;br /&gt;\SomeOtherFolder has unresolved SIDs: &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT User:S-1-5-21-1016452943-3003584382-490080582-1136 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; NT User:S-1-5-21-1016452943-3003584382-490080582-1135&lt;/p&gt;
&lt;p&gt;If you add the &amp;ndash;Remove parameter, it will also tell you that it&amp;rsquo;s removing them.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the script. Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;# Check-UnresolvedSIDs.ps1 &lt;br /&gt;# &lt;br /&gt;# This script will remove all unresolved SIDs from public folder permissions. &lt;br /&gt;# This will take quite some time to run against a large hierarchy.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;param([string]$Server, [bool]$Remove)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;if ([System.String]::IsNullOrEmpty($Server)) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "You must specify a server." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;function CheckUnresolvedForFolder($folder) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ($folder.Identity.ToString() + ": Checking folder") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $unresolved = Get-PublicFolderClientPermission -Identity $folder -Server $Server| WHERE { $_.User -like "NT User:S-*" } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($unresolved -ne $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ($folder.Identity.ToString() + " has unresolved SIDs:") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $unresolved) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; " + $item.User.ToString()) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($Remove) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Removing the unresolved SIDs...") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $unresolved) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item | Remove-PublicFolderClientPermission -Identity $folder -Server $Server -Confirm:$false &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Unresolved SIDs were removed.") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;function DoFolderRecursive($folder) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CheckUnresolvedForFolder($folder) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $subfolders = Get-PublicFolder -Identity $folder -GetChildren &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($subfolders -ne $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($subfolder in $subfolders) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolderRecursive($subfolder) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;$ipmSubtree = Get-PublicFolder "\" -Server $Server &lt;br /&gt;DoFolderRecursive($ipmSubtree) &lt;br /&gt;$nonIpmSubtree = Get-PublicFolder "\NON_IPM_SUBTREE" -Server $Server &lt;br /&gt;DoFolderRecursive($nonIpmSubtree)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;"Done!"&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3460826" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/ExFolders/">ExFolders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Information+Store/">Information Store</category></item><item><title>New Version of ExFolders Fixes Non-Canonical ACLs</title><link>http://blogs.technet.com/b/bill_long/archive/2011/10/23/new-version-of-exfolders-fixes-non-canonical-acls.aspx</link><pubDate>Sun, 23 Oct 2011 07:07:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3460823</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3460823</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/10/23/new-version-of-exfolders-fixes-non-canonical-acls.aspx#comments</comments><description>&lt;p&gt;When I wrote ExFolders, I thought the non-canonical Exchange ACL problems were permanently behind us in Exchange 2010. For this reason, ExFolders did not include any functionality to deal with non-canonical ACLs. It turns out I was overly optimistic.&lt;/p&gt;
&lt;p&gt;In the last few weeks I&amp;rsquo;ve seen a couple of cases where customers ended up with non-canonical ACLs on public folders in Exchange 2010. They were seeing events like this:&lt;/p&gt;
&lt;p&gt;Log Name: Application &lt;br /&gt;Source: MSExchangeIS &lt;br /&gt;Event ID: 9775 &lt;br /&gt;Task Category: General &lt;br /&gt;Level: Warning &lt;br /&gt;Description: &lt;br /&gt;The mailbox '' contains a folder 'My Public Folder' with a security descriptor that violates the canonical format.&lt;/p&gt;
&lt;p&gt;Trying to modify the permissions with Add-PublicFolderClientPermission would result in this error:&lt;/p&gt;
&lt;p&gt;MapiExceptionNonCanonicalACL: Unable to modify table. (hr=0x80004005, ec=2409)&lt;/p&gt;
&lt;p&gt;Each affected environment only had one folder in this state, so it does not appear to be a widespread problem, such as when something scanned the M: drive back in the Exchange 2000 days.&lt;/p&gt;
&lt;p&gt;Even so, customers need a way to fix these problems. Since PFDAVAdmin fixed this for older versions of Exchange, it made sense to include this functionality in ExFolders for Exchange 2010.&lt;/p&gt;
&lt;p&gt;Note, however, that what I&amp;rsquo;ve added to ExFolders is very different from the &amp;ldquo;Fix Folder DACLs&amp;rdquo; option in PFDAVAdmin. &amp;ldquo;Fix Folder DACLs&amp;rdquo; would run through your whole folder hierarchy looking for all kinds of problems and adjusting the DACL portion of the ACL.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;ve added in the October 20th, 2011 release of &lt;a href="http://gallery.technet.microsoft.com/Exchange-2010-SP1-ExFolders-e6bfd405"&gt;ExFolders for 2010 Sp1&lt;/a&gt; is something much more limited in scope. When you right-click on a folder, you&amp;rsquo;ll see a &amp;ldquo;Clear Permissions&amp;rdquo; option. The previous build actually had this option as well, but it would not work on non-canonical ACLs. In this latest version, the &amp;ldquo;Clear Permissions&amp;rdquo; option accesses the raw security descriptor (similar to what PFDAVAdmin used to do) so it can clear it even when it&amp;rsquo;s non-canonical. You can use this to set one specific folder back into a good state and then manually set the permissions to whatever they should be.&lt;/p&gt;
&lt;p&gt;This will be good enough to address these one-off non-canonical ACLs. I don&amp;rsquo;t expect we&amp;rsquo;ll be seeing widespread problems with this, but I&amp;rsquo;ll be keeping an eye on it. Hopefully there will be no need to introduce a bulk folder ACL fix again.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3460823" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/ExFolders/">ExFolders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Information+Store/">Information Store</category></item><item><title>Investigating complex LDAP filters in Exchange</title><link>http://blogs.technet.com/b/bill_long/archive/2011/10/05/investigating-complex-ldap-filters-in-exchange.aspx</link><pubDate>Thu, 06 Oct 2011 04:56:29 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3457554</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3457554</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/10/05/investigating-complex-ldap-filters-in-exchange.aspx#comments</comments><description>&lt;p&gt;Customers migrating from Exchange 2003 to 2007 or 2010 often use my &lt;a href="http://gallery.technet.microsoft.com/scriptcenter/7c04b866-f83d-4b34-98ec-f944811dd48d"&gt;ConvertFrom-LdapFilter script&lt;/a&gt; to do very literal conversions from their old LDAP filters to the new OPATH filter syntax. In most cases, that works, but sometimes you’ll run across a filter like this:&lt;/p&gt;  &lt;p&gt;(&amp;amp;(&amp;amp;(&amp;amp;(|(&amp;amp;(objectCategory=person)(objectSid=*)(!samAccountType:1.2.840.113556.1.4.804:=3))(&amp;amp;(objectCategory=person)(!objectSid=*))(&amp;amp;(objectCategory=group)(groupType:1.2.840.113556.1.4.804:=14))))(objectCategory=user)(memberOf=CN=SomeGroup,CN=Users,DC=contoso,DC=com)))&lt;/p&gt;  &lt;p&gt;My script will refuse to process this filter because of the bitwise filters on samAccountType and groupType. So what to do?&lt;/p&gt;  &lt;p&gt;The first thing you should do is step back and say, “Who do I want this filter to match? What was the original intent of this filter?” If you’re not sure, you may be able to get an idea by breaking down the filter logic like this:&lt;/p&gt;  &lt;p&gt;&lt;font face="Lucida Console"&gt;(&amp;amp;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (|      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (objectCategory=person)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (objectSid=*)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (!samAccountType:1.2.840.113556.1.4.804:=3)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (objectCategory=person)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (!objectSid=*)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;amp;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (objectCategory=group)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (groupType:1.2.840.113556.1.4.804:=14)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (objectCategory=user)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (memberOf=CN=SomeGroup,CN=Users,DC=contoso,DC=com)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; )      &lt;br /&gt;)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Now that we can see how all the matching conditions relate to each other, we have a couple of questions to answer before we can totally understand the filter. We need to know what these two conditions mean:&lt;/p&gt;  &lt;p&gt;(!samAccountType:1.2.840.113556.1.4.804:=3)   &lt;br /&gt;(groupType:1.2.840.113556.1.4.804:=14)&lt;/p&gt;  &lt;p&gt;Searching the KB, we can find that 1.2.840.113556.1.4.804 is the bitwise OR match condition, described in &lt;a href="http://support.microsoft.com/kb/269181"&gt;KB 269181&lt;/a&gt;. This means that if any one of the specified flags is found, it’s a match.&lt;/p&gt;  &lt;p&gt;Looking at the samAccountType filter, we have a value of 3 in decimal. Converting this to binary shows that we have the two rightmost bits set:&lt;/p&gt;  &lt;p&gt;00000011&lt;/p&gt;  &lt;p&gt;So this bitwise OR filter matches on the 0x1 bit or the 0x2 bit. But the condition starts with a NOT (that’s what the ! means), so we’ll only match objects where neither of those bits are set. Now we need to look up what all these bits mean for the samAccountType filter. We can find those definitions here: &lt;a title="http://msdn.microsoft.com/en-us/library/cc228417(v=PROT.13).aspx" href="http://msdn.microsoft.com/en-us/library/cc228417(v=PROT.13).aspx"&gt;http://msdn.microsoft.com/en-us/library/cc228417(v=PROT.13).aspx&lt;/a&gt;. A quick look at the list reveals that if we’re not matching anything with 0x1 or 0x2, that leaves 3 values that we will match on:&lt;/p&gt;  &lt;p&gt;SAM_GROUP_OBJECT   &lt;br /&gt;SAM_ALIAS_OBJECT    &lt;br /&gt;SAM_USER_OBJECT&lt;/p&gt;  &lt;p&gt;So basically, the whole purpose of that condition is to say, “only match on groups, contacts, or users”.&lt;/p&gt;  &lt;p&gt;Now that we have that part figured out, we need to find out what this groupType condition means. Again, we have a bitwise OR. This time the flags are 14 in decimal, which gives us the following bits:&lt;/p&gt;  &lt;p&gt;00001110&lt;/p&gt;  &lt;p&gt;The 0x2, 0x4, and 0x8 bit are set. We can find the definitions of the groupType values here: &lt;a title="http://msdn.microsoft.com/en-us/library/cc228506(v=PROT.13).aspx" href="http://msdn.microsoft.com/en-us/library/cc228506(v=PROT.13).aspx"&gt;http://msdn.microsoft.com/en-us/library/cc228506(v=PROT.13).aspx&lt;/a&gt;. This tells us that this condition matches groups that are either Universal, Resource, or Account groups. I have no idea what these flags mean (aside from Universal), but I don’t have a single group in my lab that isn���t one of these types.&lt;/p&gt;  &lt;p&gt;Now that we understand the whole filter, we can explain the logic like this:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;The object must match any one of the following conditions:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;It has a SID and is either a user, group, or contact&lt;/li&gt;      &lt;li&gt;It does not have a SID&lt;/li&gt;      &lt;li&gt;It is a group that has either the Universal, Resource, or Account flag set&lt;/li&gt;   &lt;/ul&gt;    &lt;li&gt;The object must also match both of the following conditions:&lt;/li&gt;    &lt;ul&gt;     &lt;li&gt;objectCategory is user&lt;/li&gt;      &lt;li&gt;It’s a member of the specified group&lt;/li&gt;   &lt;/ul&gt; &lt;/ul&gt;  &lt;p&gt;At this point, it’s pretty clear that the whole idea of this filter is just to match members of a group. The filter is extremely overcomplicated, and the bitwise filters that we had to spend so much time investigating are largely pointless. This filter was almost certainly built using Exchange System Manager in Exchange 2000 or 2003. That management tool was infamous for its overly-complex filters, and it’s unlikely that a human would purposely make a filter this obtuse. If I was writing my own LDAP filter to accomplish this in Exchange 2003, I would simply use:&lt;/p&gt;  &lt;p&gt;(&amp;amp;(mailnickname=*)(memberOf=CN=SomeGroup,CN=Users,DC=contoso,DC=com))&lt;/p&gt;  &lt;p&gt;But now that we know what the filter is supposed to do, we can just replace it directly with a much more elegant OPATH filter and call it a day:&lt;/p&gt;  &lt;p&gt;memberOfGroup -eq CN=SomeGroup,CN=Users,DC=contoso,DC=com&lt;/p&gt;  &lt;p&gt;Setting the RecipientFilter on the policy to that value will essentially accomplish the same thing as that huge, messy LDAP filter, and it’s a whole lot easier to read and quickly ascertain what it does.&lt;/p&gt;  &lt;p&gt;For more on translating LDAP filters to OPATH, see this article: &lt;a title="http://technet.microsoft.com/en-us/library/cc164375.aspx" href="http://technet.microsoft.com/en-us/library/cc164375.aspx"&gt;http://technet.microsoft.com/en-us/library/cc164375.aspx&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3457554" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/OPATH/">OPATH</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/LDAP/">LDAP</category></item><item><title>Identifying Unresolved LegacyExchangeDNs via EWS and Powershell</title><link>http://blogs.technet.com/b/bill_long/archive/2011/09/16/identifying-unresolved-legacyexchangedns-via-ews-and-powershell.aspx</link><pubDate>Fri, 16 Sep 2011 17:42:47 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3453786</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3453786</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/09/16/identifying-unresolved-legacyexchangedns-via-ews-and-powershell.aspx#comments</comments><description>&lt;p&gt;I recently worked with a customer who had inadvertently deleted all their user accounts (and thus their Exchange mailboxes), and with no backup available, they had to recreate them. Talk about a nightmare! After they did so, they were able to get their email back, but they discovered that replying to email messages from before the problem resulted in a non-delivery report.&lt;/p&gt;  &lt;p&gt;This is because of a fairly well-documented behavior. Email addresses in the From, To, and other fields are resolved to legacyExchangeDNs and stored in the message. When you reply to a message, we expect to be able to resolve that legacyExchangeDN. If we can’t, it causes an NDR. In various migration scenarios where the legacyExchangeDN of a user changes, we populate the user’s proxyAddresses with an X500 address that contains the old legacyExchangeDN. This allows the old value to resolve, preserving the ability to reply to old messages.&lt;/p&gt;  &lt;p&gt;In this case, when the users were recreated, they got new legacyExchangeDNs, which broke the ability to reply to old email. We needed to somehow get the old leg DNs back, but we didn’t know what they all were, and having to manually poke around in mailboxes looking for them was not realistic.&lt;/p&gt;  &lt;p&gt;To solve this problem, I wrote a script to scan a mailbox and output any unresolved legacyExchangeDNs. There are a few interesting parts to this script, so I figured I would post it in case others find it useful (and so I can easily refer back to it in the future).&lt;/p&gt;  &lt;p&gt;The first interesting part is the way it gets the user’s password. &lt;strike&gt;I needed to get the user’s password without displaying it to the console. Unfortunately, EWS won’t seem to accept a SecureString, so I couldn’t use Get-Credential or similar approaches to ask the user for his password. To solve this, I had to adapt a routine I found in a couple of other blog posts so it would work in Powershell. You’ll find that near the top of the script.&lt;/strike&gt; DJ found a much simpler way to accomplish this, so the 15ish lines of code that I had have been replaced with a single line that gets the password without showing it. Thanks DJ!&lt;/p&gt;  &lt;p&gt;The second interesting part is that it demonstrates how to open another user’s mailbox folders. The script will ask you for one email address for authentication purposes, and then it will ask you for another user’s SMTP address, which is optional. If you enter the other user, the script will scan that user’s folders instead of the authenticating user’s folders.&lt;/p&gt;  &lt;p&gt;The third interesting part is that EWS will not return the full recipient information as part of a FindItems() call – you only get back some basic information, which wasn’t enough to tell me if there was an unresolved legacyExchangeDN. To solve this, I had to actually bind to each individual email message. I did this using a specific property set of only a few properties that I was interested in, but it still made the script quite slow.&lt;/p&gt;  &lt;p&gt;I wanted this script to work against both on-premises and Office 365 or BPOS environments. &lt;strike&gt;Unfortunately, Autodiscover to a cloud environment results in a redirect that can’t be handled in Powershell (or if it can, I haven’t figured out how). You have to create a callback to validate the redirection URL, and while I found that I could cast a script block to a delegate, I couldn’t get the script block to handle this properly. So if you’re connecting to the cloud, you have to manually specify your EWS URL.&lt;/strike&gt; DJ also showed me how to make Autodiscover to the cloud work in Powershell, and I’ve updated the script below. Thanks again DJ! This script is really much better now thanks to him.&lt;/p&gt;  &lt;p&gt;The script will scan the Inbox and any subfolders, as well as Sent Items and Deleted Items, looking for unresolved leg DNs. Any it finds will be written out to a CSV file. It caches what it finds so that duplicates are not written to the CSV.&lt;/p&gt;  &lt;p&gt;Anyway, here’s the script!&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Scan-MailboxForLegDNs.ps1&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;Import-Module -Name &amp;quot;C:\Program Files\Microsoft\Exchange\Web Services\1.1\Microsoft.Exchange.WebServices.dll&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$hostName = Read-Host &amp;quot;Hostname for EWS endpoint (leave blank to attempt Autodiscover)&amp;quot;     &lt;br /&gt;$outputFile = Read-Host &amp;quot;Output file name&amp;quot;      &lt;br /&gt;$emailAddress = Read-Host &amp;quot;Email address for authentication&amp;quot;      &lt;br /&gt;$password = $host.ui.PromptForCredential(&amp;quot;Credentials&amp;quot;, &amp;quot;Please enter your password to authenticate to EWS.&amp;quot;, $emailAddress, &amp;quot;&amp;quot;).GetNetworkCredential().Password&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# If specified, we'll try to open this mailbox instead of the one that authenticated     &lt;br /&gt;$otherMailboxSmtp = Read-Host &amp;quot;SMTP address of other mailbox (optional)&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Initialize the output file     &lt;br /&gt;Set-Content -Path $outputFile -Value &amp;quot;Display Name,LegacyExchangeDN&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Make variables for the properties to make them easier to type,     &lt;br /&gt;# then stick them into a PropertySet      &lt;br /&gt;$toRecipientsProperty = [Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::ToRecipients      &lt;br /&gt;$ccRecipientsProperty = [Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::CcRecipients      &lt;br /&gt;$fromProperty = [Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::From      &lt;br /&gt;$subjectProperty = [Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::Subject      &lt;br /&gt;$arrayOfPropertiesToLoad = @($toRecipientsProperty, $ccRecipientsProperty, $fromProperty, $subjectProperty)      &lt;br /&gt;$propertySet = new-object Microsoft.Exchange.WebServices.Data.PropertySet($arrayOfPropertiesToLoad)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Here's where we'll store the ones we found to avoid duplicates in the CSV     &lt;br /&gt;$legDNsFound = new-object 'System.Collections.Generic.List[string]'&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# This function checks an individual EmailAddress to see if it's an unresolved legacyExchangeDN     &lt;br /&gt;function CheckAddress($emailAddress)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ($emailAddress.RoutingType -eq &amp;quot;EX&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Legacy DN: &amp;quot; + $emailAddress.Address)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Display Name: &amp;quot; + $emailAddress.Name)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (!($legDNsFound.Contains($emailAddress.Address.ToLower())))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $legDNsFound.Add($emailAddress.Address.ToLower())      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Add-Content -Path $outputFile -Value ($emailAddress.Name.Replace(&amp;quot;,&amp;quot;, &amp;quot;.&amp;quot;) + &amp;quot;,&amp;quot; + $emailAddress.Address)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# This function loops through the items in a folder     &lt;br /&gt;function ProcessFolder($folder)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Scanning folder: &amp;quot; + $folder.DisplayName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $itemView = new-object Microsoft.Exchange.WebServices.Data.ItemView(100)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; while (($folderItems = $folder.FindItems($itemView)).Items.Count -gt 0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach ($item in $folderItems)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($item.GetType() -eq [Microsoft.Exchange.WebServices.Data.EmailMessage])      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $message = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($exchService, $item.Id, $propertySet)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160; &amp;quot; + $message.Subject)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach ($emailAddress in $message.ToRecipients)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CheckAddress($emailAddress)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach ($emailAddress in $message.CcRecipients)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CheckAddress($emailAddress)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; CheckAddress($message.From)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $offset += $folderItems.Items.Count      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $itemView = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# This function recursively processes subfolders     &lt;br /&gt;function DoSubfoldersRecursive($folder)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ($folder.ChildFolderCount -gt 0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $folderView = new-object Microsoft.Exchange.WebServices.Data.FolderView($folder.ChildFolderCount)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $subfolders = $folder.FindFolders($folderView)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach ($subfolder in $subfolders)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ProcessFolder($subfolder)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoSubfoldersRecursive($subfolder)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Here's where we try to connect     &lt;br /&gt;# If a URL was specified we'll use that; otherwise we'll use Autodiscover      &lt;br /&gt;$exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)      &lt;br /&gt;$exchService.Credentials = new-object System.Net.NetworkCredential($emailAddress, $password, &amp;quot;&amp;quot;)      &lt;br /&gt;if ($hostName -ne &amp;quot;&amp;quot;)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Using EWS URL:&amp;quot; + &amp;quot;&lt;/font&gt;&lt;a href="https://&amp;quot;"&gt;&lt;font color="#0000ff"&gt;https://&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff"&gt; + $hostName + &amp;quot;/EWS/Exchange.asmx&amp;quot;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $exchService.Url = new-object System.Uri((&amp;quot;&lt;/font&gt;&lt;a href="https://&amp;quot;"&gt;&lt;font color="#0000ff"&gt;https://&amp;quot;&lt;/font&gt;&lt;/a&gt;&lt;font color="#0000ff"&gt; + $hostName + &amp;quot;/EWS/Exchange.asmx&amp;quot;))     &lt;br /&gt;}      &lt;br /&gt;elseif ($otherMailboxSmtp -ne &amp;quot;&amp;quot;)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Autodiscovering &amp;quot; + $otherMailboxSmtp + &amp;quot;...&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $exchServce.AutoDiscoverUrl($otherMailboxSmtp, {$true})      &lt;br /&gt;}      &lt;br /&gt;else      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Autodiscovering &amp;quot; + $emailAddress + &amp;quot;...&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $exchService.AutodiscoverUrl($emailAddress, {$true})      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;if ($exchService.Url -eq $null)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$mailbox = new-object Microsoft.Exchange.WebServices.Data.Mailbox($emailAddress)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# If some other mailbox was specified, open that one instead.     &lt;br /&gt;if ($otherMailboxSmtp -ne &amp;quot;&amp;quot;)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $mailbox = new-object Microsoft.Exchange.WebServices.Data.Mailbox($otherMailboxSmtp)      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Create some variables for the folder names so they're easier to type     &lt;br /&gt;$inboxFolder = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox      &lt;br /&gt;$sentItemsFolder = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::SentItems      &lt;br /&gt;$deletedItemsFolder = [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::DeletedItems&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# We'll bind to each folder by instantiating a FolderId that points to the mailbox we want.&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# First, scan the inbox     &lt;br /&gt;$inboxId = new-object Microsoft.Exchange.WebServices.Data.FolderId($inboxFolder, $mailbox)      &lt;br /&gt;$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, $inboxId)      &lt;br /&gt;ProcessFolder($inbox)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;# Now any subfolders      &lt;br /&gt;DoSubfoldersRecursive($inbox)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;# Now Sent Items      &lt;br /&gt;$sentItemsId = new-object Microsoft.Exchange.WebServices.Data.FolderId($sentItemsFolder, $mailbox)      &lt;br /&gt;$sentItems = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, $sentItemsId)      &lt;br /&gt;ProcessFolder($sentItems)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;# Now Deleted Items      &lt;br /&gt;$deletedItemsId = new-object Microsoft.Exchange.WebServices.Data.FolderId($deletedItemsFolder, $mailbox)      &lt;br /&gt;$deletedItems = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, $deletedItemsId)      &lt;br /&gt;ProcessFolder($deletedItems)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&amp;quot;Done!&amp;quot;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3453786" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Web+Services/">Exchange Web Services</category></item><item><title>The Effects Of Archival Stubs On Database Space Management</title><link>http://blogs.technet.com/b/bill_long/archive/2011/09/02/the-effects-of-archival-stubs-on-database-space-management.aspx</link><pubDate>Fri, 02 Sep 2011 23:02:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3450971</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3450971</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/09/02/the-effects-of-archival-stubs-on-database-space-management.aspx#comments</comments><description>&lt;p&gt;Update: The Exchange 2010 issue was resolved in SP2 RU1.&lt;br /&gt;&lt;br /&gt;Recently, there have been some theories flying around the blogosphere about the way archive stubbing affects space reclamation in Exchange databases. Specifically, some have questioned whether Exchange will properly reclaim the space when the size of an item in the database shrinks. I contend that yes, Exchange will properly reclaim that space. But you don&amp;rsquo;t have to take my word for it. I will show you exactly how I tested it, so that you can test it yourself and draw your own conclusions.&lt;/p&gt;
&lt;p&gt;First, however, I want to point out that we are currently investigating an issue with Exchange 2010 where database space is not reclaimed, but this issue does not necessarily have anything to do with archival or stubbing. We believe we have reproduced the behavior without those factors in the mix at all, and we are still trying to understand the behavior. This issue only affects Exchange 2010. As a result, I do not recommend trying to test this on Exchange 2010 at this time. The space may not be reclaimed as expected, and you could erroneously conclude that stubbing is at fault, when it&amp;rsquo;s actually due to the issue that we are investigating.&lt;/p&gt;
&lt;p&gt;That said, let&amp;rsquo;s get started with the test. The point of my test was to prove whether we free up space in the database when a large message body is replaced with a small one. We can&amp;rsquo;t really test this on 2010 because of the outstanding issue we&amp;rsquo;re looking at, but it can easily be tested on 2007 or 2003. I decided to perform a simple test on Exchange 2007. Here&amp;rsquo;s what I did.&lt;/p&gt;
&lt;h3&gt;The Test&lt;/h3&gt;
&lt;p&gt;First, I created a brand new database on my Exchange 2007 server. On that database I put a single mailbox. Then, I wrote a simple script to send a bunch of messages with large bodies to that mailbox. Here&amp;rsquo;s the script:&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;# Send-SMTPMessages&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;param([string]$ServerName, [string]$RecipientAddress, [int]$NumberOfMessages)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;$bodySB = new-object System.Text.StringBuilder &lt;br /&gt;for ($x = 0; $x -lt 25; $x++) # 25 = 5000 byte body (25 iterations * 2 bytes for each character * 100 characters) &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $foo = $bodySB.Append("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890") &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;$smtpClient = new-object System.Net.Mail.SmtpClient($ServerName)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;for ($x = 0; $x -lt $NumberOfMessages; $x++) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Sending message " + $x.ToString()) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $message = new-object System.Net.Mail.MailMessage("sendsmtpmsgscript@contoso.com", $RecipientAddress, ("Message " + ($x+1).ToString()), $bodySB.ToString()) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $smtpClient.Send($message) &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I ran the script with the following syntax:&lt;/p&gt;
&lt;p&gt;.\Send-SMTPMessages MyServerName mytestmailbox@contoso.com 10000&lt;/p&gt;
&lt;p&gt;As the script is written above, this will generate 10,000 messages (which I specified at the command line), with each of those messages having a 5000-byte message body. You can adjust the size of the message body by altering the number of iterations of the for loop, as I noted in the script. All those messages will end up in the Inbox of your test mailbox.&lt;/p&gt;
&lt;p&gt;With that done, I let online defrag run to make sure there was no free space (I set the schedule and watched for the 1221 event), and then I dismounted the database and generated a space dump with eseutil /ms.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re looking at space in an Exchange database, it&amp;rsquo;s important to understand how the database is structured. In all versions of Exchange prior to 2010, the database contained one big Msg table. That table held the bodies of every single message, for every single folder, for every single mailbox in the database. It was all stuffed into one huge table (attachments were stored in another huge table).&lt;/p&gt;
&lt;p&gt;So, as expected, my space dump showed that the vast majority of the content of the database was in the Msg table. Here is a snippet of the actual output:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Lucida Console;" face="Lucida Console"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type&amp;nbsp;&amp;nbsp; ObjidFDP&amp;nbsp;&amp;nbsp;&amp;nbsp; PgnoFDP&amp;nbsp; PriExt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Owned&amp;nbsp; Available &lt;br /&gt;Msg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tbl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 50&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11270&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 16 &lt;br /&gt;&amp;nbsp; &amp;lt;Long Values&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LV&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 98&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 51&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10046&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;ldquo;Owned&amp;rdquo; tells us how many pages belong to this table, and &amp;ldquo;Available&amp;rdquo; tells us how many of those pages are free. I had just created 10,000 new messages, so as you would expect, there was very little free space in the table.&lt;/p&gt;
&lt;p&gt;With that done, I mounted the database and ran another script. I wrote this second script to simulate the act of stubbing. It iterates over every message in the Inbox and changes the body to simply say &amp;ldquo;Stubbed!&amp;rdquo;, reducing the body size from 5000 bytes to less than 100 (it actually comes out to something like 80 bytes, because this method of setting the body generates some HTML around the text). Here&amp;rsquo;s the script:&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;# Stub-AllMessagesInMailbox.ps1&lt;br /&gt;# This script requires the EWS Managed API to be installed.&lt;/span&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;param($ServerName, $UserName, $Password, $DomainName)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll"&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;$exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1) &lt;br /&gt;$exchService.Credentials = new-object System.Net.NetworkCredential($UserName, $Password, $DomainName) &lt;br /&gt;$exchService.Url = new-object System.Uri(("&lt;/span&gt;&lt;a href="https://&amp;quot;"&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;https://"&lt;/span&gt;&lt;/a&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt; + $ServerName + "/EWS/Exchange.asmx")) &lt;br /&gt;$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;" color="#0000ff"&gt;$offset = 0 &lt;br /&gt;$itemView = new-object Microsoft.Exchange.WebServices.Data.ItemView(100) &lt;br /&gt;while (($inboxItems = $inbox.FindItems($itemView)).Items.Count -gt 0) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $inboxItems) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Stubbing item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Body = "Stubbed!" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $offset += $inboxItems.Items.Count &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $itemView = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset) &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #000000;" color="#000000"&gt;After all my items were &amp;ldquo;stubbed&amp;rdquo;, I immediately dismounted the database again and ran another space dump, without letting online defrag run. The result surprised me:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Lucida Console;" face="Lucida Console"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type&amp;nbsp;&amp;nbsp; ObjidFDP&amp;nbsp;&amp;nbsp;&amp;nbsp; PgnoFDP&amp;nbsp; PriExt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Owned&amp;nbsp; Available &lt;br /&gt;Msg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tbl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 50&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11414&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12 &lt;br /&gt;&amp;nbsp; &amp;lt;Long Values&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LV&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 98&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 51&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10054&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7952&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;My Owned pages went up slightly, but I instantly had 7,952 pages free in the LV tree of the Msg table &amp;ndash; about 62 MB. And this was before allowing online defrag to run. After online defrag I had even more free pages:&lt;/p&gt;
&lt;p&gt;&lt;span style="font-family: Lucida Console;" face="Lucida Console"&gt;Name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Type&amp;nbsp;&amp;nbsp; ObjidFDP&amp;nbsp;&amp;nbsp;&amp;nbsp; PgnoFDP&amp;nbsp; PriExt&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Owned&amp;nbsp; Available &lt;br /&gt;Msg&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Tbl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 19&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 50&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 11414&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 16 &lt;br /&gt;&amp;nbsp; &amp;lt;Long Values&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; LV&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 98&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 51&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1-m&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10050&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 8207&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;I repeated this test using message bodies of 2000 bytes and 7000 bytes, and the results were the same. I tried stubbing 5000-byte items down to 1078 bytes instead of 100 bytes, and the results were the same. I even tried stubbing only every 5th message instead of all the messages. In all my tests, Exchange 2007 freed a ton of pages when I reduced the size of the message bodies.&lt;/p&gt;
&lt;h3&gt;Conclusions From Testing&lt;/h3&gt;
&lt;p&gt;From this test, it is quite clear that after stubbing the items, space is reclaimed &amp;ndash; and not just a small amount, either. In fact, we reclaimed more space than we would expect based on the size of the items. 5000 bytes x 10000 messages = roughly 50 MB, but we got back about 65 MB (8207 pages * 8192 bytes per page = 67,231,744 bytes). This is likely due to page fragmentation from &lt;em&gt;before&lt;/em&gt; the stubbing. That is, if our items are 5k in size and we have 8k pages in Exchange 2007, we can&amp;rsquo;t fit 2 items on one page. As a result, there will be some unused space on these pages. After we stubbed, we were able to fit more items on a page more efficiently, and space wasted by fragmentation actually &lt;em&gt;decreased&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Page fragmentation might also explain why the Msg table was about 90 MB in size before we stubbed, when we had only added 50 MB of message bodies. This is a great example of why you can&amp;rsquo;t just add up mailbox sizes to determine how big the database file should be. It has a lot to do with what sort of data is in the database.&lt;/p&gt;
&lt;h3&gt;So What&amp;rsquo;s The Deal With Stubbing?&lt;/h3&gt;
&lt;p&gt;A few years back, I worked on a series of Exchange 2003 cases where customers were using stub archival (also known as shortcuts), and they were concerned at the discrepancy between reported mailbox size and actual database size. Several of those customers sent me databases, and I spent a few months working with the archival software vendor to analyze the database contents and understand the reason for the difference. Our findings revealed that the mystery space was being taken up by two types of overhead.&lt;/p&gt;
&lt;p&gt;The first type of overhead is properties that simply don't count toward the size of the message. When you look at the size of a message in Outlook, the size you see is not the total size of all the data that Exchange stores for that message. We store certain properties that do not count toward message size, and they aren&amp;rsquo;t counted against the user and aren&amp;rsquo;t reflected in the message size. These may be publicly documented properties such as PR_URL_NAME or other internal properties which are not publicly documented.&lt;/p&gt;
&lt;p&gt;The second type of overhead is page fragmentation. A page in an Exchange 2003 database is 4k in size. Each record in the database has to be arranged onto these pages, and depending on how efficiently we are able to do so, there will be some space left on the page. This is page fragmentation, which results in empty space that cannot be reclaimed by online maintenance.&lt;/p&gt;
&lt;p&gt;To the extent that an Exchange database is made up of many tiny items, these two kinds of overhead become more apparent. I worked with the vendor to set up a lab environment where we could test this theory with the vendor&amp;rsquo;s real archival software. We tested several scenarios, but I think the final test was the most interesting. We used LoadSim in a lab environment to fill a database with 1.4 million messages ranging in size from 1k to 4k with no attachments. Even before archiving, the database had about 30% overhead from fragmentation and 20% from properties that don't count toward message size. This showed that the behavior can be achieved even without archival by filling the database with lots of small items. After archiving everything and leaving shortcuts in place, those numbers went up to a combined 70% (because all the 4k items became much smaller shortcuts), although archiving did free up about 15% of the database. The same behavior would be expected from any archival product that is configured to leave shortcuts behind.&lt;/p&gt;
&lt;p&gt;Exchange will continue to work just fine in this scenario. There's nothing inherently wrong with it. It's just that when you archive email messages and leave behind a shortcut, you are taking out the big properties like message body and attachments, and leaving a small stub - but all the overhead associated with the item remains. Although you do save disk space by taking out the big stuff, the remaining tiny items still have the same amount of overhead as a normal item. The ratio of overhead to actual email rises, so the database size will be considerably larger than what you would expect from adding up the reported mailbox sizes.&lt;/p&gt;
&lt;p&gt;We concluded that if you want to reduce the overhead, the best approach is to expire the shortcuts after some time limit. To the extent you expire the shortcuts, you should see the overhead come down. Of course, another option is to let all the shortcuts stay in the database, knowing that your database is perfectly healthy despite the size difference between the mailbox sizes and the file size.&lt;/p&gt;
&lt;p&gt;So what about Exchange 2007? If anything, I would expect page fragmentation to be somewhat less of an issue in 2007 than 2003 due to the larger page size. That should make it easier to arrange several stubbed items onto a single page. But again, this will depend a lot on what sort of items you put in the database.&lt;/p&gt;
&lt;h2&gt;In Conclusion&lt;/h2&gt;
&lt;p&gt;I avoided discussing Exchange 2010 here, because the issue with space reclamation which we are currently investigating makes it very difficult to test and draw any conclusions about how 2010 will behave.&lt;/p&gt;
&lt;p&gt;However, my findings in testing Exchange 2007 are clear: When the items shrink, we reclaim a lot of space. Background cleanup is able to grab much of the space even before online defrag comes along. Maybe someone can find fault with my testing, or maybe someone can come up with a reproducible scenario where we don&amp;rsquo;t reclaim the space. If you can, I would love to hear from you.&lt;/p&gt;
&lt;p&gt;Let me clearly state: At this time, there is no known issue with archival stubs beyond the increased overhead ratio I described above.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3450971" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Information+Store/">Information Store</category></item><item><title>Hierarchy Replication Fails Due To Zero GUID</title><link>http://blogs.technet.com/b/bill_long/archive/2011/06/24/hierarchy-replication-fails-due-to-zero-guid.aspx</link><pubDate>Fri, 24 Jun 2011 21:57:24 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3437404</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3437404</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/06/24/hierarchy-replication-fails-due-to-zero-guid.aspx#comments</comments><description>&lt;p&gt;Exchange 2010 Sp1 Rollup Update 4 released a couple of days ago, and I want to briefly mention one of the fixes it includes. The fix I’m talking about is KB &lt;a href="http://support.microsoft.com/kb/2506049"&gt;2506049&lt;/a&gt;, “The hierarchy of a new public folder database on an Exchange Server 2010 SP1 server is not replicated”. You’ll know you’ve hit this problem if you get the very specific events mentioned in the article with error code 80070057. Specifically, we should see this in the 3079:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Unexpected replication thread error &lt;strong&gt;80070057&lt;/strong&gt; on database &amp;quot;First Storage Group\Public Folder Store (&lt;var&gt;&amp;lt;Server_Name&amp;gt;&lt;/var&gt;)&amp;quot;.       &lt;br /&gt;      &lt;br /&gt;&lt;strong&gt;EcReplFolderMessagesUnpack        &lt;br /&gt;EcReplMessageUnpack&lt;/strong&gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;If you’re not seeing that, then you’re not hitting this problem.&lt;/p&gt;  &lt;p&gt;If you are hitting this problem, it means that your current PF databases which have hierarchy and content have a GUID in them somewhere of 00000000-0000-0000-0000-000000000000. It’s a GUID of all zeroes, and it’s not valid. Starting with Exchange 2010 SP1, we block these GUIDs from entering a new database. So, if you have this sitting around in your old PF databases, and you bring up a new clean database on 2010 SP1, the hierarchy fails to replicate because we refuse to let this GUID replicate in. You’ll never notice this problem until you try to create a new database on 2010 SP1 or later.&lt;/p&gt;  &lt;p&gt;What I want to focus on, however, is the fix. The article states the following:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;After you apply this update on all the computers that have public folder databases, follow these steps: &lt;/p&gt;    &lt;ol&gt;     &lt;li&gt;Unmount all public folder databases in the organization. &lt;/li&gt;      &lt;li&gt;Run the following command on all the computers that have public folder databases in the organization:       &lt;br /&gt;&lt;b&gt;isinteg -s &amp;lt;server&amp;gt; -test replidguid -fix&lt;/b&gt;&lt;/li&gt;      &lt;li&gt;Mount all public folder databases.&lt;/li&gt;   &lt;/ol&gt;   &lt;b&gt;Notes&lt;/b&gt;    &lt;ul&gt;     &lt;li&gt;The command must be run simultaneously on all the computers that have public folder databases in the organization. &lt;/li&gt;      &lt;li&gt;Do not follow these steps if there are any public folder servers that are not running Update Rollup 4 for Exchange Server 2010 SP1, such as Exchange Server 2003, Exchange Server 2007, or earlier versions of Exchange Server 2010. &lt;/li&gt;      &lt;li&gt;If you try to run the command on only a subset of computers that have public folder databases in the organization, public folder replication issues occur. Additionally, the issues cannot be resolved.&lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;p&gt;This command will strip the zero GUID out of the databases. Yes, the command must be run simultaneously on all public folder databases in the org. This means that all public folder servers must be on at least Exchange 2010 SP1 RU4. If you have any Exchange 2007 or 2003 public folder servers, you cannot use this fix.&lt;/p&gt;  &lt;p&gt;Even if all your public folder databases are on Exchange 2010 SP1 RU4 or newer, you must dismount all of them at the same time and run this command against all of them. &lt;strong&gt;They must all be dismounted at the same time and must not be mounted until the command has been run.&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;To put it another way, a fixed database must not replicate with an unfixed database. In order to achieve this, all databases must be dismounted before you start running the isinteg command. Once the command completes, you can mount that fixed database if you want. But be very careful. It is probably safer to just leave them all down until you are sure they have all been fixed.&lt;/p&gt;  &lt;p&gt;If you fix one or more databases and then accidentally mount one that has not been fixed, you run a high risk of introducing a form of logical corruption that cannot be fixed, ever, at all. When the article says that the issues cannot be resolved, we really mean it. The only option at that point is to pull the public folder data out to PSTs and start over with clean public folder databases everywhere.&lt;/p&gt;  &lt;p&gt;Please use caution when using this fix, and make sure that when this isinteg command is run, all public folder databases have been dismounted and are not mounted again until they are fixed.&lt;/p&gt;  &lt;p&gt;The good news is that this fix is extremely fast. This isinteg command should complete in less than a minute.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3437404" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category></item><item><title>Do Not Use Remove-PublicFolder To Remove A Public Folder Database</title><link>http://blogs.technet.com/b/bill_long/archive/2011/06/11/do-not-use-remove-publicfolder-to-remove-a-public-folder-database.aspx</link><pubDate>Sat, 11 Jun 2011 05:30:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3434887</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3434887</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/06/11/do-not-use-remove-publicfolder-to-remove-a-public-folder-database.aspx#comments</comments><description>&lt;p&gt;About once a week, someone comes to me about a case where a customer has accidentally deleted all their public folders when they were just trying to get rid of one public folder store. This happens because of &lt;a href="http://social.technet.microsoft.com/Forums/en-US/exchangesvrdeploy/thread/47166fac-ebf3-42d9-bec3-ca6423f0e427"&gt;threads&lt;/a&gt; or blog &lt;a href="http://telnetport25.wordpress.com/2007/08/21/quick-tip-removing-exchange-2007-error-with-public-folder-replicas/"&gt;posts&lt;/a&gt; where someone suggests using some variation of this command:&lt;/p&gt;
&lt;p&gt;Get-PublicFolder "\" -Recurse -ResultSize Unlimited | Remove-PublicFolder&lt;/p&gt;
&lt;p&gt;The first part of this command returns every public folder in the hierarchy (except for System Folders, which are under \Non_Ipm_Subtree). It returns every folder in the hierarchy, not just the ones that have replicas on a particular server. The second part of this command &lt;strong&gt;deletes those folders out of the hierarchy&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Yes, it deletes them. I don&amp;rsquo;t mean it just deletes them off of one particular store &amp;ndash; that would be removing or deleting a &lt;strong&gt;replica&lt;/strong&gt;. Remove-PublicFolder &lt;strong&gt;deletes the folder&lt;/strong&gt;, just like if you go into Outlook, navigate to the folder, and choose Delete.&lt;/p&gt;
&lt;p&gt;Of course, the deletion of the folder can take up to 15 minutes to replicate to the other public folder stores, so some customers get lucky. They run the command, then immediately run Remove-PublicFolderDatabase and delete the database before it has a chance to replicate. In that case, you only lose the directory objects for mail-enabled folders, so if you don&amp;rsquo;t have any mail-enabled folders, you may not even notice a problem.&lt;/p&gt;
&lt;p&gt;In other cases, customers get very unlucky, and the change replicates immediately, wiping out every public folder on every public folder server throughout the entire organization.&lt;/p&gt;
&lt;p&gt;If you get nothing else from this post, please just remember that Remove-PublicFolder deletes the public folder, and that change will replicate to all the other public folder stores.&lt;/p&gt;
&lt;p&gt;So, what should you do if you are trying to remove a public folder database, and it&amp;rsquo;s telling you something like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;i&gt;Remove-PublicFolderDatabase : The public folder database specified contains folder replicas. Before deleting the public folder database, remove the folders or move the replicas to another public folder database.&lt;/i&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In that case, you should read my post on the Exchange Team Blog from several years ago:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/b/exchange/archive/2007/11/13/clarifying-the-public-folder-store-removal-on-exchange-server-2007.aspx"&gt;http://blogs.technet.com/b/exchange/archive/2007/11/13/clarifying-the-public-folder-store-removal-on-exchange-server-2007.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The bottom line is that if you&amp;rsquo;re getting that error, you should use Get-PublicFolderStatistics to see which folders have not replicated off&amp;nbsp;that store. The replica list on those folders needs to be changed so that you've added&amp;nbsp;some other server, if there wasn't one already, and removed this server.&amp;nbsp;This can be done with Set-PublicFolder, or MoveAllReplicas.ps1,&amp;nbsp;or PFMC, or ExFolders, etc. Once you've changed the replica list, allow some time for replication.&lt;/p&gt;
&lt;p&gt;Unfortunately, in many cases, customers change the replica list and wait, but the folders are still sticking in Get-PublicFolderStatistics.&amp;nbsp;If those are folders you don&amp;rsquo;t care about, like OWAScratchPad and such, then feel free to delete them with Remove-PublicFolder (or Outlook, or MfcMapi, or PFMC, etc). If those are folders you do care about, you should confirm whether all the data you wanted replicated off. In most cases, they will be stuck because of a few bad/corrupt items that don&amp;rsquo;t want to replicate.&lt;/p&gt;
&lt;p&gt;If you have folders that are stuck because of a few corrupt items, you have a few options. You can delete the bad items, which will allow the replica to gracefully remove itself via the normal replica removal process. You can dismount the database and delete it with ADSI Edit, losing any data that didn&amp;rsquo;t replicate off, and possibly breaking age limits for any folders that still had replicas there. But either of those options is probably better than piping the results of Get-PublicFolder to Remove-PublicFolder, which runs the risk of deleting the whole hierarchy throughout your environment.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3434887" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category></item><item><title>Importing PFDAVAdmin or ExFolders Exports Without PFDAVAdmin or ExFolders</title><link>http://blogs.technet.com/b/bill_long/archive/2011/04/26/importing-pfdavadmin-or-exfolders-exports-without-pfdavadmin-or-exfolders.aspx</link><pubDate>Tue, 26 Apr 2011 05:26:51 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3424181</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3424181</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2011/04/26/importing-pfdavadmin-or-exfolders-exports-without-pfdavadmin-or-exfolders.aspx#comments</comments><description>&lt;p&gt;It’s almost May and I haven’t posted anything yet this year, so it’s definitely time to post a new script.&lt;/p&gt;  &lt;p&gt;I recently worked with a customer that needed to export the public folder permissions from one Exchange organization and import them into another. The trick was that on the import side, some of the accounts were only mail-enabled – not mailbox-enabled. This creates a problem for ExFolders, because the API it uses does not consider mail-enabled accounts to be valid security principals. However, if you use the Add-PublicFolderClientPermission cmdlet to set the permissions, it has no problem with such an account.&lt;/p&gt;  &lt;p&gt;I looked at changing ExFolders to better support this, but the changes would be complex and I just didn’t have that kind of time. Instead, I decided to write a script to import the permissions using the cmdlet. There are a few things to be aware of about the script.&lt;/p&gt;  &lt;p&gt;First, the script will be &lt;strong&gt;much&lt;/strong&gt; slower than using PFDAVAdmin or ExFolders to run the import. This is because the cmdlets only let you modify one user at a time, and unless you want to do a lot of complicated calculations, you need to remove the existing permissions for the user before adding the new ones. This means we end up running two cmdlets for every user permission. If you are importing permissions for 5 users on a folder, it will take 10 commands to assign those permissions.&lt;/p&gt;  &lt;p&gt;Second, the script currently only works with exports that are in legacyExchangeDN format. If you used NT Account format (domain\user), this script can’t handle them. This means the legacyExchangeDNs from the old environment have to be resolvable in the new one. That is usually the case, since they are brought over as X500 addresses in most migrations.&lt;/p&gt;  &lt;p&gt;And finally, this script works only with public folder permissions exports from PFDAVAdmin or ExFolders. If you exported replicas or properties or something, this script won’t help you.&lt;/p&gt;  &lt;p&gt;Anyway, here is the script. Enjoy!&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Import-PFPermissions.ps1     &lt;br /&gt;#      &lt;br /&gt;# The purpose of this script is to import permissions from an export      &lt;br /&gt;# file generated using PFDAVAdmin or ExFolders.      &lt;br /&gt;#       &lt;br /&gt;# Syntax example:      &lt;br /&gt;#       &lt;br /&gt;# .\Import-PFPermissions C:\someimportfile.txt MYPFSERVER&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;param([string]$importFile, [string]$server)&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;function ConvertRightsString([string]$pfdavRightsString)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $pfdavRights = $pfdavRightsString.Split(@(' '))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $powershellRights = &amp;quot;&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; foreach ($right in $pfdavRights)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($right -eq &amp;quot;All&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;Owner,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Owner&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;CreateItems,ReadItems,CreateSubfolders,FolderOwner,FolderVisible,EditOwnedItems,EditAllItems,DeleteOwnedItems,DeleteAllItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Contact&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;FolderContact,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Create&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;CreateItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;CreateSubfolder&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;CreateSubfolders,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Delete&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;DeleteAllItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;DeleteOwn&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;DeleteOwnedItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Write&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;EditAllItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;WriteOwn&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;EditOwnedItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;o&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;FolderOwner,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Visible&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;FolderVisible,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($right -eq &amp;quot;Read&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += &amp;quot;ReadItems,&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $powershellRights += ($right + &amp;quot;,&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $powershellRights = $powershellRights.TrimEnd(@(','))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return $powershellRights      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;function RemoveFolderVisibleWithTrap([string]$folderPath, [string]$server, [string]$userString)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; trap [Exception]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; continue      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $returnedValue = Remove-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights FolderVisible      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$fileReader = new-object System.IO.StreamReader($importFile)     &lt;br /&gt;while ($null -ne ($buffer = $fileReader.ReadLine()))      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ($buffer.StartsWith(&amp;quot;SETACL`t&amp;quot;))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $columns = $buffer.Split(@(&amp;quot;`t&amp;quot;))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # Resolve the folder path, which should always be the second column.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $folderPath = $columns[1]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($folderPath.StartsWith(&amp;quot;Public Folders\&amp;quot;))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $folderPath = $folderPath.Substring(14)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($folderPath.StartsWith(&amp;quot;System Folders\&amp;quot;))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $folderPath = (&amp;quot;\NON_IPM_SUBTREE&amp;quot; + $folderPath.Substring(14))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Updating folder: &amp;quot; + $folderPath)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for ($x = 2; $x -lt $columns.Length; $x+=2)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $userString = $columns[$x]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($userString.StartsWith(&amp;quot;/o=&amp;quot;))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $recipient = Get-Recipient $userString      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($recipient -ne $null)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $userString = $recipient.Identity      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Could not resolve: &amp;quot; + $userString)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; continue      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($userString -ne &amp;quot;Default&amp;quot; -and $userString -ne &amp;quot;Anonymous&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Skipping unrecognized user format: &amp;quot; + $userString)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; continue      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Processing user: &amp;quot; + $userString)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Checking for existing permissions...&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $permsForUser = Get-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($permsForUser -ne $null)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Removing existing permissions...&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $permsForUser | Remove-PublicFolderClientPermission -Identity $folderPath -Server $server -Confirm:$false      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Adding new permissions...&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $rightsString = ConvertRightsString $columns[$x+1]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AccessRights: &amp;quot; + $rightsString)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $rightsArray = $rightsString.Split(@(','))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($permissionString -eq &amp;quot;None&amp;quot;)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # This requires special handling. In the cmdlet, there is no way to grant a user no permissions,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # denying the ability to even see the folder, because the None role includes the FolderVisible      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # right. When a user has None without folder visible, it still shows up as None, but IsRole is      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # false. We need to check for that situation here to make sure None is really None. In the      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # export, None really means no rights at all.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; #      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # So, what we do here, is first we set rights of None. Then, we try to remove FolderVisible,      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # and ignore any errors that happen. If it succeeds, we don't have FolderVisible anymore, and      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; # if it fails, we didn't have FolderVisible in the first place, so it doesn't matter.      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $returnedValue = Add-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights $rightsArray      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RemoveFolderVisibleWithTrap $folderPath $server $userString      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $returnedValue = Add-PublicFolderClientPermission -Identity $folderPath -Server $server -User $userString -AccessRights $rightsArray      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3424181" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/ExFolders/">ExFolders</category></item><item><title>Canonical Ordering Of Mailbox Permissions In Exchange</title><link>http://blogs.technet.com/b/bill_long/archive/2010/12/27/canonical-ordering-of-mailbox-permissions-in-exchange.aspx</link><pubDate>Mon, 27 Dec 2010 19:30:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3377403</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3377403</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/12/27/canonical-ordering-of-mailbox-permissions-in-exchange.aspx#comments</comments><description>&lt;p&gt;An Access Control List, or &lt;strong&gt;ACL&lt;/strong&gt;, is basically just a list of Access Control Entries, or &lt;strong&gt;ACEs&lt;/strong&gt;. Each ACE contains a flag indicating whether it&amp;rsquo;s an Allow or a Deny ACE, a mask that shows which rights are being allowed or denied, and a SID to which those allow or deny rights are applied.&lt;/p&gt;
&lt;p&gt;Evaluating an ACL to determine if a user has certain rights is pretty simple. We take the user&amp;rsquo;s token, which is a list of all SIDs that apply to this user (all groups he&amp;rsquo;s a member of), and then we iterate through the ACL looking at each ACE in the order in which it appears. We keep evaluating ACEs until we hit one of two conditions: either &lt;em&gt;all rights requested have been granted&lt;/em&gt;, or &lt;em&gt;any one right requested has been denied&lt;/em&gt;. At that point, evaluation stops, and we don&amp;rsquo;t even bother looking at the rest of the ACEs.&lt;/p&gt;
&lt;p&gt;Because of this process, in order to achieve the desired behavior where denies take precedence over allows, the ACL must be in a specific order. If the ACL is ordered correctly, we say it is canonical. If the order is incorrect, we say it is non-canonical, because it does not follow the established rules for the ordering of ACEs in an ACL.&lt;/p&gt;
&lt;p&gt;For example, let&amp;rsquo;s say we have the following very simple ACL, with only two ACEs:&lt;/p&gt;
&lt;table cellpadding="2" cellspacing="0" border="0" style="width: 400px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Allow/Deny&lt;/td&gt;
&lt;td width="133" valign="top"&gt;Rights Mask&lt;/td&gt;
&lt;td width="133" valign="top"&gt;SID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Deny&lt;/td&gt;
&lt;td width="133" valign="top"&gt;0xFFFFFFFF&lt;/td&gt;
&lt;td width="133" valign="top"&gt;S-1-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Allow&lt;/td&gt;
&lt;td width="133" valign="top"&gt;0xFFFFFFFF&lt;/td&gt;
&lt;td width="133" valign="top"&gt;S-1-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The S-1-1-0 SID is the SID for the Everyone group. In this ACL, we have two ACEs. The first ACE denies all rights to the Everyone group. The second one grants all rights to the Everyone group. When we go through the process of checking a user&amp;rsquo;s rights, the first ACE we hit says that all rights are denied to Everyone. Because of that, we stop right there, and the evaluation result will be that all rights are denied. In this case, canonical order was followed, so we have the expected behavior &amp;ndash; the user is denied access to the object.&lt;/p&gt;
&lt;p&gt;Now imagine the ACEs are not in canonical order:&lt;/p&gt;
&lt;table cellpadding="2" cellspacing="0" border="0" style="width: 401px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Allow/Deny&lt;/td&gt;
&lt;td width="133" valign="top"&gt;Rights Mask&lt;/td&gt;
&lt;td width="133" valign="top"&gt;SID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Allow&lt;/td&gt;
&lt;td width="133" valign="top"&gt;0xFFFFFFFF&lt;/td&gt;
&lt;td width="133" valign="top"&gt;S-1-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="133" valign="top"&gt;Deny&lt;/td&gt;
&lt;td width="133" valign="top"&gt;0xFFFFFFFF&lt;/td&gt;
&lt;td width="133" valign="top"&gt;S-1-1-0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In this case, when we evaluate the ACL, the first ACE we hit says that all rights are allowed. The evaluation stops right there, and the result is that the user is allowed to access the object, despite the fact that we have also denied all rights to Everyone! So in this case, the ACL is non-canonical, and the result is that the permissions don&amp;rsquo;t function as expected &amp;ndash; the user is allowed access.&lt;/p&gt;
&lt;p&gt;Note that the above is a much simplified example just to illustrate why canonical order exists. For full information on canonical ordering of ACEs, see MSDN.&lt;/p&gt;
&lt;p&gt;Canonical ordering is not enforced by Windows itself &amp;ndash; it is enforced by the tools that are usually used to manage those ACLs. If you set permissions on an Active Directory object using Active Directory Users And Computers, those permissions will be canonical. If you set rights on a file using Explorer, the ACL on the file will be canonical.&lt;/p&gt;
&lt;p&gt;However, it&amp;rsquo;s entirely possible for a programmer to write a tool that saves ACLs to these objects in non-canonical order. In fact, in some cases this has been done intentionally. Back in Exchange 2003, you could choose to hide distribution group membership. Doing so caused us to purposely put the ACL in non-canonical order. After hiding the membership, attempting to go to the Security tab in ADUC resulted in the message &amp;ldquo;Windows can not edit the permissions on &amp;lsquo;whatever&amp;rsquo; because they have been written in a nonstandard format by another application. To enable editing, you must use the application to restore the permissions to a standard format.&amp;rdquo; This message was because the ACL was non-canonical.&lt;/p&gt;
&lt;p&gt;Mailbox permissions require canonical ordering just like AD permissions or file permissions (public folder permissions have their own canonical order that is different from Windows canonical order &amp;ndash; that&amp;rsquo;s a topic for another post). If you run &lt;strong&gt;Add-MailboxPermissions&lt;/strong&gt; to modify the permissions and the ACL is not canonical, the cmdlet reports an error:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The ACL for the object "whatever" is not in canonical order (Deny/Allow/Inherited) and will be ignored.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This makes it impossible to edit the mailbox rights using the cmdlet.&lt;/p&gt;
&lt;p&gt;I recently ran across a case where some mailboxes migrated from Exchange 2003 to Exchange 2007 were in this state. We were not able to determine what application made the ACLs non-canonical. To fix the problem, I wrote a simple application called &lt;strong&gt;FixMailboxSD&lt;/strong&gt; and made the tool and the source available on Codeplex: &lt;a href="http://fixmailboxsd.codeplex.com/" title="http://fixmailboxsd.codeplex.com/"&gt;http://fixmailboxsd.codeplex.com/&lt;/a&gt;. This uses the old CDOEXM interfaces from Exchange 2003 to put the mailbox rights back in canonical order.&lt;/p&gt;
&lt;p&gt;So, if you need an example of how to play with mailbox rights from C# using CDOEXM, you can take a look at this simple tool. Or, if you run into this same problem in your environment, feel free to use the tool to correct the mailbox rights on any affected mailboxes.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3377403" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category></item><item><title>Get-PublicFolderStatistics Can’t Find A Folder</title><link>http://blogs.technet.com/b/bill_long/archive/2010/10/28/get-publicfolderstatistics-can-t-find-a-folder.aspx</link><pubDate>Thu, 28 Oct 2010 18:36:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3364722</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3364722</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/10/28/get-publicfolderstatistics-can-t-find-a-folder.aspx#comments</comments><description>&lt;p&gt;On Exchange 2010, when you use the Get-PublicFolderStatistics command to look for the statistics of a particular folder, you may see an error like this one:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/8468.image_5F00_2.png"&gt;&lt;img height="118" width="686" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/2570.image_5F00_thumb.png" alt="image" border="0" title="image" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The cmdlet throws an InvalidOperationException saying that it &amp;ldquo;couldn&amp;rsquo;t find public folder&amp;rdquo;. However, if you look at the replica list, it clearly indicates that there is a replica on that server. This is because Get-PublicFolderStatistics is doing something sneaky in the background without warning you.&lt;/p&gt;
&lt;p&gt;If you run Get-PublicFolderStatistics with no other parameters, you&amp;rsquo;ll see this message:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/5226.image_5F00_4.png"&gt;&lt;img height="127" width="690" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/0842.image_5F00_thumb_5F00_1.png" alt="image" border="0" title="image" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the end of the list of results, it is warning you that it didn&amp;rsquo;t return the whole list of folders &amp;ndash; it only returned the first 100. You have to use -ResultSize Unlimited to get the entire list.&lt;/p&gt;
&lt;p&gt;When you run Get-PublicFolderStatistics and specify a particular Identity, the &lt;em&gt;same thing is happening&lt;/em&gt; in the background, but it doesn&amp;rsquo;t warn you. By default, it only returns the first 100 folders and looks through those for a matching Identity. If the folder you specified doesn&amp;rsquo;t happen to be one of the first 100, the command fails to find it.&lt;/p&gt;
&lt;p&gt;To make this work, you need to add -ResultSize Unlimited to the command:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/7776.image_5F00_6.png"&gt;&lt;img height="124" width="690" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/0028.image_5F00_thumb_5F00_2.png" alt="image" border="0" title="image" style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With that command, it is able to search the entire list of folders to find the one the user specified.&lt;/p&gt;
&lt;p&gt;Hopefully this helps anyone out there who is confused by the behavior of this cmdlet. On a recent case, quite a bit of time was spent before we understood why the command was failing to find the folder!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3364722" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category></item><item><title>Cleaning Viruses In Public Folders Using OOM</title><link>http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-oom.aspx</link><pubDate>Tue, 14 Sep 2010 07:26:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3355294</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3355294</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-oom.aspx#comments</comments><description>&lt;p&gt;In my &lt;a href="http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-ews.aspx"&gt;previous post&lt;/a&gt;, I provided an example script that used EWS to delete items out of public folders. Of course, you can only use EWS if your public folders are on Exchange 2007 or 2010.&lt;/p&gt;
&lt;p&gt;The example script in this post uses Outlook Object Model instead. This means it has to be run from a machine with Outlook installed (it should work with Outlook 2007 or Outlook 2010) as well as Powershell 2.0.&lt;/p&gt;
&lt;p&gt;You might notice that this script is a little simpler than the EWS example. Most of that is due to the fact that Outlook Object Model doesn&amp;rsquo;t give us much control over how to retrieve the contents of a folder. For folders with lots of items, you may find that this script will run very slowly, if it works at all. The EWS version won&amp;rsquo;t have that problem since it is able to use ranged retrieval, whereas this one has to get the items in one big chunk.&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# Delete-PublicFolderItems.ps1 &lt;br /&gt;# &lt;br /&gt;# Syntax: &lt;br /&gt;# &lt;br /&gt;# .\Delete-PublicFolderItems \TopFolder\Subfolder $false &lt;br /&gt;# This example runs against a single folder and does not recurse. &lt;br /&gt;# &lt;br /&gt;# .\Delete-PublicFolderItems "" $true &lt;br /&gt;# This example runs against the entire public folder hierarchy.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;param([string]$folderPath, [bool]$recurse)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# By default, this script only reports what it would have deleted. &lt;br /&gt;# If you flip $readOnly to $false, it WILL DELETE ITEMS OUT OF YOUR &lt;br /&gt;# PUBLIC FOLDERS. Make sure you've tested it first and you have a &lt;br /&gt;# backup. &lt;br /&gt;$readOnly = $true&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;$outlook = new-object -com Outlook.Application &lt;br /&gt;$mapi = $outlook.GetNamespace("MAPI") &lt;br /&gt;$pfStore = $null &lt;br /&gt;foreach ($store in $mapi.Stores) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($store.ExchangeStoreType -eq 2) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $pfStore = $store &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;if ($pfStore -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Couldn't find public folder store." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$pfRoot = $pfStore.GetRootFolder()&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# Define the function we'll use to traverse &lt;br /&gt;# the PF tree if a path was specified. &lt;br /&gt;function GetNamedFromCollection($name, $collection) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $collection) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Name -eq $name -or $item.DisplayName -eq $name) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $item &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $null &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$allPFs = GetNamedFromCollection "All Public Folders" $pfRoot.Folders &lt;br /&gt;if ($allPFs -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Couldn't find All Public Folders folder." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$folderPath = $folderPath.Trim("\") &lt;br /&gt;$folderPathSplit = $folderPath.Split("\") &lt;br /&gt;$folder = $allPFs &lt;br /&gt;if ($folderPath.Length -gt 0) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Traversing folder path..." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for ($x = 0; $x -lt $folderPathSplit.Length; $x++) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folder = GetNamedFromCollection $folderPathSplit[$x] $folder.Folders &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($folder -eq $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Could not find folder: " + $folderPath) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Found folder: " + $folder.FolderPath) &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# Now let's define the function that'll do the real work&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoFolder($folder) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Scanning folder: " + $folder.FolderPath) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $folder.Items) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ########################################################## &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Here's the most important part. This is where we &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # decide whether to delete the item. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # By default this script will delete any item that &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # contains the phrase "Here you have" in the subject. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # If that isn't what you want, you need to edit &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # the criteria here. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Subject.Contains("Here you have")) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($readOnly) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Would have deleted item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Deleting item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Delete() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch { "Error processing folder." } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($recurse) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($subfolder in $folder.Folders) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolder $subfolder &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch { "Error processing folder: " + $subfolder.FolderPath } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;DoFolder $folder&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;"Done!"&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3355294" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Outlook+Object+Model/">Outlook Object Model</category></item><item><title>Cleaning Viruses In Public Folders Using EWS</title><link>http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-ews.aspx</link><pubDate>Tue, 14 Sep 2010 06:23:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3355281</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3355281</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-ews.aspx#comments</comments><description>&lt;p&gt;As a result of last week&amp;rsquo;s virus outbreak, I&amp;rsquo;ve been getting some questions about how to clean viruses out of public folders. Unfortunately, there&amp;rsquo;s no equivalent of Export-Mailbox to pull infected messages out of public folders. However, it&amp;rsquo;s pretty easy to write a script to accomplish this through Exchange Web Services or Outlook Object Model based on my &lt;a href="http://blogs.technet.com/b/bill_long/archive/2010/04/06/accessing-the-information-store-from-powershell.aspx"&gt;previous post&lt;/a&gt; about accessing the Information Store from Powershell.&lt;/p&gt;
&lt;p&gt;This script is an example that uses EWS through the EWS Managed API, so it can be used for public folders on Exchange 2007 or 2010. You can run it from a Powershell 2.0 command prompt on a machine where you&amp;rsquo;ve installed the EWS Managed API. The Exchange tools aren&amp;rsquo;t required.&lt;/p&gt;
&lt;p&gt;Note that because this script accesses public folders via EWS, which is a client API, you must have the proper client permissions to the public folder in order to see and delete the items in question. Being an Exchange Administrator does not mean you will be able to delete items out of the public folders through a client. For more on admin rights versus client rights, see &lt;a href="http://blogs.technet.com/b/bill_long/archive/2010/04/28/public-folder-admin-permissions-versus-client-permissions.aspx" title="my post on that topic"&gt;my post on that topic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For an example that uses Outlook Object Model, which allows it to run against Exchange 2003 (or 2007 or 2010), see my &lt;a href="http://blogs.technet.com/b/bill_long/archive/2010/09/14/cleaning-viruses-in-public-folders-using-oom.aspx" title="next post"&gt;next post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Delete-PublicFolderItems.ps1&lt;br /&gt;# &lt;/span&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;This script requires Powershell 2.0 and .NET Framework 3.5. &lt;br /&gt;# &lt;br /&gt;# Syntax: &lt;br /&gt;# &lt;br /&gt;# .\Delete-PublicFolderItems &amp;lt;email address for autodiscover&amp;gt; &amp;lt;path to folder&amp;gt; &amp;lt;recurse&amp;gt; &lt;br /&gt;# &lt;br /&gt;# Examples: &lt;br /&gt;# &lt;br /&gt;# .\Delete-PublicFolderItems administrator@contoso.com \TopLevelFolder\Subfolder $false &lt;br /&gt;# This example runs against one specific folder and does not recurse. &lt;br /&gt;# &lt;br /&gt;# .\Delete-PublicFolderItems administrator@contoso.com "" $true &lt;br /&gt;# This example recursively runs against every folder in the PF hierarchy.&lt;br /&gt;#&lt;br /&gt;# The email address you specify should typically be the email address of the admin&lt;br /&gt;# you're logged in as. Otherwise you may see some strange autodiscover errors.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;param([string]$autoDiscoverEmail, [string]$folderPath, [bool]$recurse)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Remember to install the EWS managed API from here: &lt;br /&gt;# &lt;/span&gt;&lt;/span&gt;&lt;a href="http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&amp;amp;FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1"&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&amp;amp;FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style="font-size: small;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# &lt;br /&gt;# Then point the following command to the location of the DLL:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# If the following is set to $true, we run in READ ONLY mode. We report what we would have deleted, &lt;br /&gt;# but we don't delete anything. &lt;br /&gt;# &lt;br /&gt;# Changing this to $false will make the script DELETE ITEMS OUT OF YOUR PUBLIC FOLDERS. &lt;br /&gt;# Make sure you have tested this first and you have a backup.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;$readOnly = $true&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Use AutoDiscover to get the ExchangeService object&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;$exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1) &lt;br /&gt;if ($exchService -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Could not instantiate ExchangeService object." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;} &lt;br /&gt;$exchService.UseDefaultCredentials = $true &lt;br /&gt;$exchService.AutodiscoverUrl($autoDiscoverEmail) &lt;br /&gt;if ($exchService.Url -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Bind to the public folders&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;$pfs = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot) &lt;br /&gt;if ($pfs -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Now let's define the function we'll call to process the folders.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;function DoFolder([Microsoft.Exchange.WebServices.Data.Folder]$folder, [string]$path) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Scanning folder: " + $path) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Scan the items in this folder &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $offset = 0; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (($results = $folder.FindItems($view)).Items.Count -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $results) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ############################################################ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Here's the most important part. This is where we determine &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # whether to delete the item or not. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # By default this script will delete any item that contains &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # the phrase "Here you have" in the subject. If this is not &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # what you want, you need to edit the criteria here. &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Subject.Contains("Here you have")) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($readOnly) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Would have deleted item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Deleting item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::HardDelete) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ############################################################ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $offset += $results.Items.Count &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $view = new-object Microsoft.Exchange.WebServices.Data.ItemView(100, $offset) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($recurse) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # Recursively do subfolders &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(2147483647) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $subfolders = $folder.FindFolders($folderView)&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($subfolder in $subfolders) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; try &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolder $subfolder ($path + "\" + $subfolder.DisplayName) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch { "Error processing folder: " + $subfolder.DisplayName } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; catch &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# Call DoFolder on the top folder. &lt;br /&gt;# If $recurse is true, it will recursively call itself.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;if ($folderPath.Length -lt 1) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolder $pfs "" &lt;br /&gt;} &lt;br /&gt;else &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folderPathTrim = $folderPath.Trim("\") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folderPathSplit = $folderPathTrim.Split("\") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $tinyView = new-object Microsoft.Exchange.WebServices.Data.FolderView(2) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $displayNameProperty = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $thisFolder = $pfs &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for ($x = 0; $x -lt $folderPathSplit.Length; $x++) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $filter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($displayNameProperty, $folderPathSplit[$x]) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $results = $thisFolder.FindFolders($filter, $tinyView) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($results.TotalCount -gt 1) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Ambiguous folder name." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($results.TotalCount -lt 1) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Folder not found." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $thisFolder = $results.Folders[0] &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolder $thisFolder $folderPath &lt;br /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;# When we return here, we're done!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&lt;span style="font-size: small;"&gt;"Done!"&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3355281" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Web+Services/">Exchange Web Services</category></item><item><title>ExFolders for Exchange 2010 Sp1</title><link>http://blogs.technet.com/b/bill_long/archive/2010/09/13/exfolders-for-exchange-2010-sp1.aspx</link><pubDate>Mon, 13 Sep 2010 18:28:53 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3355141</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3355141</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/09/13/exfolders-for-exchange-2010-sp1.aspx#comments</comments><description>&lt;p&gt;A few of you emailed me when you noticed an error running ExFolders on Exchange 2010 SP1, which was recently released. Attempting to navigate into a mailbox would throw an error stating, “Error: Method not found.” This was due to some changes in the DLLs that ExFolders relies on.&lt;/p&gt;  &lt;p&gt;We’ve just posted a new version of ExFolders that works properly with Sp1. You can find it &lt;a href="http://msexchangeteam.com/files/12/attachments/entry456255.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The RTM version is still available for download as well. Be aware that the RTM version won’t work on Sp1, and the Sp1 version won’t work on RTM, as far as navigating into mailboxes.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3355141" width="1" height="1"&gt;</description></item><item><title>How To Identify Bad Items In Public Folder Replication</title><link>http://blogs.technet.com/b/bill_long/archive/2010/05/27/how-to-identify-bad-items-in-public-folder-replication.aspx</link><pubDate>Thu, 27 May 2010 19:24:56 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3334273</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3334273</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/05/27/how-to-identify-bad-items-in-public-folder-replication.aspx#comments</comments><description>&lt;p&gt;As I’ve previously discussed &lt;a href="http://msexchangeteam.com/archive/2008/01/10/447843.aspx"&gt;here&lt;/a&gt; and &lt;a href="http://blogs.technet.com/bill_long/archive/2010/04/22/fixing-public-folder-replication-errors-from-exchange-2003-to-exchange-2007-or-2010.aspx"&gt;here&lt;/a&gt;, there are various things that will prevent an item from replicating to an Exchange 2007 or Exchange 2010 public folder store – things like bad start/end dates on appointments, category names that contain certain characters, etc. However, once you’ve figured out that replication is failing because of one of these problems, it can still be tricky to identify which particular items are the ‘bad’ items. In this post, I want to share the approach we usually use to track these down.&lt;/p&gt;  &lt;p&gt;Now, you may be thinking, “Well, I can just compare the source and the destination to see which items didn’t make it over, and those are my bad items, right?” Not quite.&lt;/p&gt;  &lt;p&gt;When we replicate changes for a particular folder, we pack up as many changes as we can until we meet the Replication Message Size Limit configured on the public folder store. This applies to both the replication of new data and the backfill of existing data. As a result, when you observe a backfill response for a folder with a bunch of messages, you typically see a big list of items in the event:&lt;/p&gt;  &lt;p&gt;Event Type:&amp;#160;&amp;#160;&amp;#160; Information   &lt;br /&gt;Event Source:&amp;#160;&amp;#160;&amp;#160; MSExchangeIS Public Store    &lt;br /&gt;Event Category:&amp;#160;&amp;#160;&amp;#160; Replication Outgoing Messages     &lt;br /&gt;Event ID:&amp;#160;&amp;#160;&amp;#160; 3021    &lt;br /&gt;Description:    &lt;br /&gt;An outgoing replication message was issued. &lt;/p&gt;  &lt;p&gt; Type: 0x80000004   &lt;br /&gt; Message ID: &amp;lt;003346D6BDE71245954899B0FC2F3702017DCF@bilongtimb1.bilong.test&amp;gt;    &lt;br /&gt; Folder: (1-16771) IPM_SUBTREE\FolderA\Subfolder1 &lt;/p&gt;  &lt;p&gt; Database &amp;quot;First Storage Group\Public Folder Store (BILONGTIMB1)&amp;quot;.   &lt;br /&gt; CNSET: 1-1,1-1791E &lt;/p&gt;  &lt;p&gt; CNSET (FAI): 1-1,1-1791E &lt;/p&gt;  &lt;p&gt; Message IDs: 90   &lt;br /&gt;&amp;#160; 1: 1-1687B, 1-16C45    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;2: 1-1687C, 1-16C46    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;3: 1-16886, 1-16C47    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;4: 1-16890, 1-16C48    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;5: 1-1689A, 1-16C49    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;6: 1-168A4, 1-16C4A    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;7: 1-168AE, 1-16C4B    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;8: 1-168B8, 1-16C4C    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;9: 1-168C2, 1-16C4D    &lt;br /&gt;--- : Test 10 : 5/19/2010 4:16:12 PM    &lt;br /&gt;10: 1-1687A, 1-16C4E    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;11: 1-1687D, 1-16C4F    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;12: 1-16887, 1-16C50    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;13: 1-16891, 1-16C51    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;14: 1-1689B, 1-16C52    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;15: 1-168A5, 1-16C53    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;16: 1-168AF, 1-16C54    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;17: 1-168B9, 1-16C55    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;18: 1-168C3, 1-16C56    &lt;br /&gt;--- : Test 9 : 5/19/2010 4:16:09 PM    &lt;br /&gt;19: 1-16879, 1-16C57    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;20: 1-1687E, 1-16C58    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;21: 1-16888, 1-16C59    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;22: 1-16892, 1-16C5A    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;23: 1-1689C, 1-16C5B    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;24: 1-168A6, 1-16C5C    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;25: 1-168B0, 1-16C5D    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;26: 1-168BA, 1-16C5E    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;27: 1-168C4, 1-16C5F    &lt;br /&gt;--- : Test 8 : 5/19/2010 4:16:05 PM    &lt;br /&gt;28: 1-16878, 1-16C60    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;29: 1-1687F, 1-16C61    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;30: 1-16889, 1-16C62    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;31: 1-16893, 1-16C63    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;32: 1-1689D, 1-16C64    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;33: 1-168A7, 1-16C65    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;34: 1-168B1, 1-16C66    &lt;br /&gt;--- : Test 7 : 5/19/2010 4:15:59 PM    &lt;br /&gt;35: 1-168BB, 1-16C67    &lt;br /&gt;--- : Test 7 : 5...    &lt;br /&gt; MIDSET Deleted: 1-1,1-16871 &lt;/p&gt;  &lt;p&gt; Server: /O=FIRST ORGANIZATION/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=CONFIGURATION/CN=SERVERS/CN=BILONGE12MB1/CN=MICROSOFT PUBLIC MDB &lt;/p&gt;  &lt;p&gt;One thing to notice is that the end of the list of items you just have a “…”. In fact, it doesn’t even give the whole date for that last item – the date is truncated. This “…” at the end means there was more stuff there, but we didn’t log the rest. Because of this, you can’t really see the entire list of items that were included in this backfill response.&lt;/p&gt;  &lt;p&gt;Anyway, if any one of these items fails in content conversion, all the other items in this message also fail to replicate. Because of this, a single problem item can prevent many other items from replicating, even when those other items are just fine.&lt;/p&gt;  &lt;p&gt;Fortunately, there’s an easy way to find the problem items. You can let the replication engine narrow down the problem for you just by changing one simple setting.&lt;/p&gt;  &lt;p&gt;On the store that’s sending the backfill response (the store that has the data), set the replication message size limit to 1KB. Here are some example screenshots of the size limit from various tools:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/0535.sizelimit_2D00_Ti.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="sizelimit-Ti" border="0" alt="sizelimit-Ti" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/8461.sizelimit_2D00_Ti_5F00_thumb.jpg" width="549" height="359" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/1121.sizelimit_2D00_E12.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="sizelimit-E12" border="0" alt="sizelimit-E12" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/7318.sizelimit_2D00_E12_5F00_thumb.jpg" width="550" height="329" /&gt;&lt;/a&gt; &lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/1070.sizelimit_2D00_E12cmd.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="sizelimit-E12cmd" border="0" alt="sizelimit-E12cmd" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/6758.sizelimit_2D00_E12cmd_5F00_thumb.jpg" width="540" height="218" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;In the top two screenshots, I had already changed the limit to 1KB. In the bottom one I had not changed it yet, so it was still at its default of 300KB.&lt;/p&gt;  &lt;p&gt;Once you’ve turned up logging, changed the limit, and re-mounted the public store, go to the server that is missing the data and force a backfill timeout on that folder. In Exchange 2007 and 2010, you do this with the Update-PublicFolder cmdlet, or by right-clicking on the folder and choosing “Update Content” in the PF management GUI. In Exchange 2003, you do this from ESM by going to the public folder tree, clicking on the folder in question in the left-hand pane, choosing the Status tab in the right-hand pane, right-clicking on the server that doesn’t have the data, and choosing “Synchronize Content”.&lt;/p&gt;  &lt;p&gt;Because of the tiny replication size limit, instead of a few big replication messages, you’ll see a ton of tiny ones. Assuming you have logging turned up on Replication Incoming and Replication Outgoing, the application log on the server that has the data will look something like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/2248.applog1.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="applog1" border="0" alt="applog1" src="http://blogs.technet.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-00-82-55-metablogapi/0601.applog1_5F00_thumb.jpg" width="604" height="486" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;That 3026 you see at the bottom is the backfill request from the other server. Then you have a huge series of 3021’s, one for each backfill response. Each of these responses will only contain one or two messages.&lt;/p&gt;  &lt;p&gt;Once this process completes, most of the good messages will have successfully replicated. At that point, you can go and force a backfill timeout one more time. You’ll see another backfill request followed by some responses – but this time, since all the good stuff replicated, you’ll only see a few backfill responses. You can look at each of those response events to see the messages listed therein.&lt;/p&gt;  &lt;p&gt;And with that information, you know which messages to focus on to determine what the problem is! You can force a backfill timeout over and over, and you should see the store repeatedly try to replicate those same problem items every time.&lt;/p&gt;  &lt;p&gt;Once you’re done troubleshooting, you can change the replication message size limit back to 300KB.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3334273" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category></item><item><title>Fixing Public Folder Directory Objects That Aren’t Linked To The Hierarchy</title><link>http://blogs.technet.com/b/bill_long/archive/2010/05/12/fixing-public-folder-directory-objects-that-aren-t-linked-to-the-hierarchy.aspx</link><pubDate>Wed, 12 May 2010 20:43:40 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3332245</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3332245</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/05/12/fixing-public-folder-directory-objects-that-aren-t-linked-to-the-hierarchy.aspx#comments</comments><description>&lt;p&gt;In my recent &lt;a href="http://msexchangeteam.com/archive/2010/05/05/454821.aspx"&gt;post&lt;/a&gt; on the Exchange Team Blog, I briefly mentioned the dangers of forcibly removing an administrative group from ADSI Edit. The most common unintended consequence of this is a deletion of the directory object that represents the Public Folder Hierarchy.&lt;/p&gt;  &lt;p&gt;Deleting this object creates quite a mess, because all of your mail-enabled public folders and all of your public folder stores point to it. Even if you create a new hierarchy object and manually link the stores to it by setting the msExchOwningPFTree value, you still have a ton of public folder directory objects in Microsoft Exchange System Objects with no homeMDB.&lt;/p&gt;  &lt;p&gt;I had a customer today in this situation, and I wrote a quick Powershell script to fix all the directory objects for the mail-enabled public folders. Here it is.&lt;/p&gt;  &lt;p&gt;If you find yourself in this situation, you’ll still need to create a new hierarchy object and link your public folder stores to it. This script does not fix that part of the problem, although it wouldn’t be hard to adapt it to link the stores as well.&lt;/p&gt;  &lt;p&gt;To keep things simple, this only runs against one domain at a time. You’ll need to change the container to point to the Microsoft Exchange System Objects container in each different domain.&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Link-PFProxies.ps1      &lt;br /&gt;#       &lt;br /&gt;# Change these two values to match your environment.       &lt;br /&gt;# $container should point to the MESO container you want to run against.       &lt;br /&gt;# $pfTreeDN should contain the distinguishedName of the public folder hierarchy object. &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$container = [ADSI](&amp;quot;LDAP://CN=Microsoft Exchange System Objects,DC=contoso,DC=com&amp;quot;)      &lt;br /&gt;$pfTreeDN = &amp;quot;CN=Public Folders,CN=Folder Hierarchies,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=contoso,DC=com&amp;quot; &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;################################################# &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$filter = &amp;quot;(!(homemdB=*))&amp;quot;      &lt;br /&gt;$propertyList = @(&amp;quot;distinguishedName&amp;quot;)       &lt;br /&gt;$scope = [System.DirectoryServices.SearchScope]::OneLevel &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$finder = new-object System.DirectoryServices.DirectorySearcher($container, $filter, $propertyList, $scope)      &lt;br /&gt;$finder.PageSize = 100       &lt;br /&gt;$results = $finder.FindAll() &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;(&amp;quot;Found &amp;quot; + $results.Count + &amp;quot; folder proxies with no homeMDB...&amp;quot;)      &lt;br /&gt;foreach ($result in $results)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Fixing object: &amp;quot; + $result.Path)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $entry = $result.GetDirectoryEntry()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $entry.Put(&amp;quot;homeMDB&amp;quot;, $pfTreeDN)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $entry.SetInfo()       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3332245" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category></item><item><title>ExFolders Update</title><link>http://blogs.technet.com/b/bill_long/archive/2010/05/07/exfolders-update.aspx</link><pubDate>Fri, 07 May 2010 20:41:04 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3331218</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3331218</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/05/07/exfolders-update.aspx#comments</comments><description>&lt;p&gt;Due to a mix-up on my part, the April 13th update of ExFolders was actually missing some of the fixes from the previous release. Some of the bits included were from a preview build of ExFolders that was created prior to Exchange 2010 RTM. Oops!&lt;/p&gt;  &lt;p&gt;The web site was just updated with the proper bits, so please grab the latest &lt;a href="http://msexchangeteam.com/files/12/attachments/entry453398.aspx"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3331218" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/ExFolders/">ExFolders</category></item><item><title>Public Folder Replication And Legacy Admin Groups</title><link>http://blogs.technet.com/b/bill_long/archive/2010/05/05/public-folder-replication-and-legacy-admin-groups.aspx</link><pubDate>Wed, 05 May 2010 19:49:57 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3330561</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3330561</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/05/05/public-folder-replication-and-legacy-admin-groups.aspx#comments</comments><description>&lt;p&gt;Today, a &lt;a href="http://msexchangeteam.com/archive/2010/05/05/454821.aspx"&gt;new post&lt;/a&gt; from me went up on the &lt;a href="http://msexchangeteam.com/"&gt;Exchange Team Blog&lt;/a&gt; regarding a particular replication error in Exchange 2010. Be sure to check it out.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3330561" width="1" height="1"&gt;</description></item><item><title>Ambiguous SID Error in PFDAVAdmin</title><link>http://blogs.technet.com/b/bill_long/archive/2010/05/04/ambiguous-sid-error-in-pfdavadmin.aspx</link><pubDate>Tue, 04 May 2010 15:09:37 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3330162</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3330162</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/05/04/ambiguous-sid-error-in-pfdavadmin.aspx#comments</comments><description>&lt;p&gt;May 13, 2010 Edit: The Download Center has been updated with the new build of PFDAVAdmin which contains the fix for this issue.&lt;/p&gt;  &lt;p&gt;With the &lt;a href="http://msexchangeteam.com/archive/2004/06/30/170331.aspx"&gt;release of the new PFDAVAdmin&lt;/a&gt; a few weeks ago, some customers started running into an “Ambiguous SID” error when trying to add the Everyone group or Anonymous group in the permissions window. The error looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/AmbiguousSIDErrorinPFDAVAdmin_8ED4/error_2.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="error" border="0" alt="error" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/AmbiguousSIDErrorinPFDAVAdmin_8ED4/error_thumb.jpg" width="612" height="374" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;When you add a new entity to the permissions window, PFDAVAdmin looks up all objects with that SID to make sure it is unique. However, in some cases it’s actually normal to have more than one object with an ObjectSid that matches the Everyone or Anonymous SID. You should always have one in the configuration context under CN=WellKnown Security Principals, but many environments will also have one in the domain context under CN=Foreign Security Principals. This is when PFDAVAdmin finds two matches for these SIDs, and it chokes.&lt;/p&gt;  &lt;p&gt;One customer worked with me directly to track down the problem (thanks Giuliano!), and it’s fixed in my internal build. The Download Center will be updated with the new build, hopefully next week.&lt;/p&gt;  &lt;p&gt;In the meantime, if you have an urgent need for the fix, click the Email link to the left to contact me directly.&lt;/p&gt;  &lt;p&gt;If you’re getting this error with something other than Everyone or Anonymous, then you can use the following Powershell script to figure out which objects match the SID in question.&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;# Find-Sid.ps1      &lt;br /&gt;#       &lt;br /&gt;# The purpose of this script is to find all objects that have a       &lt;br /&gt;# given SID in objectSid, sidHistory, or msExchMasterAccountSid.       &lt;br /&gt;#       &lt;br /&gt;# Syntax:       &lt;br /&gt;#       &lt;br /&gt;# .\Find-Sid &amp;lt;sid&amp;gt;       &lt;br /&gt;#       &lt;br /&gt;# Example:       &lt;br /&gt;#       &lt;br /&gt;# .\Find-Sid S-1-1-0 &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;param([string]$sidString) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$gcRootDSE = [ADSI]&amp;quot;GC://RootDSE&amp;quot;      &lt;br /&gt;$gcRoot = [ADSI](&amp;quot;GC://&amp;quot; + $gcRootDSE.dnsHostName) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$sid = new-object System.Security.Principal.SecurityIdentifier($sidString)      &lt;br /&gt;[byte[]]$sidBytes = ,0 * $sid.BinaryLength       &lt;br /&gt;$sid.GetBinaryForm($sidBytes, 0) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$byteString = &amp;quot;&amp;quot;      &lt;br /&gt;for ($x = 0; $x -lt $sidBytes.Length; $x++)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $byteString = $byteString + &amp;quot;\&amp;quot; + $sidBytes[$x].ToString(&amp;quot;X2&amp;quot;)       &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$filter = &amp;quot;(|(objectSid=&amp;quot; + $byteString + &amp;quot;)(sidHistory=&amp;quot; + $byteString + &amp;quot;)(msExchMasterAccountSid=&amp;quot; + $byteString + &amp;quot;))&amp;quot;      &lt;br /&gt;$searcher = new-object System.DirectoryServices.DirectorySearcher($gcRoot, $filter, @(&amp;quot;distinguishedName&amp;quot;), [System.DirectoryServices.SearchScope]::Subtree)       &lt;br /&gt;$results = $searcher.FindAll() &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&amp;quot;Matching objects:&amp;quot;      &lt;br /&gt;foreach ($result in $results)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $result.Properties[&amp;quot;distinguishedname&amp;quot;]       &lt;br /&gt;}&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3330162" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category></item><item><title>Public Folder Admin Permissions Versus Client Permissions</title><link>http://blogs.technet.com/b/bill_long/archive/2010/04/28/public-folder-admin-permissions-versus-client-permissions.aspx</link><pubDate>Thu, 29 Apr 2010 04:47:37 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3329097</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3329097</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/04/28/public-folder-admin-permissions-versus-client-permissions.aspx#comments</comments><description>&lt;p&gt;Most Exchange administrators have noticed at one time or another that there are folders they can see and access through admin tools such as Exchange System Manager or PFDAVAdmin, but they can’t see or access those same folders through Outlook or OWA. I see a lot of confusion over this issue, so I want to explain a bit about how this works.&lt;/p&gt;  &lt;p&gt;Each public folder has two sets of permissions – &lt;strong&gt;client&lt;/strong&gt; permissions and &lt;strong&gt;admin&lt;/strong&gt; permissions. These are stored in two separate properties on the folder. Let’s start by taking a look at these two different ACLs.&lt;/p&gt;  &lt;h3&gt;Client Permissions&lt;/h3&gt;  &lt;p&gt;When you’re thinking about public folder permissions, you’re usually thinking about client permissions. Client permissions are the ones you see when you get properties on a folder in Outlook, or when you use the Get-PublicFolderClientPermission cmdlet, or when you look at Folder Permissions in the ExFolders or PFDAVAdmin tool. Here are some screenshots of looking at client permissions from different interfaces.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/Clientperms-ESM.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="Clientperms-ESM" border="0" alt="Clientperms-ESM" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/Clientperms-ESM_thumb.jpg" width="520" height="566" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Client permissions in Exchange System Manager&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-Outlook.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clientperms-Outlook" border="0" alt="clientperms-Outlook" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-Outlook_thumb.jpg" width="424" height="511" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Client permissions in Outlook 2007&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-PFDAVAdmin.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clientperms-PFDAVAdmin" border="0" alt="clientperms-PFDAVAdmin" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-PFDAVAdmin_thumb.jpg" width="533" height="401" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Client permissions in PFDAVAdmin&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-Powershell.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="clientperms-Powershell" border="0" alt="clientperms-Powershell" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/clientperms-Powershell_thumb.jpg" width="661" height="119" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Client permissions in Powershell&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Since folders in the hierarchy have typically been created by many different users, the client permissions are often different on each folder. The creator of the folder will be the Owner, and will often change the other rights on the folder as well, so there’s no telling what the client permissions will look like throughout the hierarchy.&lt;/p&gt;  &lt;h3&gt;Admin Permissions&lt;/h3&gt;  &lt;p&gt;Each public folder has a separate ACL that contains admin permissions. Admin permissions can only be seen through admin tools such as ESM or the Get-PublicFolderAdministrativePermission cmdlet. Here are some screenshots of looking at admin permissions.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/adminperms-ESM.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="adminperms-ESM" border="0" alt="adminperms-ESM" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/adminperms-ESM_thumb.jpg" width="477" height="498" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Admin permissions in ESM&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/adminperms-Powershell.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="adminperms-Powershell" border="0" alt="adminperms-Powershell" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/adminperms-Powershell_thumb.jpg" width="725" height="377" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;strong&gt;Admin permissions in Powershell&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Unlike client permissions, admin permissions are typically the same on every folder in the hierarchy. While it’s possible to change the admin permissions on individual folders, that’s a very rare scenario. This means that in most environments, Exchange admins do have admin permissions to every folder in the public folder hierarchy.&lt;/p&gt;  &lt;h3&gt;Am I using admin or client permissions?&lt;/h3&gt;  &lt;p&gt;When you access a public folder, we only honor one ACL or the other – either the client OR the admin permissions, but not both! The ACL we use to determine your access to a folder is determined entirely by the tool you are using to access it.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;If you are using Outlook to access a public folder, we only look at the client permissions.&lt;/li&gt;    &lt;li&gt;If you are using Outlook Web Access to access a public folder, we only look at the client permissions.&lt;/li&gt;    &lt;li&gt;If you are using Exchange System Manager to access a public folder, we only look at the admin permissions.&lt;/li&gt;    &lt;li&gt;If you are using the Exchange Powershell public folder cmdlets or the Exchange 2007 public folder management GUI, we only look at the admin permissions.&lt;/li&gt;    &lt;li&gt;If you are using PFDAVAdmin or ExFolders to access a public folder, we only look at the admin permissions.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This means that while an administrator can see and access all the public folders through an admin tool, he does not have the same rights when using a client such as Outlook. The behavior is different between the two types of programs, because we only look at one ACL or the other.&lt;/p&gt;  &lt;p&gt;This is actually controlled by the tool or client you are using. Any program has the option of asserting admin rights when connecting to the public store, but it is typically hard-coded and the user does not get a choice. The client programs never assert admin rights, while the admin programs always do. If you’re an admin using an admin tool, then you get to use the admin ACL instead of the client ACL to access the public folders through that tool, because the tool asserted admin rights when it connected to the public store.&lt;/p&gt;  &lt;p&gt;One way to see this is to use the &lt;a href="http://mfcmapi.codeplex.com/"&gt;MFCMAPI&lt;/a&gt; tool. After logging on, if you go to the MDB menu and choose Open Public Store, you’ll see the following dialog box:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/mfcmapi-admin.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="mfcmapi-admin" border="0" alt="mfcmapi-admin" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/PublicFolderAdminPermissionsVersusClient_14E6D/mfcmapi-admin_thumb.jpg" width="703" height="534" /&gt;&lt;/a&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;This shows a list of optional flags you can pass when opening the public store. Notice the very first one: 0x00000001 OPENSTORE_USE_ADMIN_PRIVILEGE. When a program passes this flag while opening the public store, it’s saying, “I’m an admin so let me use the admin permissions instead of the client permissions.” The store checks to see if the user has Exchange admin rights, and if so, he gets to use the admin ACL. MFCMAPI is the only tool I’m aware of that actually lets you choose whether to use the client or admin ACL by letting you modify the flags passed when opening the public store.&lt;/p&gt;  &lt;p&gt;If you were writing your own tool, such as a migration tool that needs to access all the public folder content, then this is exactly what you would want to do – pass the OPENSTORE_USE_ADMIN_PRIVILEGE flag when opening the public folder store. If you assert admin rights when opening the store, then your tool automatically gets access to all the public folders (assuming it’s being run by an Exchange admin), and you don’t have to worry about the different client permissions on all the folders.&lt;/p&gt;  &lt;p&gt;If you do need to access all public folders from a program that uses client permissions, you’ll need to use an admin tool to grant client permissions to the desired user on all the folders. This is easily accomplished using ESM, PFDAVAdmin, ExFolders, AddUsersToPFRecursive.ps1, etc.&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3329097" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/ExFolders/">ExFolders</category></item><item><title>Importing Public Folder Contacts From A CSV File</title><link>http://blogs.technet.com/b/bill_long/archive/2010/04/23/importing-public-folder-contacts-from-a-csv-file.aspx</link><pubDate>Fri, 23 Apr 2010 15:30:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3327910</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3327910</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/04/23/importing-public-folder-contacts-from-a-csv-file.aspx#comments</comments><description>&lt;P&gt;I just had a customer who needed to migrate contacts from an external database into a public folder. They could export the contacts from the database to a CSV, but they needed a way to get the CSV into the public folder. Last night, I whipped up this quick script.&lt;/P&gt;
&lt;P&gt;This morning, I was looking at my RSS feeds, and found that Glen Scales had just solved the same problem in a &lt;A href="http://gsexdev.blogspot.com/2010/04/flexible-exchange-contact-creation.html" mce_href="http://gsexdev.blogspot.com/2010/04/flexible-exchange-contact-creation.html"&gt;new blog post&lt;/A&gt;. Figures! Here is my version, but I recommend taking a look at his work as well.&lt;/P&gt;
&lt;P&gt;That said, here’s what an example CSV might look like for use with my script:&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;GivenName,Surname,EmailAddress1,EmailAddress2,HomePhone,MobilePhone,Business &lt;BR&gt;Contact,1,contact1@contoso.com,contact1@northwindtraders.com,888-555-1212,888-555-1212,One Microsoft Way%Redmond%WA%US%98052 &lt;BR&gt;Contact,2,contact2@contoso.com,contact2@northwindtraders.com,888-555-1212,888-555-1212,One Microsoft Way%Redmond%WA%US%98052&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Notice the weird physical address syntax where each part of the address is separated with a % character. This was my way of dealing with the need to parse out the individual address fields (Street, City, State, CountryOrRegion, PostalCode). Everything else is pretty straightforward. There are a lot of properties you can set that are not shown in this example CSV. I’ve listed most of them in the comments at the top of the script. Here it is.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;# Import-PFContacts &lt;BR&gt;# &lt;BR&gt;# The purpose of this script is to import contacts into a public folder on &lt;BR&gt;# Exchange 2007 or 2010 from a CSV file. The script reads from a CSV and then &lt;BR&gt;# creates a contact with the appropriate fields using the Exchange Web &lt;BR&gt;# Services Managed API. &lt;BR&gt;# &lt;BR&gt;# Requirements: &lt;BR&gt;# &lt;BR&gt;# This script requires Powershell 2.0. If you get the following error then you do not &lt;BR&gt;# have Powershell 2.0 installed: &lt;BR&gt;# &lt;BR&gt;# The term 'Import-Module' is not recognized as a cmdlet, function, operable program, &lt;BR&gt;# or script file. Verify the term and try again. &lt;BR&gt;# &lt;BR&gt;# The script also requires the EWS managed API, which can be downloaded here: &lt;BR&gt;# http://www.microsoft.com/downloads/details.aspx?displaylang=en&amp;amp;FamilyID=c3342fb3-fbcc-4127-becf-872c746840e1 &lt;BR&gt;# &lt;BR&gt;# Make sure the Import-Module command below matches the DLL location of the API. &lt;BR&gt;# &lt;BR&gt;# Syntax: &lt;BR&gt;# .\Import-PFContacts admin@contoso.com C:\SomeFile.csv "Top Level Folder\Subfolder\Contacts Folder" &lt;BR&gt;# &lt;BR&gt;# The first parameter is the email address that we'll use to run autodiscovery &lt;BR&gt;# and logon. The second parameter is the import file, and the third is the folder &lt;BR&gt;# where we want to create the contacts. &lt;BR&gt;# &lt;BR&gt;# Below you will find details on the columns that are supported in the import &lt;BR&gt;# file. Note that column names are CASE SENSITIVE. &lt;BR&gt;# &lt;BR&gt;# The import file can contain the following email address columns: &lt;BR&gt;# &lt;BR&gt;# EmailAddress1, EmailAddress2, EmailAddress3 &lt;BR&gt;# &lt;BR&gt;# The import file can contain the following phone number columns: &lt;BR&gt;# &lt;BR&gt;# AssistantPhone, BusinessFax, BusinessPhone, BusinessPhone2, Callback, CarPhone, &lt;BR&gt;# CompanyMainPhone, HomeFax, HomePhone, HomePhone2, Isdn, MobilePhone, OtherFax, &lt;BR&gt;# OtherTelephone, Pager, PrimaryPhone, RadioPhone, Telex, TtyTddPhone &lt;BR&gt;# &lt;BR&gt;# The import file can contain the following physical address columns. Note that &lt;BR&gt;# the syntax for these is a little odd at the moment. The address has five fields, &lt;BR&gt;# which must be in order and separated by % characters. They are street, city, &lt;BR&gt;# state, country or region, and postal code. Some of the fields can be left &lt;BR&gt;# blank if desired. An example address entry might look like this: &lt;BR&gt;# One Microsoft Way%Redmond%WA%US%98052 &lt;BR&gt;# The physical address columns are: &lt;BR&gt;# &lt;BR&gt;# Home, Business, Other &lt;BR&gt;# &lt;BR&gt;# The imort file can contain the following other columns: &lt;BR&gt;# &lt;BR&gt;# AssistantName, Birthday, BusinessHomePage, CompanyName, CompleteName, Department, &lt;BR&gt;# DisplayName, FileAs, Generation, GivenName, Initials, JobTitle, Manager, MiddleName, &lt;BR&gt;# Mileage, NickName, OfficeLocation, Profession, SpouseName &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;param([string]$autoDiscoverAddress, [string]$importFile, [string]$folderPath) &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;########## &lt;BR&gt;# &lt;BR&gt;# This path must match the install location of the EWS managed API. Change it if needed. &lt;BR&gt;# &lt;BR&gt;Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\1.0\Microsoft.Exchange.WebServices.dll" &lt;BR&gt;# &lt;BR&gt;########## &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;$emailAddressColumns = new-object System.Collections.Specialized.StringCollection &lt;BR&gt;$foo = $emailAddressColumns.AddRange(@("EmailAddress1", "EmailAddress2", "EmailAddress3")) &lt;BR&gt;$phoneNumberColumns = new-object System.Collections.Specialized.StringCollection &lt;BR&gt;$foo = $phoneNumberColumns.AddRange(@("AssistantPhone", "BusinessFax", "BusinessPhone", "BusinessPhone2", "Callback", "CarPhone")) &lt;BR&gt;$foo = $phoneNumberColumns.AddRange(@("CompanyMainPhone", "HomeFax", "HomePhone", "HomePhone2", "Isdn", "MobilePhone", "OtherFax")) &lt;BR&gt;$foo = $phoneNumberColumns.AddRange(@("OtherTelephone", "Pager", "PrimaryPhone", "RadioPhone", "Telex", "TtyTddPhone")) &lt;BR&gt;$physicalAddressColumns = new-object System.Collections.Specialized.StringCollection &lt;BR&gt;$foo = $physicalAddressColumns.AddRange(@("Business", "Home", "Other")) &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;$exchService = new-object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1) &lt;BR&gt;$exchService.UseDefaultCredentials = $true &lt;BR&gt;$exchService.AutodiscoverUrl($autoDiscoverAddress) &lt;BR&gt;$pfsRoot = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($exchService, [Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot) &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;$tinyView = new-object Microsoft.Exchange.WebServices.Data.FolderView(2) &lt;BR&gt;$displayNameProperty = [Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName &lt;BR&gt;$folderPathSplits = $folderPath.Split(@('\')) &lt;BR&gt;$folder = $pfsRoot &lt;BR&gt;for ($x = 0; $x -lt $folderPathSplits.Length;$x++) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $filter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo($displayNameProperty, $folderPathSplits[$x]) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $results = $folder.FindFolders($filter, $tinyView) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($results.TotalCount -gt 1) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Ambiguous name: " + $folderPathSplits[$x]) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($results.TotalCount -lt 1) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Folder not found: " + $folderPathSplits[$x]) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folder = $results.Folders[0] &lt;BR&gt;} &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;$importReader = new-object System.IO.StreamReader($importFile) &lt;BR&gt;$headers = $importReader.ReadLine().Split(@(',')) &lt;BR&gt;$line = 1 &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;while ($null -ne ($buffer = $importReader.ReadLine())) &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $line++ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($buffer.Length -gt 0) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact = new-object Microsoft.Exchange.WebServices.Data.Contact($exchService) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $columns = $buffer.Split(@(',')) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for ($x = 0; $x -lt $headers.Length; $x++) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($columns[$x].Length -lt 1) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; continue &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($emailAddressColumns.Contains($headers[$x])) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $emailAddressType = $headers[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $emailAddressType = [Microsoft.Exchange.WebServices.Data.EmailAddressKey]::$emailAddressType &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.EmailAddresses[$emailAddressType] = $columns[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($phoneNumberColumns.Contains($headers[$x])) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $phoneType = $headers[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $phoneType = [Microsoft.Exchange.WebServices.Data.PhoneNumberKey]::$phoneType &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.PhoneNumbers[$phoneType] = $columns[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($physicalAddressColumns.Contains($headers[$x])) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $addressFields = $columns[$x].Split(@('%')) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $addressType = $headers[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $addressType = [Microsoft.Exchange.WebServices.Data.PhysicalAddressKey]::$addressType &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address = new-object Microsoft.Exchange.WebServices.Data.PhysicalAddressEntry &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address.Street = $addressFields[0] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address.City = $addressFields[1] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address.State = $addressFields[2] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address.CountryOrRegion = $addressFields[3] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $address.PostalCode = $addressFields[4] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.PhysicalAddresses[$addressType] = $address &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($headers[$x] -eq "Birthday") &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.Birthday = [System.DateTime]::Parse($columns[$x]) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $attribute = $headers[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.$attribute = $columns[$x] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newContact.Save($folder.Id) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;BR&gt;} &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#0000ff&gt;"Done!"&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3327910" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Web+Services/">Exchange Web Services</category></item><item><title>Fixing Public Folder Replication Errors From Exchange 2003 to Exchange 2007 or 2010</title><link>http://blogs.technet.com/b/bill_long/archive/2010/04/22/fixing-public-folder-replication-errors-from-exchange-2003-to-exchange-2007-or-2010.aspx</link><pubDate>Thu, 22 Apr 2010 19:18:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3327671</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>25</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3327671</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/04/22/fixing-public-folder-replication-errors-from-exchange-2003-to-exchange-2007-or-2010.aspx#comments</comments><description>&lt;p&gt;In my post &lt;a href="http://blogs.technet.com/bill_long/archive/2010/04/06/accessing-the-information-store-from-powershell.aspx"&gt;Accessing The Information Store From Powershell&lt;/a&gt;, I promised I would post a real-world Outlook Object Model example in the future, so here it is.&lt;/p&gt;
&lt;p&gt;Back in 2008, I posted &lt;a href="http://msexchangeteam.com/archive/2008/01/10/447843.aspx"&gt;part 4&lt;/a&gt; of my public folder replication troubleshooting series on the Exchange Team Blog, with part 4 focused on Exchange 2007. In that post, I described several content conversion issues that prevent items from replicating from Exchange 2003 to Exchange 2007. These same problems prevent replication to Exchange 2010.&lt;/p&gt;
&lt;p&gt;We are looking at ways to possibly address this in the product, but for now, we often use a script I wrote to identify and correct some of these problems. The script uses Outlook Object Model from Powershell to dig through the public folder items on the Exchange 2003 side and examine them for known problems. It does not fix every possible problem, but it does fix a few of the common ones and can save you quite a bit of manual work.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve called in with one of these problems, you may have used an earlier version of this script already. This is the latest version. Enjoy!&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# Fix-PFItems.ps1 &lt;br /&gt;# &lt;br /&gt;# This script should be run on a workstation where Outlook is installed &lt;br /&gt;# as well as Powershell. You do not need the Exchange Management Console &lt;br /&gt;# installed in order to use this. The Outlook profile you are using should be &lt;br /&gt;# one that will access public folders on the Exchange 2003 server, because &lt;br /&gt;# the whole point is to fix the items on the 2003 side so they will replicate &lt;br /&gt;# to Exchange 2007/2010. If you're not sure which replica of a folder your &lt;br /&gt;# profile is accessing, launch MFCMapi, logon to the same profile, navigate &lt;br /&gt;# to the public folder, and look at the PR_REPLICA_SERVER property. This will &lt;br /&gt;# tell you which replica your client is looking at. &lt;br /&gt;# &lt;br /&gt;# Syntax info: &lt;br /&gt;# &lt;br /&gt;# Examples: &lt;br /&gt;# .\Fix-PFItems -folderPath "Departments\HR" -splitOnBadchar $true -resetEmptyCategories $false -doAppointments $false -doInstanceKey $false -doSubfolders $false &lt;br /&gt;# .\Fix-PFItems "Departments\HR" $true $false $false $false $false &lt;br /&gt;# &lt;br /&gt;# folderPath should be in the form: "TopLevelFolder\Subfolder\Subfolder 2" &lt;br /&gt;# a folderPath of "" will run against all public folders &lt;br /&gt;# splitOnBadChar determines whether we split the category into two names, or just replace badChar &lt;br /&gt;# resetEmptyCategories will clear all categories on items that already appear to have no &lt;br /&gt;#&amp;nbsp;&amp;nbsp; categories. This ensures that the categories value is REALLY empty, and should fix &lt;br /&gt;#&amp;nbsp;&amp;nbsp; items that have an empty array in the categories. Be aware that since this changes ALL &lt;br /&gt;#&amp;nbsp;&amp;nbsp; items that appear to have no categories, it could cause a lot of replication. &lt;br /&gt;# doAppointments determines whether appointment items are processed. Note that if this is $true &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; and $commitChanges is set to $true, ALL appointment items in the specified folders &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; will be modified by the script. This will change the last modified time and cause &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; replication. &lt;br /&gt;# doInstanceKey determines whether we clear PR_INSTANCE_KEY on items. Note that if this is $true &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; and $commitChanges is set to $true, ALL items in ALL folders that you specify will be &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; be modified. &lt;br /&gt;# doSubfolders determines whether we automatically traverse subfolders of the specified folder &lt;br /&gt;# &lt;br /&gt;# This script will identify 5 types of problems: &lt;br /&gt;# &lt;br /&gt;# 1. Categories that contain a bad character, typically a comma. This error is identified in the &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; content conversion tracing by output that states: &lt;br /&gt;# &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; PropertyValidationException: Property validation failed. Property = [{GUID}:'Keywords'] &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; Categories Error = Element 0 in the multivalue property is invalid.. &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; This problem will always be fixed if $commitChanges is $true (see below). The &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; -splitOnBadChar parameter lets you choose whether to split the category into two separate &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; categories (A category such as "catone,cattwo" would become two separate categories &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; "catone" and "cattwo") or to simply get rid of the bad character ("catone,cattwo" becomes &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; "catonecattwo"). &lt;br /&gt;# &lt;br /&gt;# 2. Categories that contain an emtpy array. This problem is identified by the same tracing &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; output as that shown for problem #1. This problem can be fixed if -resetEmptyCategories &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; is $true and $commitChanges is changed to $true (see below). Note that this will modify &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; all items that appear to have no categories, as the script can't tell the difference &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; between an empty array and an item that truly has no categories. &lt;br /&gt;# &lt;br /&gt;# 3. Appointment items with invalid start/end dates. This problem can be fixed if $doAppointments &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; is $true and $commitChanges is changed to $true. See below. Note that this does not fix &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; every possible problem with appointments. &lt;br /&gt;# &lt;br /&gt;# 4. Address type properties that are longer than 9 characters. This problem can be identified &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; by content conversion tracing that states: &lt;br /&gt;# &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; Property validation failed. Property = [{GUID}:0x8nnn] Email2AddrType Error = &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; Email2AddrType is too long: maximum length is 9, actual length is nn.. &lt;br /&gt;# &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; This problem cannot be fixed by the script. You can try to fix it manually using &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; mfcmapi, but sometimes these properties cannot be changed and the item &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; must be deleted. &lt;br /&gt;# &lt;br /&gt;# 5. A bad PR_INSTANCE_KEY. This problem can be identified by an error in the &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; content conversion tracing that says MapiExceptionPropsDontMatch. This problem can &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; be fixed by the script if -doInstanceKey is $true and $commitChanges is $true (see &lt;br /&gt;#&amp;nbsp;&amp;nbsp;&amp;nbsp; below). &lt;br /&gt;# &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;param([string]$folderPath, [bool]$splitOnBadchar, [bool]$resetEmptyCategories, [bool]$doAppointments, [bool]$doInstanceKey, [bool]$doSubfolders) &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# &lt;br /&gt;# By default, the script does NOT change anything. You must &lt;br /&gt;# change $commitChanges to $true in order for the script to actually &lt;br /&gt;# do anything. &lt;br /&gt;# &lt;br /&gt;# This has the potential to change a lot of items in your public folders! &lt;br /&gt;# Run it in READ ONLY mode first to see what will get changed, and have a &lt;br /&gt;# good backup just in case! &lt;br /&gt;# &lt;br /&gt;$commitChanges = $false &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# $badChar is the character we want to get rid of in the category names. &lt;br /&gt;# Normally it's a comma, but it can be changed to anything you want. &lt;br /&gt;$badChar = "," &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# $reportAll will make the script report all categories and address types &lt;br /&gt;# that were found. This is just for reporting purposes so you can see what values &lt;br /&gt;# exist. &lt;br /&gt;$reportAll = $false &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# &lt;br /&gt;########################################################################## &lt;br /&gt;# &lt;br /&gt;# Be careful changing anything below this point. &lt;br /&gt;# &lt;br /&gt;########################################################################## &lt;br /&gt;# &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$allCategories = new-object System.Collections.Specialized.StringCollection &lt;br /&gt;$allAddressTypes = new-object System.Collections.Specialized.StringCollection &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function GetNamedFromCollection($name, $collection) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $collection) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Name -eq $name -or $item.DisplayName -eq $name) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $item &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return $null &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function RecordAddrType($type) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($reportAll) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!($allAddressTypes.Contains($type))) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $temp = $allAddressTypes.Add($type) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoCategories($item) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $categoryArray = $item.PropertyAccessor.GetProperty("urn:schemas-microsoft-com:office:office#Keywords") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($categoryArray.Length -eq 0 -and $resetEmptyCategories -eq $true) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($commitChanges) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp; Resetting categories..." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.PropertyAccessor.SetProperty("urn:schemas-microsoft-com:office:office#Keywords", $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Save() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp; Would have reset the categories, but we're in Read-Only mode." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $fixedCategories = $false &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string[]]$newCategoryArray = @() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($cat in $categoryArray) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($reportAll) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!($allCategories.Contains($cat))) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $temp = $allCategories.Add($cat) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($cat.Contains($badChar)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!($splitOnBadchar)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # In this case, we just replace the badChar with nothing &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newCategoryArray += $cat.Replace($badChar, "") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # In this case, we split it into multiple separate categories &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $categorySplit = $cat.Split($badChar) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($newCat in $categorySplit) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newCat = $newCat.Trim() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($newCat.Length -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newCategoryArray += $newCat &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $fixedCategories = $true &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elseif ($cat.Trim() -eq "") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # this category should be deleted from the item &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $fixedCategories = $true &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newCategoryArray += $cat &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($fixedCategories) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp; Old category list for this item:" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($cat in $categoryArray) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; " + $cat) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp; New category list for this item:" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($cat in $newCategoryArray) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; " + $cat) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($commitChanges) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.PropertyAccessor.SetProperty("urn:schemas-microsoft-com:office:office#Keywords", $newCategoryArray) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Save() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Changes saved.") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Changes not saved (READ ONLY mode).") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoAppointmentProps($item) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Class -eq 26) # olAppointment in the olObjectClass enumeration is 26 &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($commitChanges) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Updating appointment props: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.IsRecurring) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $recurPattern = $item.GetRecurrencePattern() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $recurPattern.StartTime = $recurPattern.StartTime &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $recurPattern.EndTime = $recurPattern.EndTime &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Save() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Start = $item.Start &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.End = $item.End &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Save() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Appointment props not updated (READ ONLY mode).") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoInstanceKey($item) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($commitChanges) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Clearing PR_INSTANCE_KEY: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.PropertyAccessor.DeleteProperty("&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/mapi/proptag/0x0FF60102&amp;quot;)"&gt;http://schemas.microsoft.com/mapi/proptag/0x0FF60102")&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $item.Save() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Changes saved.") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; PR_INSTANCE_KEY not cleared (READ ONLY mode).") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoAddrType($item) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $senderAddrType = $item.PropertyAccessor.GetProperty("&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/mapi/proptag/0x0C1E001E&amp;quot;)"&gt;http://schemas.microsoft.com/mapi/proptag/0x0C1E001E")&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RecordAddrType $senderAddrType &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($senderAddrType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! PR_SENDER_ADDRTYPE is too long: " + $senderAddrType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $sentRepresentingAddrType = $item.PropertyAccessor.GetProperty("&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/mapi/proptag/0x0064001E&amp;quot;)"&gt;http://schemas.microsoft.com/mapi/proptag/0x0064001E")&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RecordAddrType $sentRepresentingAddrType &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($sentRepresentingAddrType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! PR_SENT_REPRESENTING_ADDRTYPE is too long: " + $sentRepresentingAddrType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $recipients = $item.Recipients &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($recipients -ne $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($recipient in $recipients) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $addrType = $recipient.PropertyAccessor.GetProperty("&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/mapi/proptag/0x3002001E&amp;quot;)"&gt;http://schemas.microsoft.com/mapi/proptag/0x3002001E")&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($addrType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! A recipient PR_ADDRTYPE is too long: " + $addrType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email1AddressType.Length -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RecordAddrType $item.Email1AddressType &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email1AddressType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! Email1AddressType is too long: " + $item.Email1AddressType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email2AddressType.Length -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RecordAddrType $item.Email2AddressType &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email2AddressType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! Email2AddressType is too long: " + $item.Email2AddressType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email3AddressType.Length -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RecordAddrType $item.Email3AddressType &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.Email3AddressType.Length -gt 9) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; WARNING! Email3AddressType is too long: " + $item.Email3AddressType) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;function DoFolder($folder) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $replicaServer = $folder.PropertyAccessor.GetProperty("&lt;/span&gt;&lt;a href="http://schemas.microsoft.com/mapi/proptag/0x6644001E&amp;quot;)"&gt;http://schemas.microsoft.com/mapi/proptag/0x6644001E")&lt;/a&gt; &lt;br /&gt;&lt;span style="color: #0000ff;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $items = $folder.Items &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ($items.Count.ToString() + " items found in folder " + $folder.FolderPath) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Accessing this folder on server: " + $replicaServer) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($item in $items) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Checking item: " + $item.Subject) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($item.PropertyAccessor -ne $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoCategories($item) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoAddrType($item) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($doAppointments) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoAppointmentProps($item) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($doInstanceKey) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoInstanceKey($item) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "&amp;nbsp;&amp;nbsp;&amp;nbsp; No PropertyAccessor on this item. It may be in a conflict state." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($doSubfolders) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($subfolder in $folder.Folders) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DoFolder($subfolder) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;"Starting..." &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;if ($commitChanges) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "commitChanges has been set to TRUE. The script WILL save changes." &lt;br /&gt;} &lt;br /&gt;else &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "commitChanges is set to FALSE. Running in READ ONLY mode. Changes will NOT be saved." &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$outlook = new-object -com Outlook.Application &lt;br /&gt;if (!($outlook.Version -like "12.*" -or $outlook.Version -like "14.*")) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("This script requires Outlook 2007 or 2010. Your version: " + $outlook.Version) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;} &lt;br /&gt;$mapi = $outlook.GetNamespace("MAPI") &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# &lt;br /&gt;# First, check the categories list and fix if necessary &lt;br /&gt;# &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;"Checking Outlook categories list..." &lt;br /&gt;$categories = $mapi.Categories &lt;br /&gt;foreach ($category in $categories) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($category.Name -ne $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($category.Name.Contains($badChar)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [string[]]$newNames = @() &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("&amp;nbsp;&amp;nbsp;&amp;nbsp; Fixing category in Outlook category list: " + $category.Name) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!($splitOnBadchar)) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # In this case, we just replace the badChar with nothing &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newName += $category.Name.Replace($badChar, "") &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; # In this case, we split it into multiple separate categories &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $categorySplit = $category.Name.Split($badChar) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($newCat in $categorySplit) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($newCat.Length -gt 0) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $newNames += $newCat &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($commitChanges) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $foo = $categories.Remove($category.Name) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach ($newName in $newNames) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $foo = $categories.Add($newName) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# &lt;br /&gt;# Categories list should be in good shape now. &lt;br /&gt;# Now find the specified folder. &lt;br /&gt;# &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;"Finding the specified folder..." &lt;br /&gt;$session = $mapi.Session &lt;br /&gt;$pfStore = $null &lt;br /&gt;foreach ($store in $mapi.Stores) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($store.ExchangeStoreType -eq 2) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $pfStore = $store &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;}&lt;br /&gt;$pfRoot = $pfStore.GetRootFolder()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #0000ff;"&gt;$allPFs = GetNamedFromCollection "All Public Folders" $pfRoot.Folders &lt;br /&gt;if ($allPFs -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Couldn't find All Public Folders folder." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;if ($pfStore -eq $null) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Couldn't find public folder store." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;span style="color: #0000ff;"&gt;$pfRoot = $pfStore.GetRootFolder()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;$folderPath = $folderPath.Trim("\") &lt;br /&gt;$folderPathSplit = $folderPath.Split("\") &lt;br /&gt;$folder = $allPFs &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;if ($folderPath.Length -gt 0) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Traversing folder path..." &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for ($x = 0; $x -lt $folderPathSplit.Length; $x++) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $folder = GetNamedFromCollection $folderPathSplit[$x] $folder.Folders &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ($folder -eq $null) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Could not find folder: " + $folderPath) &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ("Found folder: " + $folder.FolderPath) &lt;br /&gt;} &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;# &lt;br /&gt;# Got the folder. &lt;br /&gt;# Start processing the folder and subfolders. &lt;br /&gt;# &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;DoFolder $folder &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;"Done!" &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style="color: #0000ff;"&gt;if ($reportAll) &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Categories found:" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $allCategories &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Address types found:" &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $allAddressTypes &lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3327671" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Public+Folders/">Public Folders</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Outlook+Object+Model/">Outlook Object Model</category></item><item><title>Checking For Protected ACLs In Active Directory</title><link>http://blogs.technet.com/b/bill_long/archive/2010/04/13/checking-for-protected-acls-in-active-directory.aspx</link><pubDate>Tue, 13 Apr 2010 17:43:40 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3324809</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3324809</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/04/13/checking-for-protected-acls-in-active-directory.aspx#comments</comments><description>&lt;p&gt;Exchange Server setup grants permissions to various groups at various places in the domain and configuration contexts of Active Directory. Since Exchange relies on these permissions in order for everything to work properly, from time to time we see cases where something is not working, and we eventually track it down to the fact that an object has been set to NOT inherit permissions from its parent. This is called a protected ACL, because it is protected from inheriting permissions from the parent. Here’s how this looks in Active Directory Users &amp;amp; Computers:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/CheckingForProtectedACLsInActiveDirector_B2CA/protectedacl_1.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="protectedacl" border="0" alt="protectedacl" src="http://blogs.technet.com/blogfiles/bill_long/WindowsLiveWriter/CheckingForProtectedACLsInActiveDirector_B2CA/protectedacl_thumb_1.jpg" width="660" height="556" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;You can imagine what fun it is to go hunting around, clicking through multiple dialog boxes to try and find an object where inheritance has been unchecked in the GUI.&lt;/p&gt;  &lt;p&gt;Fortunately, Powershell makes it easy to evaluate whether an ACL is protected by exposing the ObjectSecurity.AreAccessRulesProtected member on a DirectoryEntry object. This makes it relatively simple to write a script that scans the entire Active Directory for objects with protected ACLs, and I wrote just such a script a couple of months back.&lt;/p&gt;  &lt;p&gt;Be aware that it’s normal for the ACLs on certain objects to be protected, such as certain containers in the domain’s System container, as well as any user objects affected by AdminSDHolder. Don’t panic when you see that inheritance is disabled on your administrator accounts, or on the various built-in groups, or the policies in the System container, etc. That’s totally normal. From an Exchange perspective, in the domain context we’d be looking for normal users or OUs that contain users. In the configuration context we’d be looking for anything under the Microsoft Exchange container.&lt;/p&gt;  &lt;p&gt;In any case, here is the script. Read the top for usage details.&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;#################################################################################     &lt;br /&gt;#       &lt;br /&gt;# The sample scripts are not supported under any Microsoft standard support       &lt;br /&gt;# program or service. The sample scripts are provided AS IS without warranty       &lt;br /&gt;# of any kind. Microsoft further disclaims all implied warranties including, without       &lt;br /&gt;# limitation, any implied warranties of merchantability or of fitness for a particular       &lt;br /&gt;# purpose. The entire risk arising out of the use or performance of the sample scripts       &lt;br /&gt;# and documentation remains with you. In no event shall Microsoft, its authors, or       &lt;br /&gt;# anyone else involved in the creation, production, or delivery of the scripts be liable       &lt;br /&gt;# for any damages whatsoever (including, without limitation, damages for loss of business       &lt;br /&gt;# profits, business interruption, loss of business information, or other pecuniary loss)       &lt;br /&gt;# arising out of the use of or inability to use the sample scripts or documentation,       &lt;br /&gt;# even if Microsoft has been advised of the possibility of such damages      &lt;br /&gt;#      &lt;br /&gt;#################################################################################      &lt;br /&gt;#      &lt;br /&gt;# Check-Inheritance      &lt;br /&gt;#      &lt;br /&gt;# The purpose of this script is to check for Active Directory objects that are      &lt;br /&gt;# set to NOT inherit permissions from their parent. It takes four parameters,      &lt;br /&gt;# all of which are optional:      &lt;br /&gt;#      &lt;br /&gt;# $BaseDN - This is the root container where we start our search. If not specified      &lt;br /&gt;#&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; we use the root of the current domain. A DC can be specified or not.      &lt;br /&gt;# $Recurse - This determines whether we search only the root, or whether we      &lt;br /&gt;#&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; recursively go through its child containers. $false by default.      &lt;br /&gt;# $ContainersOnly - This determines if we look only at containers, or if we also      &lt;br /&gt;#&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; inspect every individual leaf object for inheritance. $false by default.      &lt;br /&gt;# $Verbose - This determines whether we log every single object we look at,       &lt;br /&gt;#&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; or whether we log only problem objects. $false by default.      &lt;br /&gt;#       &lt;br /&gt;# Examples:      &lt;br /&gt;#       &lt;br /&gt;# .\Check-Inheritance -BaseDN &amp;quot;LDAP://CN=Users,DC=contoso,DC=com&amp;quot; -Recurse $true -ContainersOnly $false -Verbose $false      &lt;br /&gt;# .\Check-Inheritance &amp;quot;LDAP://DC1/CN=Users,DC=contoso,DC=com&amp;quot; $true $false $false      &lt;br /&gt;# .\Check-Inheritance &amp;quot;LDAP://CN=Users,DC=contoso,DC=com&amp;quot;      &lt;br /&gt;# .\Check-Inheritance      &lt;br /&gt;#      &lt;br /&gt;# Output looks like this:      &lt;br /&gt;#       &lt;br /&gt;# Inheritance disabled: CN=Someobject,DC=contoso,DC=com      &lt;br /&gt;# Inheritance disabled: CN=Someotherobject,DC=contoso,DC=com      &lt;br /&gt;#       &lt;br /&gt;# If verbose is turned on, it will also report the DN of every object it looks at:      &lt;br /&gt;#      &lt;br /&gt;# CN=Object1,DC=contoso,DC=com      &lt;br /&gt;# CN=Object2,DC=contoso,DC=com      &lt;br /&gt;# Inheritance disabled: CN=Object3,DC=contoso,DC=com      &lt;br /&gt;# CN=Object4,DC=contoso,DC=com &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;param([string]$BaseDN, [bool]$Recurse, [bool]$ContainersOnly, [bool]$Verbose) &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;function DoContainer($base)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $finder = new-object System.DirectoryServices.DirectorySearcher($base, $filter, $propertyList, $scope)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $finder.PageSize = 100      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $results = $finder.FindAll()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ($results.Count -gt 0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; foreach ($result in $results)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $entry = $result.GetDirectoryEntry()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($entry.ObjectSecurity.AreAccessRulesProtected)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Inheritance disabled: &amp;quot; + $entry.distinguishedName)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; elseif ($Verbose)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $entry.distinguishedName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ($Recurse)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DoContainer $entry      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;if ($BaseDN -eq &amp;quot;&amp;quot;)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $dcRoot = [ADSI]&amp;quot;LDAP://RootDSE&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $BaseDN = (&amp;quot;LDAP://&amp;quot; + $dcRoot.dnsHostName + &amp;quot;/&amp;quot; + $dcRoot.DefaultNamingContext)      &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$filter = &amp;quot;(objectClass=*)&amp;quot;     &lt;br /&gt;if ($ContainersOnly)      &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $filter = &amp;quot;(|(objectClass=organizationalUnit)(objectClass=container))&amp;quot;      &lt;br /&gt;} &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;$propertyList = @(&amp;quot;distinguishedName&amp;quot;)     &lt;br /&gt;$scope = [System.DirectoryServices.SearchScope]::OneLevel &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;(&amp;quot;Base container: &amp;quot; + $BaseDN)     &lt;br /&gt;(&amp;quot;Recurse: &amp;quot; + $Recurse)      &lt;br /&gt;(&amp;quot;ContainersOnly: &amp;quot; + $ContainersOnly)      &lt;br /&gt;(&amp;quot;Verbose: &amp;quot; + $Verbose)      &lt;br /&gt;&amp;quot;Here we go...&amp;quot;      &lt;br /&gt;&amp;quot;&amp;quot;      &lt;br /&gt;$baseEntry = [ADSI]$BaseDN      &lt;br /&gt;DoContainer $baseEntry &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&amp;quot;Done!&amp;quot;&lt;/font&gt;&lt;/p&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3324809" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Powershell/">Powershell</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category></item><item><title>PFDAVAdmin Update Released</title><link>http://blogs.technet.com/b/bill_long/archive/2010/04/09/pfdavadmin-update-released.aspx</link><pubDate>Fri, 09 Apr 2010 17:47:00 GMT</pubDate><guid isPermaLink="false">d5e57398-b9ef-4490-9955-07cbb4e4a80d:3324194</guid><dc:creator>Bill Long [Exchange]</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.technet.com/b/bill_long/rsscomments.aspx?WeblogPostID=3324194</wfw:commentRss><comments>http://blogs.technet.com/b/bill_long/archive/2010/04/09/pfdavadmin-update-released.aspx#comments</comments><description>&lt;P&gt;As &lt;A href="http://msexchangeteam.com/archive/2010/04/09/454590.aspx" mce_href="http://msexchangeteam.com/archive/2010/04/09/454590.aspx"&gt;announced&lt;/A&gt; over on the Exchange Team Blog, an &lt;A href="http://www.microsoft.com/downloads/details.aspx?familyid=635BE792-D8AD-49E3-ADA4-E2422C0AB424" mce_href="http://www.microsoft.com/downloads/details.aspx?familyid=635BE792-D8AD-49E3-ADA4-E2422C0AB424"&gt;updated version of PFDAVAdmin&lt;/A&gt; was released to the download center a few days ago. See that post for details. This updated version has been used internally for a while, but if you notice any problems with it, let me know.&lt;/P&gt;&lt;img src="http://blogs.technet.com/aggbug.aspx?PostID=3324194" width="1" height="1"&gt;</description><category domain="http://blogs.technet.com/b/bill_long/archive/tags/Exchange+Server/">Exchange Server</category><category domain="http://blogs.technet.com/b/bill_long/archive/tags/PFDAVAdmin/">PFDAVAdmin</category></item></channel></rss>