How to Enable Active Directory Recycle Bin with PowerShell

This guide provides effective instructions on how to enable Active Directory Recycle Bin with PowerShell. Accidental deletions in Active Directory (AD) are one of those scenarios that keep IT teams on edge. A misplaced click or an over-broad script can take down users, groups, or OUs in seconds. Microsoft’s Active Directory Recycle Bin dramatically reduces recovery pain by allowing you to restore deleted objects with their attributes intact—no authoritative restores, no downtime. The PowerShell script you provided streamlines enabling that feature safely and consistently, with built-in guardrails for production environments.

Background

The Active Directory Recycle Bin is a forest-wide feature that, once enabled, lets administrators reanimate deleted objects without resorting to backups. For MSPs managing many domains—or internal IT teams shepherding complex forests—standardizing how you enable this capability matters. Doing it by hand in the GUI can be error-prone and inconsistent across technicians. A PowerShell script to Enable Active Directory Recycle Bin ensures checks are run (domain controller? elevated privileges? functional levels?) and that the irreversible nature of the change is explicitly acknowledged.

This script is designed to run on a domain controller, targets Windows Server 2016+ for platform consistency, and verifies that your forest and domain functional levels meet the minimum of Windows Server 2008 R2—the Microsoft prerequisite for the Recycle Bin. It also clearly warns that the action cannot be undone, aligning with change-management best practices.

The Script

#Requires -Version 5.1

<#
.SYNOPSIS
    Enables the Active Directory Recycle Bin feature. Must be run on a domain controller. Please note this action CANNOT be undone, per Microsoft.
.DESCRIPTION
    Enables the Active Directory Recycle Bin feature. Must be run on a domain controller. Please note this action CANNOT be undone, per Microsoft.
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).

.PARAMETER ConfirmAcceptance
    Confirms acknowledgment that enabling the Active Directory Recycle Bin is a permanent action and cannot be undone. This parameter is required to proceed with enabling the recycle bin.

.EXAMPLE
    -ConfirmAcceptance

    [Info] Enabling the Active Directory Recycle Bin feature for domain 'test2.lan'.
    [Info] Successfully enabled the Active Directory Recycle Bin feature for domain 'test2.lan'.

.NOTES
    Minimum OS Architecture Supported: Windows Server 2016+
    Version: 1.0
    Release Notes: Initial Release
#>

[CmdletBinding()]
param (
    [Parameter()]
    [switch]$ConfirmAcceptance = [System.Convert]::ToBoolean($env:confirmAcceptanceActionCannotBeUndone)
)

