Restoring deleted objects

To restore a deleted object, you need to know its ADS path. To get the ADS path of a deleted object, you can search in the Deleted Objects container in your directory with the help of IAdmDirectorySearcher. For example, you can find a deleted user by their user principal name.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$serviceHost = "localhost"
$managedDomain = "DC=example,DC=com"
$myFilter = "(userprincipalname=j.smith@example.com)"

# Connect to Adaxes service.
$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly($serviceHost)

# Bind to the managed domain.
$searcher = $admService.OpenObject("Adaxes://$managedDomain", $NULL, $NULL, 0)

# Specify to search deleted objects.
$searcher.Tombstone = $True

# Specify search filter.
$filter = "(&" + $myFilter + "(isDeleted=TRUE))"
$searcher.SearchFilter = $filter 

try
{
    # Execute search
    $searchResultIterator = $searcher.ExecuteSearch()
    
    # Fetch results
    $searchResults = $searchResultIterator.FetchAll()
    foreach ($searchResult in $searchResults)
    {
        Write-Host $searchResult.AdsPath
    }
}
finally
{
    # Release resources used by the search.
    $searchResultIterator.Dispose()
}
C#
using System;
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main()
    {
        const string serviceHost = "localhost";
        const string managedDomain = "DC=example,DC=com";
        const string myFilter = "(userprincipalname=j.smith@example.com)";

        // Connect to Adaxes service.
        AdmNamespace adsNS = new AdmNamespace();
        IAdmService admService = adsNS.GetServiceDirectly(serviceHost);

        // Bind to the managed domain.
        IAdmDirectorySearcher searcher = (IAdmDirectorySearcher)admService.OpenObject(
            $"Adaxes://{managedDomain}", null, null, 0);

        // Specify to search deleted objects.
        searcher.Tombstone = true;

        // Specify search filter.
        string filter = $"(&{myFilter}(isDeleted=TRUE))";
        searcher.SearchFilter = filter;

        // Execute search.
        using (IAdmSearchResultIterator results = searcher.ExecuteSearch())
        {
            foreach (IAdmSearchResult result in results.FetchAll())
            {
                Console.WriteLine(result.AdsPath);
            }
        }
    }
}

Once you have the ADS path of the object you want to restore, bind to the container where you want to restore it and call the RestoreHere method of the IAdmContainer interface.

PowerShell
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

$serviceHost = "localhost"

# Connect to Adaxes service.
$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly($serviceHost)

# Bind to the Organizational Unit where to restore.
$ouToRestoreIn = $admService.OpenObject("Adaxes://OU=Sales,DC=example,DC=com", $NULL, $NULL, 0)

# Restore the object.
$deletedObjectPath = "Adaxes://example.com/CN=John Smith" + `
    "\0ADEL:eb5feb21-e648-42ad-b86c-89d3c6807953," + `
    "CN=Deleted Objects,DC=example,DC=com"
$newRdn = $NULL
$restoreChildObjects = $FALSE
$ouToRestoreIn.RestoreHere($deletedObjectPath, $newRdn, $restoreChildObjects)
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main()
    {
        const string serviceHost = "localhost";

        // Connect to Adaxes service.
        AdmNamespace adsNS = new AdmNamespace();
        IAdmService admService = adsNS.GetServiceDirectly(serviceHost);

        // Bind to the Organizational Unit where to restore.
        IAdmContainer ouToRestoreIn = (IAdmContainer)admService.OpenObject(
            "Adaxes://OU=Sales,DC=example,DC=com", null, null, 0);

        // Restore the object.
        string deletedObjectPath = @"Adaxes://example.com/CN=John Smith" +
            @"\0ADEL:eb5feb21-e648-42ad-b86c-89d3c6807953," +
            @"CN=Deleted Objects,DC=example,DC=com";
        string newRdn = null;
        bool restoreChildObjects = false;
        ouToRestoreIn.RestoreHere(deletedObjectPath, newRdn, restoreChildObjects);
    }
}

When restoring an object, you can change its relative distinguished name (RDN). To do this, specify the new RDN as the value of the newRdn parameter of the RestoreHere method.

