Powershell : OneDrive Best Practice's Checker

This comes from some problems. I’ve been seeing with the OneDrive client Which sometimes does not work as expected and have more excessive communication with your SYSVOL shares if not set up correctly, this can also be exacerbated if you’re also utilizing folder redirection.

Because I’ve noticed an excessive use of Windows devices mainly slide devices excessive talking to the SVSVOL - which can have a detrimental effect when you’re trying to update your policy objects.

Note : The SYSVOL for the uninitialized is the share that each domain controller has that stores group policy objects, and scripts - this is the share that your Windows devices will need to talk to every 90 minutes (my default) for group policy.

The problem statement

The combination of Folder Redirection and OneDrive, particularly in the context of modern workplace will need to ensure that best practices are being followed for both folder redirection and OneDrive.

Consider this scenario:

  • Folder Redirection policies contain "target path" settings that Windows needs to validate
  • OneDrive's Known Folder Move (KFM) feature interacts with redirected folders

When both are in play, Windows may be continuously checking policy to ensure the correct location for files which will cause the excessive SYSVOL share connections as discussed at the start of this article.

This would explain why:

  • It's specific to endpoints with user profiles (laptops and user based services)
  • Infrastructure servers (which typically don't use OneDrive or folder redirection) aren't affected
  • The locks are read-only (policy validation vs modification)

The continuous policy locks could be caused by OneDrive's Known Folder Move feature constantly validating its configuration against Group Policy.

Always review best Practices and Recommodations

Obviously, up to this point all this is reviewing best practices and hypothesis based on what I’m seeing on different servers, So the easiest way to solve this is to write a script that will analyze your set up for services that can affect this behavior and give you an output that includes a risk score.

Risk Score and Compliance Status

The risk score is very simple as it works with the compliant field, if you have a high risk item that’s compliant don’t need to worry about it., however, if you have a high risk item that’s not compliant You may wish to think to update that setting to align yourself with best practices.

If you do not have the recommended setting set, you will simply see “ Not configured” - if after review, you decide to set this value simply review the scripts to see what value should be set.

When you have successfully allowed the script to run, you can review the CSV file for the findings, when run the script looks like this on completion:


The results CSV file in my example looks like this:

"Component","Setting","CurrentValue","RecommendedValue","Impact","Status"
"Policy","KFMOptInWithWizard","Not configured",,"Low - Only affects initial setup","Checked"
"Policy","PreventKnownFolderMove","Not configured",,"High - Can conflict with folder redirection policies","Checked"
"Policy","FilesOnDemandEnabled","Not configured","1","High - Affects storage and sync behavior","Checked"
"Policy","FolderRedirectionEnabled","Not configured",,"High - Can conflict with OneDrive KFM","Checked"
"Policy","BackgroundPolicyRefresh","Not configured","90","High - Frequent refreshes increase SYSVOL access","Checked"
"Policy","UEVEnabled","Not configured",,"Medium - Can cause additional policy checks","Checked"
"Policy","DownloadBandwidthLimit","Not configured","0","Medium - Can cause frequent policy checks if set too low","Checked"
"Policy","SilentAccountConfig","Not configured","1","High - Affects initial setup and account configuration","Checked"
"Policy","DFSPollInterval","Not configured","600","Medium - Frequent polling increases network activity","Checked"
"Policy","KFMSilentOptIn","Not configured",,"High - Continuous validation if always enforced","Checked"
"Policy","OfflineFileSync","Not configured",,"Medium - Can cause continuous sync attempts","Checked"
"Folder Redirection","Desktop","\\bear.local\lee\desktop","Context Dependent","High","Standard Path"

Script : OneDriveBestPractices.ps1

# Comprehensive Policy and System Configuration Audit Script
function Get-ExtendedPolicyAudit {
    # OneDrive policies to check
    $oneDrivePolicies = @{
        # Sync Settings
        "SilentAccountConfig" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = 1
            Description = "Silently configure OneDrive accounts"
            Impact = "High - Affects initial setup and account configuration"
        }
        "FilesOnDemandEnabled" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = 1
            Description = "Enable Files On-Demand"
            Impact = "High - Affects storage and sync behavior"
        }
        "DownloadBandwidthLimit" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = 0
            Description = "Download bandwidth limit"
            Impact = "Medium - Can cause frequent policy checks if set too low"
        }
        # Known Folder Move Settings
        "KFMSilentOptIn" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = $null
            Description = "Silently move Windows known folders to OneDrive"
            Impact = "High - Continuous validation if always enforced"
        }
        "KFMOptInWithWizard" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = $null
            Description = "Show OneDrive folder move wizard"
            Impact = "Low - Only affects initial setup"
        }
        "PreventKnownFolderMove" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive"
            RecommendedValue = $null
            Description = "Prevent users from redirecting known folders"
            Impact = "High - Can conflict with folder redirection policies"
        }
    }

    # Additional System Policies to Check
    $additionalPolicies = @{
        # Folder Redirection Settings
        "FolderRedirectionEnabled" = @{
            Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
            Description = "Folder Redirection Status"
            Impact = "High - Can conflict with OneDrive KFM"
        }
        # Background Processing Settings
        "BackgroundPolicyRefresh" = @{
            Path = "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System"
            Name = "GroupPolicyRefreshTimeDC"
            RecommendedValue = 90
            Description = "Group Policy Refresh Interval"
            Impact = "High - Frequent refreshes increase SYSVOL access"
        }
        # File System Settings
        "OfflineFileSync" = @{
            Path = "HKLM:\SYSTEM\CurrentControlSet\Services\CSC\Parameters"
            Name = "FormatDatabase"
            Description = "Offline Files Status"
            Impact = "Medium - Can cause continuous sync attempts"
        }
        # UE-V Settings
        "UEVEnabled" = @{
            Path = "HKLM:\SOFTWARE\Microsoft\UEV\Agent"
            Name = "Enabled"
            Description = "User Experience Virtualization Status"
            Impact = "Medium - Can cause additional policy checks"
        }
        # DFS Client Settings
        "DFSPollInterval" = @{
            Path = "HKLM:\SYSTEM\CurrentControlSet\Services\Dfsc\Parameters"
            Name = "PKTInfoCacheLifetime"
            RecommendedValue = 600
            Description = "DFS Client Polling Interval"
            Impact = "Medium - Frequent polling increases network activity"
        }
    }
    function Get-FolderRedirectionStatus {
        $redirectedFolders = @()
        $knownFolders = @{
            "Desktop" = "{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}"
            "Documents" = "{FDD39AD0-238F-46AF-ADB4-6C85480369C7}"
            "Pictures" = "{33E28130-4E1E-4676-835A-98395C3BC3BB}"
            "Music" = "{4BD8D571-6D19-48D3-BE97-422220080E43}"
            "Videos" = "{18989B1D-99B5-455B-841C-AB7C74E4DDFC}"
        }
        foreach ($folder in $knownFolders.GetEnumerator()) {
            $path = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" -Name $folder.Key -ErrorAction SilentlyContinue
            if ($path) {
                $redirectedFolders += [PSCustomObject]@{
                    Folder = $folder.Key
                    Path = $path.$($folder.Key)
                    IsOneDrivePath = $path.$($folder.Key) -like "*OneDrive*"
                }
            }
        }
        return $redirectedFolders
    }
    function Get-SystemHealthMetrics {
        $metrics = @{
            "CPU_Usage" = (Get-Counter '\Processor(_Total)\% Processor Time' -SampleInterval 1 -MaxSamples 1).CounterSamples.CookedValue
            "Memory_Usage" = (Get-Counter '\Memory\% Committed Bytes In Use' -SampleInterval 1
MaxSamples 1).CounterSamples.CookedValue
            "Disk_Queue_Length" = (Get-Counter '\LogicalDisk(_Total)\Current Disk Queue Length' -SampleInterval 1 -MaxSamples 1).CounterSamples.CookedValue
        }
        return $metrics
    }

    function Get-NetworkConnectivityStatus {
        $networkAdapters = Get-NetAdapter | Where-Object Status -eq 'Up'
        $vpnConnections = Get-VpnConnection -AllUserConnection | Where-Object Status -eq 'Connected'
        return @{
            "ActiveAdapters" = $networkAdapters
            "VPNConnections" = $vpnConnections
        }
    }

    function Get-RunningServiceStatus {
        $relevantServices = @(
            "OneDrive Sync Service",
            "Background Tasks Infrastructure Service",
            "Group Policy Client",
            "Windows Search",
            "Offline Files",
            "Distributed File System"
        )     
        $serviceStatus = Get-Service | Where-Object { $_.DisplayName -in $relevantServices }
        return $serviceStatus
    }
    function Test-ConfigurationConflicts {
        param (
            [Parameter(Mandatory=$true)]
            [object[]]$ConfigData
        )
        $warnings = @()
        $criticalIssues = @()

        # Check for OneDrive KFM and Folder Redirection coexistence

        $oneDriveKFM = $ConfigData | Where-Object { $_.Setting -eq "KFMSilentOptIn" -and $_.CurrentValue -eq 1 }
        $folderRedirection = $ConfigData | Where-Object { 
            $_.Component -eq "Folder Redirection" -and 
            $_.CurrentValue -notlike "*OneDrive*" -and 
            $_.CurrentValue -ne "Default"
        }
        if ($oneDriveKFM -and $folderRedirection) {
            $criticalIssues += [PSCustomObject]@{
                Severity = "Critical"
                Issue = "Conflicting folder management policies detected"
                Description = "Both OneDrive Known Folder Move and traditional Folder Redirection are enabled"
                Recommendation = "Choose either OneDrive KFM or Folder Redirection, not both"
                AffectedPaths = ($folderRedirection | ForEach-Object { $_.Setting }) -join ", "
            }
        }

        # Check for mixed redirection paths
        $mixedPaths = $ConfigData | Where-Object { 
            $_.Component -eq "Folder Redirection" -and 
            ($_.CurrentValue -like "*OneDrive*" -or $_.CurrentValue -like "\\*")
        }       
        if ($mixedPaths) {
            $warnings += [PSCustomObject]@{
                Severity = "High"
                Issue = "Mixed folder redirection paths detected"
                Description = "Some folders using OneDrive, others using traditional redirection"
                Recommendation = "Standardize on either OneDrive or traditional folder redirection"
                AffectedPaths = ($mixedPaths | ForEach-Object { "$($_.Setting): $($_.CurrentValue)" }) -join ", "
            }
        }

        # All other checks from previous script
        $offlineFiles = $ConfigData | Where-Object { $_.Setting -eq "OfflineFileSync" -and $_.CurrentValue -eq 1 }
        $oneDriveEnabled = $ConfigData | Where-Object { $_.Setting -eq "FilesOnDemandEnabled" -and $_.CurrentValue -eq 1 }
        if ($offlineFiles -and $oneDriveEnabled) {
            $warnings += [PSCustomObject]@{
                Severity = "High"
                Issue = "Redundant offline file configurations"
                Description = "Both Windows Offline Files and OneDrive Files On-Demand are enabled"
                Recommendation = "Disable Windows Offline Files when using OneDrive Files On-Demand"
                AffectedPaths = "System-wide setting"
            }
        }
        $redirectedFolders = ($ConfigData | Where-Object { $_.Component -eq "Folder Redirection" }).Count
        if ($redirectedFolders -gt 3 -and $oneDriveEnabled) {
            $warnings += [PSCustomObject]@{
                Severity = "Medium"
                Issue = "High number of redirected folders with OneDrive"
                Description = "Multiple redirected folders may cause excessive sync load"
                Recommendation = "Consider reducing number of redirected folders or implementing selective sync"
                AffectedPaths = "Multiple folders"
            }
        }
        return @($criticalIssues + $warnings)
    }

    # Main Execution
    $results = @()
    $errors = @()

    # Check all policies
    $allPolicies = $oneDrivePolicies + $additionalPolicies
    foreach ($policy in $allPolicies.GetEnumerator()) {
        try {
            $currentValue = Get-ItemProperty -Path $policy.Value.Path -Name $policy.Key -ErrorAction SilentlyContinue
            $results += [PSCustomObject]@{
                Component = "Policy"
                Setting = $policy.Key
                CurrentValue = if ($currentValue) { $currentValue.$($policy.Key) } else { "Not configured" }
                RecommendedValue = $policy.Value.RecommendedValue
                Impact = $policy.Value.Impact
                Status = "Checked"
            }
        }
        catch {
            $errors += "Failed to check $($policy.Key): $_"
        }
    }

    # Get all other status checks
    $redirectionStatus = Get-FolderRedirectionStatus
    $healthMetrics = Get-SystemHealthMetrics
    $networkStatus = Get-NetworkConnectivityStatus
    $serviceStatus = Get-RunningServiceStatus

    # Add all results to main results array
    $results += $redirectionStatus | ForEach-Object {
        [PSCustomObject]@{
            Component = "Folder Redirection"
            Setting = $_.Folder
            CurrentValue = $_.Path
            RecommendedValue = "Context Dependent"
            Impact = "High"
            Status = if ($_.IsOneDrivePath) { "OneDrive Path" } else { "Standard Path" }
        }
    }

    # Process conflicts
    $conflictAnalysis = Test-ConfigurationConflicts -ConfigData $results

    # Output to screen
    if ($conflictAnalysis) {
        Write-Host "`nConfiguration Issues Detected:" -ForegroundColor Red
        foreach ($issue in $conflictAnalysis) {
            Write-Host "`n[$($issue.Severity)] $($issue.Issue)" -ForegroundColor $(
                if ($issue.Severity -eq "Critical") { "Red" } else { "Yellow" }
            )
            Write-Host "Description: $($issue.Description)"
            Write-Host "Recommendation: $($issue.Recommendation)"
            if ($issue.AffectedPaths -ne "N/A") {
                Write-Host "Affected Items: $($issue.AffectedPaths)"
            }
        }
    }

    # Export results
    $timestamp = Get-Date -Format "yyyyMMdd_HHmmss"   

    # Export configuration data
    $results | Export-Csv -Path "SystemConfiguration_$timestamp.csv" -NoTypeInformation   

    # Export conflict analysis to separate CSV
    if ($conflictAnalysis) {
        $conflictAnalysis | Export-Csv -Path "ConfigurationIssues_$timestamp.csv" -NoTypeInformation
        Write-Host "`nResults exported to:"
        Write-Host "- SystemConfiguration_$timestamp.csv"
        Write-Host "- ConfigurationIssues_$timestamp.csv"
    } else {
        Write-Host "`nNo configuration issues detected. System configuration exported to:"
        Write-Host "- SystemConfiguration_$timestamp.csv"
    }
    return $results
}

# Run the audit
Get-ExtendedPolicyAudit

Previous Post Next Post

نموذج الاتصال