#requires -version 5.1 # ========================================== # ONEDRIVE CLEAN UNINSTALL + SPECIFIC VERSION INSTALL # Run as Administrator (or SYSTEM) # ========================================== $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' # ========================================== # CONFIGURATION # ========================================== $Version = '25.087.0506.0001' $DownloadURL = "https://oneclient.sfx.ms/Win/Installers/$Version/amd64/OneDriveSetup.exe" $TempFolder = Join-Path $env:TEMP 'OneDriveInstall' $Installer = Join-Path $TempFolder 'OneDriveSetup.exe' $ProgramFiles64 = if ($env:ProgramW6432) { $env:ProgramW6432 } else { $env:ProgramFiles } $InstallFolder = Join-Path $ProgramFiles64 'Microsoft OneDrive' $OneDriveExe = Join-Path $InstallFolder 'OneDrive.exe' $RegistryPaths = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall' ) $MachineInstallPaths = @( $OneDriveExe, (Join-Path $env:ProgramFiles 'Microsoft OneDrive\OneDrive.exe'), (Join-Path ${env:ProgramFiles(x86)} 'Microsoft OneDrive\OneDrive.exe') ) | Where-Object { $_ } | Select-Object -Unique # ========================================== # FUNCTIONS # ========================================== function Get-OneDriveRegistration { $Results = @() foreach ($RegistryPath in $RegistryPaths) { if (Test-Path $RegistryPath) { foreach ($Key in Get-ChildItem $RegistryPath) { $App = Get-ItemProperty $Key.PSPath -ErrorAction SilentlyContinue if ($App.DisplayName -eq 'Microsoft OneDrive') { $Results += [PSCustomObject]@{ DisplayName = $App.DisplayName UninstallString = $App.UninstallString RegistryKey = $Key.PSPath } } } } } return $Results } # ========================================== # MAIN # ========================================== try { # ------------------------------------------ # Administrator check # ------------------------------------------ $IsAdmin = ([Security.Principal.WindowsPrincipal] ` [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) if (-not $IsAdmin) { throw 'Administrator privileges are required.' } Write-Host '' Write-Host '==========================================' -ForegroundColor Cyan Write-Host 'ONEDRIVE CLEAN REINSTALL' -ForegroundColor Cyan Write-Host "Target Version: $Version" -ForegroundColor Cyan Write-Host '==========================================' -ForegroundColor Cyan # ------------------------------------------ # PHASE 1 - Uninstall existing OneDrive # ------------------------------------------ Write-Host '' Write-Host 'PHASE 1: Removing existing OneDrive...' -ForegroundColor Cyan Write-Host 'Stopping OneDrive processes...' Get-Process OneDrive -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue Start-Sleep -Seconds 3 $Registrations = @(Get-OneDriveRegistration) if ($Registrations.Count -gt 0) { foreach ($Registration in $Registrations) { Write-Host "Found installation: $($Registration.DisplayName)" Write-Host "Uninstall command: $($Registration.UninstallString)" $UninstallCommand = $Registration.UninstallString if ([string]::IsNullOrWhiteSpace($UninstallCommand)) { throw 'Uninstall command is missing.' } # Parse executable and arguments if ($UninstallCommand -match '^\s*"([^"]+)"\s*(.*)$') { $Uninstaller = $Matches[1] $Arguments = $Matches[2] } elseif ($UninstallCommand -match '^\s*(\S+)\s*(.*)$') { $Uninstaller = $Matches[1] $Arguments = $Matches[2] } else { throw 'Could not parse uninstall command.' } # A previous uninstall may already have removed this entry's files if (!(Test-Path $Uninstaller)) { Write-Warning "Uninstaller no longer exists, skipping: $Uninstaller" continue } Write-Host 'Starting uninstall...' $StartParams = @{ FilePath = $Uninstaller PassThru = $true Wait = $true } if (-not [string]::IsNullOrWhiteSpace($Arguments)) { $StartParams.ArgumentList = $Arguments } $UninstallProcess = Start-Process @StartParams Write-Host "Uninstaller exit code: $($UninstallProcess.ExitCode)" if ($UninstallProcess.ExitCode -ne 0) { throw "OneDrive uninstaller returned an error (exit code $($UninstallProcess.ExitCode))." } } } else { Write-Host 'No registered machine-wide installation found.' } # ------------------------------------------ # PHASE 2 - Confirm removal # ------------------------------------------ Write-Host '' Write-Host 'PHASE 2: Confirming OneDrive removal...' -ForegroundColor Cyan $Deadline = (Get-Date).AddSeconds(120) $Removed = $false do { Start-Sleep -Seconds 5 Get-Process OneDrive -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue $Registered = @(Get-OneDriveRegistration) $FilesExist = $false foreach ($Path in $MachineInstallPaths) { if (Test-Path $Path) { $FilesExist = $true Write-Host "Remaining executable: $Path" } } if ($Registered.Count -eq 0 -and !$FilesExist) { $Removed = $true break } Write-Host 'Waiting for OneDrive removal...' } while ((Get-Date) -lt $Deadline) if (!$Removed) { throw 'OneDrive removal could not be confirmed. Reinstallation aborted.' } Write-Host 'SUCCESS: Machine-wide OneDrive installation removed.' -ForegroundColor Green # ------------------------------------------ # PHASE 3 - Download installer # ------------------------------------------ Write-Host '' Write-Host "PHASE 3: Downloading OneDrive $Version..." -ForegroundColor Cyan New-Item -Path $TempFolder -ItemType Directory -Force | Out-Null [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12 try { Write-Host 'Attempting BITS download...' Start-BitsTransfer ` -Source $DownloadURL ` -Destination $Installer ` -DisplayName "OneDrive $Version Download" ` -Description 'Downloading OneDrive installer' ` -ErrorAction Stop Write-Host 'BITS download completed.' -ForegroundColor Green } catch { Write-Warning 'BITS failed. Trying Invoke-WebRequest...' Remove-Item $Installer -Force -ErrorAction SilentlyContinue Invoke-WebRequest ` -Uri $DownloadURL ` -OutFile $Installer ` -UseBasicParsing ` -ErrorAction Stop Write-Host 'Fallback download completed.' -ForegroundColor Green } # ------------------------------------------ # PHASE 4 - Verify download # ------------------------------------------ Write-Host '' Write-Host 'PHASE 4: Verifying installer...' -ForegroundColor Cyan if (!(Test-Path $Installer)) { throw 'Installer download failed.' } $File = Get-Item $Installer if ($File.Length -lt 1MB) { throw 'Downloaded installer is unexpectedly small.' } Write-Host "Downloaded size: $([math]::Round($File.Length / 1MB, 2)) MB" $Signature = Get-AuthenticodeSignature -FilePath $Installer if ($Signature.Status -ne 'Valid' -or $Signature.SignerCertificate.Subject -notmatch 'Microsoft') { throw 'Microsoft signature verification failed. Installation aborted.' } Write-Host 'Microsoft digital signature verified.' -ForegroundColor Green # ------------------------------------------ # PHASE 5 - Install machine-wide # ------------------------------------------ Write-Host '' Write-Host "PHASE 5: Installing OneDrive $Version..." -ForegroundColor Cyan $Install = Start-Process ` -FilePath $Installer ` -ArgumentList '/allusers', '/silent' ` -Wait ` -PassThru Write-Host "Installer exit code: $($Install.ExitCode)" if ($Install.ExitCode -ne 0) { throw "OneDrive installation failed (exit code $($Install.ExitCode))." } # ------------------------------------------ # PHASE 6 - Verify installed version # ------------------------------------------ Write-Host '' Write-Host 'PHASE 6: Verifying installation...' -ForegroundColor Cyan # Wait for the executable to appear (up to 60 seconds) $InstallDeadline = (Get-Date).AddSeconds(60) while (!(Test-Path $OneDriveExe) -and (Get-Date) -lt $InstallDeadline) { Start-Sleep -Seconds 3 } if (!(Test-Path $OneDriveExe)) { throw 'OneDrive.exe not found in expected installation directory.' } $InstalledVersion = (Get-Item $OneDriveExe).VersionInfo.ProductVersion Write-Host '' Write-Host '==========================================' -ForegroundColor Cyan Write-Host 'INSTALLATION RESULTS' -ForegroundColor Cyan Write-Host '==========================================' -ForegroundColor Cyan Write-Host "Requested Version: $Version" Write-Host "Installed Version: $InstalledVersion" Write-Host "Install Location: $InstallFolder" if ($InstalledVersion -like "$Version*") { Write-Host '' Write-Host 'SUCCESS: Correct OneDrive version installed!' -ForegroundColor Green } else { throw "Version mismatch! Expected $Version but found $InstalledVersion." } Write-Host '' Write-Host '==========================================' -ForegroundColor Green Write-Host 'ONEDRIVE CLEAN REINSTALL COMPLETED' -ForegroundColor Green Write-Host "Version: $InstalledVersion" -ForegroundColor Green Write-Host '==========================================' -ForegroundColor Green $ExitCode = 0 } catch { Write-Host '' Write-Host "ERROR: $($_.Exception.Message)" -ForegroundColor Red $ExitCode = 1 } finally { # ------------------------------------------ # PHASE 7 - Cleanup (always runs) # ------------------------------------------ Write-Host '' Write-Host 'PHASE 7: Cleaning up temporary files...' -ForegroundColor Cyan Remove-Item $TempFolder -Recurse -Force -ErrorAction SilentlyContinue } exit $ExitCode