$newRdn = "CN=John Dowson"
$ouToRestoreIn.RestoreHere($deletedObjectPath, $newRdn, $restoreChildObjects)

To restore a deleted object along with all child objects, specify TRUE as the value of the of the restoreChildObjects parameter of the RestoreHere method.

$restoreChildObjects = $TRUE
$ouToRestoreIn.RestoreHere($deletedObjectPath, $newRdn, $restoreChildObjects)

Restoring objects to their original container

You can restore an object to the container it was deleted from. The DN of the container can obtained from the lastKnownParent property of the deleted object.

PowerShell
 [Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")
 
 $serviceHost = "localhost"

 # Connect to Adaxes service.
 $admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
 $admService = $admNS.GetServiceDirectly($serviceHost)
 
 # Get the last known parent.
 $deletedObjectPath = "Adaxes://example.com/CN=John Smith" + `
     "\0ADEL:eb5feb21-e648-42ad-b86c-89d3c6807953," + `
     "CN=Deleted Objects,DC=example,DC=com"
 $deletedObject = $admService.OpenObject($deletedObjectPath, $NULL, $NULL, 0)
 $lastKnownParentDN = $deletedObject.Get("lastKnownParent")
 
 # Bind to the Organizational Unit where to restore.
 $ouToRestoreIn = $admService.OpenObject("Adaxes://$lastKnownParentDN", $NULL, $NULL, 0)
 
 # Restore the object.
 $ouToRestoreIn.RestoreHere($deletedObjectPath, $NULL, $FALSE)
C#
using Softerra.Adaxes.Adsi;
using Softerra.Adaxes.Interop.Adsi;
using Softerra.Adaxes.Interop.Adsi.PersistentObjects;

class Program
{
    static void Main()
    {
        const string serviceHost = "localhost";

        // Connect to Adaxes service.
        AdmNamespace adsNS = new AdmNamespace();
        IAdmService admService = adsNS.GetServiceDirectly(serviceHost);

        // Get the last known parent.
        string deletedObjectPath = @"Adaxes://example.com/CN=John Smith" +
           @"\0ADEL:eb5feb21-e648-42ad-b86c-89d3c6807953," +
           @"CN=Deleted Objects,DC=example,DC=com";
        IADs deletedObject = (IADs)admService.OpenObject(deletedObjectPath, null, null, 0);
        string lastKnownParentDN = (string)deletedObject.Get("lastKnownParent");

        // Bind to the Organizational Unit where to restore.
        IAdmContainer ouToRestoreIn = (IAdmContainer)admService.OpenObject(
            $"Adaxes://{lastKnownParentDN}", null, null, 0);

        // Restore the object.
        ouToRestoreIn.RestoreHere(deletedObjectPath, null, false);
    }
}

Note

To restore deleted objects in a managed domain, the recycle bin must be enabled in that domain.

 How to check the status of the recycle bin

You can use one of the following methods to check which domains managed by Adaxes have recycle bin enabled:

  • Generate the built-in Domains with Recycle Bin disabled report.
  • Execute the following script in Windows PowerShell.
[Reflection.Assembly]::LoadWithPartialName("Softerra.Adaxes.Adsi")

# The host name of the computer where Adaxes service is installed.
$serviceHost = "localhost"

# Connect to Adaxes service.
$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly($serviceHost)

# Connect to Adaxes service.
$admNS = New-Object "Softerra.Adaxes.Adsi.AdmNamespace"
$admService = $admNS.GetServiceDirectly($serviceHost)

# Check status of recycle bin in managed domains.
$managedDomains = $admService.GetManagedDomains()
foreach ($item in $managedDomains)
{
    $domainName = $item.Name
    $domain = $admService.OpenObject("Adaxes://$domainName/rootDSE", $NULL, $NULL, 0)
    $isEnabled = $domain.Get("adm-RecycleBinEnabled")
    Write-Host "Recycle bin enabled for $domainName`: $isEnabled"
}

Requirements

Minimum required version: 2018.1

See also