Force Desktop, Documents, Pictures to Move to OneDrive

Modified on Mon, 8 Dec at 6:56 PM

Run this script from an Entra joined user. It will take effect on next login. The policy settings are set for all users.


# Requires administrative privileges (Run as administrator) to set HKLM registry keys.

# ==================================================================================================
#                                   DOMAIN AND TENANT ID RETRIEVAL
# ==================================================================================================

function Get-TenantIdFromDomain {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Domain
    )
    
    # Use the well-known OpenID configuration endpoint to find the Tenant ID (GUID)
    $Uri = "https://login.windows.net/$Domain/.well-known/openid-configuration"
    
    try {
        Write-Host "Attempting to retrieve Tenant ID from domain '$Domain'..."
        # Fetch the configuration document and convert to JSON object
        $Config = Invoke-WebRequest -UseBasicParsing -Uri $Uri -ErrorAction Stop | ConvertFrom-Json

        # The Tenant ID is the GUID embedded in the token_endpoint URL path
        $TokenEndpoint = $Config.token_endpoint
        
        if ($TokenEndpoint) {
            # Split the URL by '/' and take the fourth element (the GUID)
            $TenantID = $TokenEndpoint.Split('/')[3]
            Write-Host "✅ Tenant ID found: $TenantID" -ForegroundColor Green
            return $TenantID
        } else {
            Write-Warning "Could not find 'token_endpoint' in the OpenID configuration."
            return $null
        }
    } catch {
        Write-Error "Failed to retrieve OpenID configuration for domain '$Domain'. Error: $($_.Exception.Message)"
        return $null
    }
}

function Get-EntraJoinedDomain {
    # Method 1 (Preferred): Use whoami /upn to get the most accurate domain suffix
    try {
        # Execute whoami /upn and capture the output
        $UPNResult = (whoami.exe /upn) -join "`n"
        
        # Split the UPN string (e.g., user@contoso.com) by the '@' symbol
        if ($UPNResult -match "@") {
            $UPNSuffix = $UPNResult.Split("@")[-1].Trim() # Get the part after the last @ and trim whitespace
            
            # Basic validation to ensure it looks like a domain
            if ($UPNSuffix -like "*.*") {
                Write-Host "✅ Detected User Principal Name (UPN) Suffix as primary domain candidate: $UPNSuffix" -ForegroundColor Cyan
                return $UPNSuffix
            }
        }
        
    } catch {
        # Ignore errors from whoami execution, proceed to fallback
    }

    # Method 2 (Fallback): Use the computer's reported domain name
    try {
        $ComputerInfo = Get-CimInstance -ClassName Win32_ComputerSystem
        $Domain = $ComputerInfo.Domain
        
        if ($Domain) {
            Write-Host "Using machine domain as primary domain candidate (Fallback): $Domain" -ForegroundColor Cyan
            return $Domain
        }

    } catch {
        # Ignore errors from Get-CimInstance, final return $null
    }
    
    Write-Error "Could not dynamically determine the primary Entra ID domain."
    return $null
}

# 1. Dynamically get the primary domain
$M365Domain = Get-EntraJoinedDomain

if (-not $M365Domain) {
    Write-Error "Cannot proceed. Primary domain could not be determined. Script stopped."
    exit 1
}

# 2. Get the Tenant ID dynamically using the domain
$TenantID = Get-TenantIdFromDomain -Domain $M365Domain

if (-not $TenantID) {
    Write-Error "Cannot proceed. Tenant ID could not be determined. Script stopped."
    exit 1
}

# ==================================================================================================
#                                   APPLYING ONEDRIVE POLICIES
# ==================================================================================================

$RegPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"

# Ensure the registry path exists
if (-not (Test-Path $RegPath)) {
    Write-Host "Creating registry path: $RegPath"
    New-Item -Path $RegPath -Force | Out-Null
}

## Policy 1: Silently Sign In Users to OneDrive (SilentAccountConfig)
# Value: 1 (Enabled)
Write-Host "Setting policy for **Silent OneDrive Sign-In**..."
New-ItemProperty -Path $RegPath -Name "SilentAccountConfig" -Value 1 -Type DWORD -Force | Out-Null

## Policy 2: Silently Move Windows Known Folders (Desktop, Documents, Pictures) (KFMSilentOptIn)
# Value: The dynamically retrieved Tenant ID
Write-Host "Setting policy for **Known Folder Move (KFM)** for Desktop, Documents, and Pictures..."
New-ItemProperty -Path $RegPath -Name "KFMSilentOptIn" -Value $TenantID -Type String -Force | Out-Null

## Policy 3: Enable Files On-Demand (Recommended)
# Value: 1 (Enabled)
Write-Host "Setting policy to enable **Files On-Demand**..."
New-ItemProperty -Path $RegPath -Name "FilesOnDemandEnabled" -Value 1 -Type DWORD -Force | Out-Null

Write-Host "---"
Write-Host "✅ All required OneDrive policies successfully applied to the local machine." -ForegroundColor Green
Write-Host "New Entra users will automatically sign in and move Desktop, Documents, and Pictures to OneDrive."

Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article