Searching for Deleted Objects
For most types of objects in Active Directory and ADAM, once an instance has been deleted, it is moved to the Deleted Objects container and it becomes a tombstone. This container is not normally visible to users and by default can be searched only by administrators.
Note: Tombstones Are Limited with DirectoryEntry
When working with tombstones, it is important to note that we cannot use DirectoryEntry to modify them. Operations on tombstones require that a special control be added to the LDAP operation and DirectoryEntry does not do this.
The process to search for deleted objects is as follows.
- Using the WKGUID syntax, bind to the Deleted Objects container with the AuthenticationTypes.FastBind option.
- Specify the SearchScope.OneLevel option (Subtree will also work, but it returns the container as well).
- Use a filter with (isDeleted=TRUE), plus any other filtering criteria.
- Set the Tombstone property on DirectorySearcher to true.
Listing 5.4 shows how this might be accomplished. Note that we are binding using the WKGUID format from Chapter 3.
Listing 5.4. Searching for Deleted Items
string adsPath = "LDAP://"; //Explicitly create our SearchRoot DirectoryEntry searchRoot = new DirectoryEntry( adsPath, null, null, AuthenticationTypes.Secure | AuthenticationTypes.FastBind //use fastbind ); using (searchRoot) { DirectorySearcher ds = new DirectorySearcher( searchRoot, "(isDeleted=TRUE)" //all deleted objects ); ds.SearchScope = SearchScope.OneLevel; ds.Tombstone = true; using (SearchResultCollection src=ds.FindAll()) { Console.WriteLine("Returning {0}", src.Count); foreach (SearchResult sr in src) { Console.WriteLine(sr.Path); } } } |
While it is not strictly necessary to bind to the Deleted Objects container, it is recommended. A search similar to Listing 5.4 would work fine if binding directly to the root application or domain partition. However, it would not be as efficient, given that we know that our deleted objects will be found in the Deleted Objects container.
Reasons to Search for Deleted Objects
Most of the time, we actually do not care about deleted objects at all and are happier to ignore them. However, if we are building a custom synchronization application using a technique called change polling, we actually do need to track object deletions. The target data source generally needs to know when to delete an object from its store as well, or it is not really staying in sync!
We may also occasionally just need to find a deleted object for various administrative reasons, but the change polling application is by far the most common.