begin {
    # Check if the operating system build version is less than 14393 (Windows Server 2016 minimum requirement)
    if ([System.Environment]::OSVersion.Version.Build -lt 14393) {
        Write-Host -Object "`n[Warning] The minimum OS version supported by this script is Windows Server 2016 (14393)."
        Write-Host -Object "[Warning] OS build '$([System.Environment]::OSVersion.Version.Build)' was detected. This could lead to errors or unexpected results.`n"
    }

    function Test-IsDomainController {
        # Determine the method to retrieve the operating system information based on PowerShell version
        try {
            $OS = if ($PSVersionTable.PSVersion.Major -lt 3) {
                Get-WmiObject -Class Win32_OperatingSystem -ErrorAction Stop
            } else {
                Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop
            }
        } catch {
            Write-Host -Object "[Error] Unable to validate whether or not this device is a domain controller."
            Write-Host -Object "[Error] $($_.Exception.Message)"
            exit 1
        }

        # Check if the ProductType is "2", which indicates that the system is a domain controller
        if ($OS.ProductType -eq "2") {
            return $true
        }
    }

    function Test-IsElevated {
        [CmdletBinding()]
        param ()

        # Get the current Windows identity of the user running the script
        $id = [System.Security.Principal.WindowsIdentity]::GetCurrent()

        # Create a WindowsPrincipal object based on the current identity
        $p = New-Object System.Security.Principal.WindowsPrincipal($id)

        # Check if the current user is in the Administrator role
        # The function returns $True if the user has administrative privileges, $False otherwise
        # 544 is the value for the Built In Administrators role
        # Reference: https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsbuiltinrole
        $p.IsInRole([System.Security.Principal.WindowsBuiltInRole]'544')
    }
}
process {
    # Attempt to determine if the current session is running with Administrator privileges.
    try {
        $IsElevated = Test-IsElevated -ErrorAction Stop
    }
    catch {
        Write-Host -Object "[Error] $($_.Exception.Message)"
        Write-Host -Object "[Error] Unable to determine if the account '$env:Username' is running with Administrator privileges."
        exit 1
    }

    if (!$IsElevated) {
        Write-Host -Object "[Error] Access Denied: The user '$env:Username' does not have administrator privileges, or the script is not running with elevated permissions."
        exit 1
    }

    # Error if not running on a domain controller
    if (-not (Test-IsDomainController)) {
        Write-Host -Object "[Error] This script must be run on a domain controller."
        exit 1
    }

    # If the user did not confirm acceptance that this action cannot be undone, exit the script
    if (-not $ConfirmAcceptance) {
        Write-Host -Object "[Error] Because this action cannot be undone, you must use the 'Confirm Acceptance' option to continue."
        Write-Host -Object "[Error] Please run this script again using the 'Confirm Acceptance' option."
        exit 1
    }

    # Get the current AD forest information
    try {
        $ForestInfo = Get-ADForest -ErrorAction Stop
    }
    catch {
        Write-Host -Object "[Error] Unable to retrieve the current Active Directory forest information."
        Write-Host -Object "[Error] $($_.Exception.Message)"
        exit 1
    }

    # Get the current AD domain information
    try {
        $DomainInfo = Get-ADDomain -ErrorAction Stop
    }
    catch {
        Write-Host -Object "[Error] Unable to retrieve the current domain name."
        Write-Host -Object "[Error] $($_.Exception.Message)"
        exit 1
    }

    # Get the domain name from the domain information
    $DomainName = $DomainInfo.DNSRoot

    if (-not $DomainName) {
        Write-Host -Object "[Error] Unable to retrieve the domain name."
        exit 1
    }

    # Check the forest and domain functional levels for Recycle Bin support
    $ForestLevel = $ForestInfo.ForestMode
    $DomainLevel = $DomainInfo.DomainMode

    if ($ForestLevel -lt 'Windows2008R2Forest' -or $DomainLevel -lt 'Windows2008R2Domain') {
        Write-Host -Object "[Error] The Active Directory Recycle Bin feature requires the forest and domain functional levels to be at least Windows Server 2008 R2."
        Write-Host -Object "[Error] The current detected levels are:"
        Write-Host -Object "Forest Level: $ForestLevel"
        Write-Host -Object "Domain Level: $DomainLevel"
        exit 1
    }

    # Get info about the Active Directory Recycle Bin feature
    try {
        $RecycleBinFeature = Get-ADOptionalFeature -Filter { Name -eq 'Recycle Bin Feature' } -ErrorAction Stop
    }
    catch {
        Write-Host -Object "[Error] Unable to retrieve information about the Active Directory Recycle Bin feature."
        Write-Host -Object "[Error] $($_.Exception.Message)"
        exit 1
    }

    # Check if the Recycle Bin feature is already enabled
    if ($RecycleBinFeature.EnabledScopes -and $RecycleBinFeature.EnabledScopes -like "*$($DomainInfo.DistinguishedName)") {
        Write-Host -Object "[Info] The Active Directory Recycle Bin feature is already enabled for domain '$DomainName'."
        exit 0
    }

    # Enable the Active Directory Recycle Bin feature
    try {
        Write-Host -Object "[Info] Enabling the Active Directory Recycle Bin feature for domain '$DomainName'."
        Enable-ADOptionalFeature -Identity $RecycleBinFeature.DistinguishedName -Scope ForestOrConfigurationSet -Target "$DomainName" -Confirm:$false -WarningAction SilentlyContinue -ErrorAction Stop
    }
    catch {
        Write-Host -Object "[Error] Failed to enable the Active Directory Recycle Bin feature."
        Write-Host -Object "[Error] $($_.Exception.Message)"
        exit 1
    }

    Write-Host -Object "[Info] Successfully enabled the Active Directory Recycle Bin feature for domain '$DomainName'."

    exit 0
}
end {
    
    
    
}

 

Detailed Breakdown

Key elements:

  • Parameter & Acknowledgment
    • -ConfirmAcceptance is a required acknowledgement. If omitted, the script aborts with a clear message.
    • The parameter defaults from the environment variable confirmAcceptanceActionCannotBeUndone. If that variable evaluates to True, the script proceeds without an interactive switch, which is handy for automation tools.
  • Platform Sanity Check
    • Warns if the OS build is below 14393 (Windows Server 2016). While AD’s Recycle Bin needs only 2008 R2 functional levels, standardizing on newer OS builds tends to reduce surprises.
  • Role and Privilege Validation
    • Test-IsElevated ensures the session is running with administrative rights (checks membership in the Built-in Administrators group).
    • Test-IsDomainController queries OS product type to confirm the script is executing on a domain controller. If not, it exits early to avoid risky remote assumptions.
  • Directory Services Prerequisites
    • Retrieves forest and domain information via Get-ADForest and Get-ADDomain (requires the ActiveDirectory module, which is present on DCs).
    • Verifies forest and domain modes are at least Windows2008R2Forest and Windows2008R2Domain.
  • Feature State Check
    • Uses Get-ADOptionalFeature -Filter { Name -eq ‘Recycle Bin Feature’ } to fetch the feature, then inspects EnabledScopes. If the current domain’s DN is already present, the script reports that Recycle Bin is enabled and exits cleanly.
  • Enablement
    • Executes Enable-ADOptionalFeature with -Scope ForestOrConfigurationSet -Target <DomainDNSRoot> -Confirm:$false.
    • Emits success output and exits with code 0.

