Introduction
Installing the OneDrive for Business client on a per machine basis is an often requested feature and for good reasons. OneDrive in it’s current state in the production ring, is installing into the users profile in %localappdata%, and for equally good reasons that is often not desired by enterprises.
Now, Microsoft has finally given us an option, allowing us to install OneDrive for the device into %programfiles(x86)%. The option is currently in preview and all the juicy details are found here: https://docs.microsoft.com/en-us/onedrive/per-machine-installation
PS. Credit where due: I was inspired by Per Larsen’s post on doing the same with Microsoft Intune and like many times before, this brought me to doing something on my own for the sharing and learning experience. Enjoy. 🙂
Powershell
The magic lies in the Powershell script found in the very end of the post.
The script basically comes with 2 options: Install with or without source files using the parameter -NoSourceFiles or -SourceFiles
Needless to say, using the -NoSourceFiles parameter downloads the OneDriveSetup.exe directly from Microsoft and stores it into Windows\Temp from where it also is installed.
Before installation
This is the familiar scenario where OneDrive is installed in the users profile. This is how it looks prior to the installation in my end:
After installation
And below illustration is OneDrive after the installation. Notice the desired location in %programfiles(x86)%. Lovely!
Putting to use with ConfigMgr
Using the script with ConfigMgr is straightforward. The easiest approach is obviously using a package with source files similar to below illustration:
And with that package, create a program running the actual script:
powershell.exe -ExecutionPolicy Bypass -NoLogo -NonInteractive -NoProfile -WindowStyle Hidden -File .\Migrate-OneDrivePerMachine.ps1 -NoSourceFiles
The Actual Script
Copy below loveliness and save it as Migrate-OneDrivePerMachine.ps1
The script does following in headlines:
- If used with -NoSourceFiles parameter, the script downloads the OneDriveSetup.exe from Microsoft
- Store the download into Windir\Temp
- Runs the installation from Windir\Temp
- Waits for the OneDriveSetup.exe process to complete
- Configures OneDrive to insiders update ring (needed in order to receive future updates for per machine installation)
- If used with -SourceFiles parameter, the script assumes local source files
- That means that the OneDriveSetup.exe should be put next to the script in the same directory
- And then the script does roughly the same
<# .SYNOPSIS Install a fresh Per Machine installation of OneDrive or migrate a current installation. .DESCRIPTION Install a fresh Per Machine installation of OneDrive or migrate a current installation. You have the option to download OneDrive in the minimum supported build directly from Microsoft or use local source files. The script also sets the update ring to Insiders. This is to ensure that future fixes for the Per Machine installation is applied. .NOTES Filename: Migrate-OneDrivePerMachine.ps1 Version: 1.1 Author: Martin Bengtsson Blog: www.imab.dk Twitter: @mwbengtsson #> [CmdletBinding()] param( [parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [switch]$NoSourceFiles, [parameter(Mandatory=$false)] [ValidateNotNullOrEmpty()] [switch]$SourceFiles ) # Parameters for the OneDrive installation $InstallParams = "/allusers /quiet" # Path for OneDrive.exe post installation $InstalledPath = "${env:ProgramFiles(x86)}\Microsoft OneDrive\OneDrive.exe" if ($PSBoundParameters["NoSourceFiles"]) { Write-Output "No Source Files parameter selected" # Official download URL to the minimum supported OneDrive build (19.043.0304.0003) $DownloadURL = "https://go.microsoft.com/fwlink/?linkid=2083517" # Save the OneDriveSetup.exe into C:\Windows\Temp $OneDriveSetup = "$ENV:windir\Temp\OneDriveSetup.exe" # Try downloading the OneDriveSetup.exe file try { Write-Output "Downloading OneDriveSetup.exe and saving it to $OneDriveSetup" Invoke-WebRequest -Uri $DownloadURL -OutFile $OneDriveSetup } catch { Write-Output "Error in downloading OneDriveSetup.exe" ; break } # Continue if the OneDriveSetup.exe file was downloaded if (Test-Path -Path $OneDriveSetup) { if (-NOT(Test-Path -Path $InstalledPath)) { Write-Output "OneDrive is not installed already. Installing OneDrive from $OneDriveSetup" try { # Waiting for the process here seems to wait indefinitely (OneDriveSetup.exe seems to spawn several processes) $RunInstall = Start-Process -FilePath $OneDriveSetup -PassThru -ArgumentList $InstallParams $Running = $true # Instead waiting for OneDriveSetup to complete with other means do { Write-Output "Installing OneDrive for Business. Hang on..." Start-Sleep -Seconds 10 if ((Get-Process "OneDriveSetup" -ErrorAction SilentlyContinue)) { $Running = $true } else { $Running = $false } } while ($Running -eq $true) } catch { Write-Output "Error installing OneDrive" ; break } } else { Write-Output "OneDrive seems to be installed already" } } else { Write-Output "Something is not right. OneDriveSetup.exe was not located on $OneDriveSetup" ; break } } if ($PSBoundParameters["SourceFiles"]) { Write-Output "Source Files parameter selected. Assuming OneDriveSetup exists locally" $runningDir = Split-Path -Parent $MyInvocation.MyCommand.Definition $OneDriveSetup = "OneDriveSetup.exe" if (-NOT(Test-Path -Path $InstalledPath)) { try { # Waiting for the process here seems to wait indefinitely (OneDriveSetup.exe seems to spawn several processes) $RunInstall = Start-Process -FilePath $runningDir\$OneDriveSetup -PassThru -ArgumentList $InstallParams $Running = $true # Instead waiting for OneDriveSetup to complete with other means do { Write-Output "Installing OneDrive for Business using local source files. Hang on..." Start-Sleep -Seconds 10 if ((Get-Process "OneDriveSetup" -ErrorAction SilentlyContinue)) { $Running = $true } else { $Running = $false } } while ($Running -eq $true) } catch { Write-Output "Error installing OneDrive using local source files. Please check if OneDriveSetup.exe exists in the source file folder" ; break } } else { Write-Output "OneDrive seems to be installed already" } } # Do following if OneDrive is found on the new location if (Test-Path -Path $InstalledPath) { Write-Output "OneDrive is installed locally in $InstalledPath" Write-Output "Configuring OneDrive update ring to Insiders through local registry settings" $RegistryPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" $Policy = "GPOSetUpdateRing" # Create a local policy configuring OneDrive update ring to Insiders. This is currently recommended in order to receive additional fixes try { New-ItemProperty -Path $RegistryPath -Name $Policy -Value 4 -PropertyType "DWORD" -Force | Out-Null } catch { Write-Output "Failed to make local changes to registry" } } else { Write-Output "Something is not right - OneDrive was not found in $InstalledPath" }
But what if couple user will log in to that machine?
If is stored on %appdata% – it’s assigned to one user. What if you move to program files? There will be sync conflicts?
This is a per machine installation and thus any current and future user profiles will use the installation made in programfiles. No conflicts. The application in %localappdata% will be retired for each user logging in 🙂
I couldn’t get it to work without the source files. I get an “Error in downloading OneDriveSetup.exe” message when I try running it from an Administrator Powershell cmd window. Works if I provide the exe.
Thanks for letting me know. That’s weird though. What happens when you run the download part separately? Do you have access to the URL? (https://go.microsoft.com/fwlink/?linkid=2083517) 🙂
Is there a way to hide the “Preparing OneDrive for first use.” dialog from appearing during installation? It also has an X at top right which users can click and thus make the installation fail.
We would like to deploy this to all our workstations as a ConfigMgr Application, replacing the old version which installs itself to all users separately, which is annoying especially on classroom workstations where that happens at each logon.
Hey, if you use ConfigMgr and run the installation in system context, the progress won’t display 🙂
Morning,
I am trying to roll this out via GPO using the -SourceFiles with the onedrive exe in the same folder, I have tried a bat file and also just the ps1 script, but nothing seems to happen. if i run it manually when logged it it works perfect. any ideas?
I like how thorough this script is!
But why not use the new w32 method of Intune? https://www.lieben.nu/liebensraum/2019/06/moving-to-onedrive-per-machine-mode-in-intune/
😀 Sure, you should use whatever you see fit. I like options! 😀
What if i want to uninstall the existing OneDrive application from all user profile. How can i achieve this, i tried removing it but it is not seems to be working. Could you please help.
OneDrive is a built in application in Windows 10. I don’t recommend uninstalling it. If you don’t allow your users using it, I would block it using AppLocker instead. OneDrive is meant to be there, so OneDrive would return when upgrading Windows 10 if you had it uninstalled. If you’re blocking it using AppLocker, OneDrive will remain blocked also through upgrading Windows 10.