Operational ergonomics:

  • Clear [Info], [Warning], and [Error] messages for easy log parsing.
  • Explicit exit codes (exit 0 on success, exit 1 on failure) to integrate with RMMs and CI/CD pipelines.

Potential Use Cases

Case Study: A regional MSP inherits a client with a single-forest, multi-domain deployment. The client recently suffered a helpdesk-triggered OU deletion that forced a lengthy restore from backup. The MSP standardizes a post-onboarding hardening checklist that includes How to Enable Active Directory Recycle Bin with a PowerShell script:

  1. Stage the script via the RMM (e.g., NinjaOne).
  2. Push an environment variable confirmAcceptanceActionCannotBeUndone=1 for audited acknowledgment.
  3. Schedule a maintenance task to run on each domain controller and capture output centrally.
  4. Validate success via logs and a quick test delete/restore of a lab user in a non-production OU.

The result: faster recoveries, fewer escalations, and measurable reduction in high-severity incidents.

Comparisons

  • GUI (Active Directory Administrative Center / ADAC): Click-through enablement works but is manual, less repeatable, and harder to audit across many domains.
  • Raw PowerShell one-liners: You can run Enable-ADOptionalFeature directly, but you lose the preflight validations this script provides (DC check, elevation check, functional level verification, clear acceptance).
  • Directory Services Restore (without Recycle Bin): Restores from backups are slower, riskier, and often lose some attribute fidelity. With Recycle Bin enabled, restores (Restore-ADObject) are straightforward and preserve most attributes.

In short, using a PowerShell script to Enable Active Directory Recycle Bin offers repeatability, safety checks, and better automation pipeline integration.

Implications

Enabling the Recycle Bin reduces time-to-restore and preserves object attributes, lowering risk in day-to-day operations. From a security perspective, it also tightens blast-radius control on accidental deletions and provides breathing room during incidents. You should still review retention policies and auditing; while the Recycle Bin is restorative, it’s not a substitute for least-privilege, change approvals, or regular backups. Importantly, because the feature is forest-wide, you’ll want formal change control and stakeholder notification across all domains before enabling it.

Recommendations

  • Plan and communicate: Treat this as a forest-wide change with CAB/CHG documentation.
  • Verify health first: Ensure AD replication is healthy (repadmin /replsummary) and time is in sync.
  • Run on a DC, as Admin: Let the script enforce this, and resist the urge to bypass checks.
  • Use explicit acknowledgment: Prefer the environment variable or -ConfirmAcceptance in automation so your change record shows explicit consent.
  • Log everything: Capture stdout/stderr and exit codes centrally for audit and rollback plans.
  • Test restores: After enablement, perform a controlled delete/restore in a lab OU to validate your runbook.
  • Pair with monitoring: Alert on mass deletions and privilege changes; Recycle Bin helps you recover, but prevention still matters.

Final Thoughts

For organizations looking to Enable Active Directory Recycle Bin with PowerShell, this script packages the right mix of safety checks and automation-readiness. In NinjaOne, you can deploy it as a reusable policy step: set the confirmAcceptanceActionCannotBeUndone variable in a script parameter, scope execution to domain controllers, and capture results to a shared log for compliance. Combine that with scheduled health checks and a simple “test restore” runbook, and you’ll turn a risky, one-off change into a controlled, auditable standard—exactly the kind of operational lift that pays dividends when the unexpected happens.

FAQs

No. Once the Active Directory Recycle Bin is enabled, it cannot be disabled. That’s why the script enforces explicit acceptance.

 

No server reboots are required. The change replicates through the forest as part of normal AD replication.

You must run as an administrator on a domain controller and have rights to modify forest-level features.

Forest and domain functional levels of Windows Server 2008 R2 or later. The script additionally warns if the OS is older than Windows
Server 2016 to promote consistency.

Pass -ConfirmAcceptance or set the environment variable confirmAcceptanceActionCannotBeUndone=1 before execution.

The script detects that state and exits successfully, making it safe to include in idempotent hardening baselines.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service delivery tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like