O4BClientAutoConfig.ps1 26.1 KB
Newer Older
1 2 3 4
#Module name:      O4BClientAutoConfig
#Author:           Jos Lieben (OGD)
#Author Company:   OGD (http://www.ogd.nl)
#Author Blog:      http://www.lieben.nu
5
#Date:             13-02-2018
6
#Purpose:          Configure Onedrive for Business (Onedrive.exe) to silently link to the user's business tenant, and optionally redirect known folders to desired subfolders
7 8
#Requirements:     Windows 10
#Instructions:     http://www.lieben.nu/liebensraum/o4bclientautoconfig/
9

Jos Lieben's avatar
Jos Lieben committed
10 11 12 13 14 15 16
#Mentions / articles used:
#@Per Larsen for writing on silent auto config: https://osddeployment.dk/2017/12/18/how-to-silently-configure-onedrive-for-business-with-intune/
#@Aaron Parker for writing on folder redirection using Powershell: https://stealthpuppy.com/onedrive-intune-folder-redirection
#https://support.office.com/en-us/article/Use-Group-Policy-to-control-OneDrive-sync-client-settings-0ecb2cf5-8882-42b3-a6e9-be6bda30899c
#https://support.office.com/en-us/article/deploy-the-new-onedrive-sync-client-in-an-enterprise-environment-3f3a511c-30c6-404a-98bf-76f95c519668
#http://www.lieben.nu/liebensraum/o4bclientautoconfig/

17
#REQUIRED CONFIGURATION:
18
$redirectFoldersToOnedriveForBusiness = $True #if enabled, the next array needs to be configured as well
19
$enableFilesOnDemand = $True #Needs Windows 10 1709 or higher
20
$listOfFoldersToRedirectToOnedriveForBusiness = @(#One line for each folder you want to redirect. For knownFolderInternalName choose from Get-KnownFolderPath function, for knownFolderInternalIdentifier choose from Set-KnownFolderPath function
21 22 23
    @{"knownFolderInternalName" = "Desktop";"knownFolderInternalIdentifier"="Desktop";"desiredSubFolderNameInOnedrive"="Desktop";"copyContents"="false"},#use copyContents with caution! Could take a long time and does not resist a reboot
    @{"knownFolderInternalName" = "MyDocuments";"knownFolderInternalIdentifier"="Documents";"desiredSubFolderNameInOnedrive"="My Documents";"copyContents"="true"},
    @{"knownFolderInternalName" = "MyPictures";"knownFolderInternalIdentifier"="Pictures";"desiredSubFolderNameInOnedrive"="My Pictures";"copyContents"="false"} #note that the last entry does NOT end with a comma
24 25 26
)

#OPTIONAL CONFIGURATION:
Jos Lieben's avatar
Jos Lieben committed
27
$xmlDownloadURL = "https://g.live.com/1rewlive5skydrive/ODSUInsider"
28
$minimumOfflineVersionRequired = 17
Jos Lieben's avatar
Jos Lieben committed
29
$temporaryInstallerPath = Join-Path $Env:TEMP -ChildPath "OnedriveInstaller.EXE"
30 31
$logFileX64 = Join-Path $Env:TEMP -ChildPath "OnedriveAutoConfigx64.log"
$logFileX86 = Join-Path $Env:TEMP -ChildPath "OnedriveAutoConfigx86.log"
Jos Lieben's avatar
Jos Lieben committed
32

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
#Restart self in x64
If (!([Environment]::Is64BitProcess)){ 
    Start-Transcript -Path $logFileX86
    if([Environment]::Is64BitOperatingSystem){
        Write-Output "Running 32 bit Powershell on 64 bit OS, restarting as 64 bit process..."
        $arguments = "-NoProfile -ExecutionPolicy ByPass -WindowStyle Hidden -File `"" + $myinvocation.mycommand.definition + "`""
        $path = (Join-Path $Env:SystemRoot -ChildPath "\sysnative\WindowsPowerShell\v1.0\powershell.exe")
        Start-Process $path -ArgumentList $arguments -Verb Open -Wait
        Write-Output "finished x64 version of PS"
        Stop-Transcript
        Exit
    }else{
        Write-Output "Running 32 bit Powershell on 32 bit OS"
    }
}else{
    Start-Transcript -Path $logFileX64
}
Jos Lieben's avatar
Jos Lieben committed
50

51
#CREATE SILENT RUNNER (SO USER DOESN'T SEE A PS WINDOW)
52
$desiredBootScriptFolder = Join-Path $Env:ProgramData -ChildPath "Lieben.nu"
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
$vbsSilentPSRunner = "
Dim objShell,objFSO,objFile

Set objShell=CreateObject(`"WScript.Shell`")
Set objFSO=CreateObject(`"Scripting.FileSystemObject`")

strPath=WScript.Arguments.Item(0)

If objFSO.FileExists(strPath) Then
    set objFile=objFSO.GetFile(strPath)
    strCMD=`"powershell -nologo -executionpolicy ByPass -command `" & Chr(34) & `"&{`" &_
     objFile.ShortPath & `"}`" & Chr(34) 
    objShell.Run strCMD,0
Else
    WScript.Echo `"Failed to find `" & strPath
    WScript.Quit
End If
"
71
$desiredBootScriptPath = Join-Path $desiredBootScriptFolder -ChildPath "O4BClientAutoConfig.ps1"
72
$desiredVBSScriptPath = Join-Path $desiredBootScriptFolder -ChildPath "O4BClientAutoConfig.vbs"
73 74 75 76 77

if(![System.IO.Directory]::($desiredBootScriptFolder)){
    New-Item -Path $desiredBootScriptFolder -Type Directory -Force
}

78 79
$vbsSilentPSRunner | Out-File $desiredVBSScriptPath -Force

80
#ENSURE CONFIG REGISTRY KEYS ARE CREATED
Jos Lieben's avatar
Jos Lieben committed
81
try{
82
    Write-Output "Adding registry keys for Onedrive"
83
    $res = New-Item -Path "HKLM:\Software\Policies\Microsoft\Onedrive" -Confirm:$False -ErrorAction SilentlyContinue
84
    $res = New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Onedrive" -Name SilentAccountConfig -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
85 86
    if($enableFilesOnDemand){
        $res = New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Onedrive" -Name FilesOnDemandEnabled -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
87 88
    }else{
        $res = New-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Onedrive" -Name FilesOnDemandEnabled -Value 0 -PropertyType DWORD -Force -ErrorAction Stop
89
    }
90
    Write-Output "Registry keys for Onedrive added"
Jos Lieben's avatar
Jos Lieben committed
91
}catch{
92 93
    Write-Error "Failed to add Onedrive registry keys, installation may not be consistent" -ErrorAction Continue
    Write-Error $_ -ErrorAction Continue
Jos Lieben's avatar
Jos Lieben committed
94 95
}

96 97 98 99 100 101 102 103 104 105
#REGISTER SCRIPT TO RUN AT LOGON
$wscriptPath = Join-Path $env:SystemRoot -ChildPath "System32\wscript.exe"
$fullRunPath = "$wscriptPath `"$desiredVBSScriptPath`" `"$desiredBootScriptPath`""
try{
    Write-Output "Adding logon registry key"
    New-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Run" -Name OnedriveAutoConfig -Value $fullRunPath -PropertyType String -Force -ErrorAction Stop
    Write-Output "logon registry key added"
}catch{
    Write-Error "Failed to add logon registry keys, user config will likely fail" -ErrorAction Continue
    Write-Error $_ -ErrorAction Continue
Jos Lieben's avatar
Jos Lieben committed
106 107
}

108
# Create a scheduled task to run the script once
109
$action = New-ScheduledTaskAction -Execute $wscriptPath -Argument "`"$desiredVBSScriptPath`" `"$desiredBootScriptPath`""
110
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Compatibility Win8
111
$principal = New-ScheduledTaskPrincipal -GroupId S-1-5-32-545
112
$task = New-ScheduledTask -Action $action -Settings $settings -Principal $principal
113 114
Register-ScheduledTask -InputObject $task -TaskName "OnedriveAutoConfig"

115
$localScriptContent = "
116 117 118 119 120 121 122
#Module name:      O4BClientAutoConfig
#Author:           Jos Lieben (OGD)
#Author Company:   OGD (http://www.ogd.nl)
#Author Blog:      http://www.lieben.nu
#Date:             12-02-2018
#Purpose:          Configure Onedrive for Business (Onedrive.exe) to silently link to the user's business tenant, and optionally redirect known folders to desired subfolders
#Requirements:     Windows 10, Powershell script should run as an Admin if O4B wasn't installed yet
123 124 125
`$redirectFoldersToOnedriveForBusiness = `$$redirectFoldersToOnedriveForBusiness
`$listOfFoldersToRedirectToOnedriveForBusiness = @("
$listOfFoldersToRedirectToOnedriveForBusiness | % {
126
        $localScriptContent += "@{`"knownFolderInternalName`"=`"$($_.knownFolderInternalName)`";`"knownFolderInternalIdentifier`"=`"$($_.knownFolderInternalIdentifier)`";`"desiredSubFolderNameInOnedrive`"=`"$($_.desiredSubFolderNameInOnedrive)`";`"copyContents`"=`"$($_.copyContents)`"},"
127 128 129 130
}
$localScriptContent = $localScriptContent -replace ".$"
$localScriptContent += ")
`$logFile = Join-Path `$Env:TEMP -ChildPath `"OnedriveAutoConfig.log`"
131 132 133
`$xmlDownloadURL = `"$xmlDownloadURL`"
`$temporaryInstallerPath = `"$temporaryInstallerPath`"
`$minimumOfflineVersionRequired = `"$minimumOfflineVersionRequired`"
134
`$onedriveRootKey = `"HKCU:\Software\Microsoft\OneDrive\Accounts\Business`"
135 136 137 138
`$desiredBootScriptFolder = `"$desiredBootScriptFolder`"
`$desiredBootScriptPath = `"$desiredBootScriptPath`"
Start-Transcript -Path `$logFile

Jos Lieben's avatar
Jos Lieben committed
139 140
#ENSURE CONFIG REGISTRY KEYS ARE CREATED
try{
141
    Write-Output `"Adding registry keys for Onedrive`"
142
    `$res = New-Item -Path `"HKCU:\Software\Microsoft\Onedrive`" -Confirm:`$False -ErrorAction SilentlyContinue
143 144 145 146
    `$res = New-ItemProperty -Path `"HKCU:\Software\Microsoft\Onedrive`" -Name DefaultToBusinessFRE -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
    `$res = New-ItemProperty -Path `"HKCU:\Software\Microsoft\Onedrive`" -Name DisablePersonalSync -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
    `$res = New-ItemProperty -Path `"HKCU:\Software\Microsoft\Onedrive`" -Name EnableEnterpriseTier -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
    `$res = New-ItemProperty -Path `"HKCU:\Software\Microsoft\Onedrive`" -Name EnableADAL -Value 1 -PropertyType DWORD -Force -ErrorAction Stop
147
    Write-Output `"Registry keys for Onedrive added`"
Jos Lieben's avatar
Jos Lieben committed
148
}catch{
149 150
    Write-Error `"Failed to add Onedrive registry keys, installation may not be consistent`" -ErrorAction Continue
    Write-Error `$_ -ErrorAction Continue
Jos Lieben's avatar
Jos Lieben committed
151 152
}

153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
function returnEnclosedValue{
    Param(
        [Parameter(Mandatory = `$True)]`$sourceString,
        [Parameter(Mandatory = `$True)]`$searchString
    )
    try{
        `$endString = `"```"`"
        `$start = `$searchString
        `$startLoc = `$sourceString.IndexOf(`$start)+`$start.Length
        if(`$startLoc -eq `$start.Length-1){
            Throw `"Not Found`"
        }
        `$searchLength = `$sourceString.IndexOf(`$endString,`$startLoc)-`$startLoc
        if(`$searchLength -eq `$startLoc-1){
            Throw `"Not Found`"
        }
        return(`$sourceString.Substring(`$startLoc,`$searchLength))
    }catch{Throw}
}

function runProcess (`$cmd, `$params, `$windowStyle=1) {
    `$p = new-object System.Diagnostics.Process
    `$p.StartInfo = new-object System.Diagnostics.ProcessStartInfo
    `$exitcode = `$false
    `$p.StartInfo.FileName = `$cmd
    `$p.StartInfo.Arguments = `$params
    `$p.StartInfo.UseShellExecute = `$False
    `$p.StartInfo.RedirectStandardError = `$True
    `$p.StartInfo.RedirectStandardOutput = `$True
    `$p.StartInfo.WindowStyle = `$windowStyle; #1 = hidden, 2 =maximized, 3=minimized, 4=normal
    `$null = `$p.Start()
    `$output = `$p.StandardOutput.ReadToEnd()
    `$exitcode = `$p.ExitCode
    `$p.Dispose()
    `$exitcode
    `$output
}

`$isOnedriveUpToDate = `$False
#GET ONLINE VERSION INFO
try{
    `$xmlInfo = Invoke-WebRequest -UseBasicParsing -Uri `$xmlDownloadURL -Method GET
    `$version = returnEnclosedValue -sourceString `$xmlInfo.Content -searchString `"currentversion=```"`"
    `$downloadURL = returnEnclosedValue -sourceString `$xmlInfo.Content -searchString `"url=```"`"
    write-output `"Microsoft's XML shows the latest Onedrive version is `$version and can be downloaded from `$downloadURL`"
}catch{
    write-error `"Failed to download / read version info for Onedrive from `$xmlDownloadURL`" -ErrorAction Continue
    write-error `$_ -ErrorAction Continue
}

203 204
#GET LOCAL INSTALL STATUS AND VERSION
try{
205
    `$installedVersion = (Get-ItemProperty -Path `"HKCU:\Software\Microsoft\OneDrive`" -Name `"Version`" -ErrorAction Stop).Version
206
    `$installedVersionPath = (Get-ItemProperty -Path `"HKCU:\Software\Microsoft\OneDrive`" -Name `"OneDriveTrigger`" -ErrorAction Stop).OneDriveTrigger
207 208 209 210 211 212 213
    Write-Output `"Detected `$installedVersion in registry`"
    if(`$installedVersion -le `$minimumOfflineVersionRequired -or (`$version -and `$version -gt `$installedVersion)){
        Write-Output `"Onedrive is not up to date!`"
    }else{
        `$isOnedriveUpToDate = `$True
        Write-Output `"Installed version of Onedrive is newer or the same as advertised version`"
    }
214
}catch{
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    write-error `"Failed to read Onedrive version information from the registry, assuming Onedrive is not installed`" -ErrorAction Continue
    write-error `$_ -ErrorAction Continue
}

#DOWNLOAD ONEDRIVE INSTALLER AND RUN IT
try{
    if(!`$isOnedriveUpToDate -and `$downloadURL){
        Write-Output `"downloading from download URL: `$downloadURL`"
        Invoke-WebRequest -UseBasicParsing -Uri `$downloadURL -Method GET -OutFile `$temporaryInstallerPath
        Write-Output `"downloaded finished from download URL: `$downloadURL`"
        if([System.IO.File]::Exists(`$temporaryInstallerPath)){
            Write-Output `"Starting client installer`"
            Sleep -s 5 #let A/V scan the file so it isn't locked
            #first kill existing instances
            get-process | where {`$_.ProcessName -like `"onedrive*`"} | Stop-Process -Force -Confirm:`$False
            Sleep -s 5
            runProcess `$temporaryInstallerPath `"/silent`"
            Sleep -s 5
            Write-Output `"Install finished`"
234
        }
235
        `$installedVersionPath = (Get-ItemProperty -Path `"HKCU:\Software\Microsoft\OneDrive`" -Name `"OneDriveTrigger`" -ErrorAction Stop).OneDriveTrigger
236
    }
237 238 239
}catch{
    Write-Error `"Failed to download or install from `$downloadURL`" -ErrorAction Continue
    Write-Error `$_ -ErrorAction Continue
240
}
Jos Lieben's avatar
Jos Lieben committed
241

242 243 244 245 246 247
#WAIT FOR CLIENT CONFIGURATION AND REDETERMINE PATH
`$maxWaitTime = 600
`$waited = 0
Write-Output `"Checking existence of client folder`"
:detectO4B while(`$true){
    if(`$waited -gt `$maxWaitTime){
248 249
        Write-Output `"Waited too long for client folder to appear. Running auto updater, then exiting`"
        `$updaterPath = Join-Path `$Env:LOCALAPPDATA -ChildPath `"Microsoft\OneDrive\OneDriveStandaloneUpdater.exe`"
250 251
        runProcess `$updaterPath
        Sleep -s 60
252 253
        runProcess `$installedVersionPath
        Sleep -s 60
254 255
    }

256 257
    `$checks = 5
    for(`$i=1;`$i -le `$checks;`$i++){
Jos Lieben's avatar
Jos Lieben committed
258
        #check if a root path for the key exists
259 260 261
        `$subPath = `"`$(`$onedriveRootKey)`$(`$i)`"
        if(Test-Path `$subPath){
            `$detectedTenant = (Get-ItemProperty -Path `"`$(`$subPath)\`" -Name `"ConfiguredTenantId`" -ErrorAction SilentlyContinue).ConfiguredTenantId
Jos Lieben's avatar
Jos Lieben committed
262
            #we've found a business key with the correct TenantID, Onedrive has been started, check for the folder path
263 264 265
            `$detectedFolderPath = (Get-ItemProperty -Path `"`$(`$subPath)\`" -Name `"UserFolder`" -ErrorAction SilentlyContinue).UserFolder
            if(`$detectedFolderPath -and [System.IO.Directory]::Exists(`$detectedFolderPath)){
                Write-Output `"detected user folder at `$detectedFolderPath, linked to tenant `$detectedTenant`"
Jos Lieben's avatar
Jos Lieben committed
266 267 268 269
                break detectO4B
            }
        }
    }
270 271 272
    if(`$waited -gt `$maxWaitTime){
        break
    }
273
    Write-Output `"failed to detect user folder! Sleeping for 30 seconds`"
274
    Sleep -Seconds 30
275 276 277 278 279 280 281 282 283 284 285 286
    `$waited+=30   
     
    #GET LOCAL INSTALL PATH
    try{
        `$installedVersionPath = (Get-ItemProperty -Path `"HKCU:\Software\Microsoft\OneDrive`" -Name `"OneDriveTrigger`" -ErrorAction Stop).OneDriveTrigger
        Write-Output `"Detected Onedrive at `$installedVersionPath`"
    }catch{
        write-error `"Failed to read Onedrive version information from the registry`" -ErrorAction Continue
        `$installedVersionPath = Join-Path `$Env:LOCALAPPDATA -ChildPath `"Microsoft\OneDrive\OneDrive.exe`"
        Write-output `"Will use auto-guessed value of `$installedVersionPath`"
    }

287 288 289
    #RUN THE LOCAL CLIENT IF ALREADY INSTALLED
    Write-Output `"Starting client...`"
    & `$installedVersionPath
Jos Lieben's avatar
Jos Lieben committed
290 291
}

292
if(!`$redirectFoldersToOnedriveForBusiness){
Jos Lieben's avatar
Jos Lieben committed
293 294 295 296 297 298 299
    Stop-Transcript
    Exit
}

###DEFINE EXTERNAL FUNCTIONS
Function Set-KnownFolderPath {
    Param (
300
            [Parameter(Mandatory = `$true)][ValidateSet('AddNewPrograms', 'AdminTools', 'AppUpdates', 'CDBurning', 'ChangeRemovePrograms', 'CommonAdminTools', 'CommonOEMLinks', 'CommonPrograms', `
Jos Lieben's avatar
Jos Lieben committed
301 302 303 304 305 306 307 308
            'CommonStartMenu', 'CommonStartup', 'CommonTemplates', 'ComputerFolder', 'ConflictFolder', 'ConnectionsFolder', 'Contacts', 'ControlPanelFolder', 'Cookies', `
            'Desktop', 'Documents', 'Downloads', 'Favorites', 'Fonts', 'Games', 'GameTasks', 'History', 'InternetCache', 'InternetFolder', 'Links', 'LocalAppData', `
            'LocalAppDataLow', 'LocalizedResourcesDir', 'Music', 'NetHood', 'NetworkFolder', 'OriginalImages', 'PhotoAlbums', 'Pictures', 'Playlists', 'PrintersFolder', `
            'PrintHood', 'Profile', 'ProgramData', 'ProgramFiles', 'ProgramFilesX64', 'ProgramFilesX86', 'ProgramFilesCommon', 'ProgramFilesCommonX64', 'ProgramFilesCommonX86', `
            'Programs', 'Public', 'PublicDesktop', 'PublicDocuments', 'PublicDownloads', 'PublicGameTasks', 'PublicMusic', 'PublicPictures', 'PublicVideos', 'QuickLaunch', `
            'Recent', 'RecycleBinFolder', 'ResourceDir', 'RoamingAppData', 'SampleMusic', 'SamplePictures', 'SamplePlaylists', 'SampleVideos', 'SavedGames', 'SavedSearches', `
            'SEARCH_CSC', 'SEARCH_MAPI', 'SearchHome', 'SendTo', 'SidebarDefaultParts', 'SidebarParts', 'StartMenu', 'Startup', 'SyncManagerFolder', 'SyncResultsFolder', `
            'SyncSetupFolder', 'System', 'SystemX86', 'Templates', 'TreeProperties', 'UserProfiles', 'UsersFiles', 'Videos', 'Windows')]
309 310
            [string]`$KnownFolder,
            [Parameter(Mandatory = `$true)][string]`$Path
Jos Lieben's avatar
Jos Lieben committed
311 312 313
    )

    # Define known folder GUIDs
314
    `$KnownFolders = @{
Jos Lieben's avatar
Jos Lieben committed
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
        'AddNewPrograms' = 'de61d971-5ebc-4f02-a3a9-6c82895e5c04';'AdminTools' = '724EF170-A42D-4FEF-9F26-B60E846FBA4F';'AppUpdates' = 'a305ce99-f527-492b-8b1a-7e76fa98d6e4';
        'CDBurning' = '9E52AB10-F80D-49DF-ACB8-4330F5687855';'ChangeRemovePrograms' = 'df7266ac-9274-4867-8d55-3bd661de872d';'CommonAdminTools' = 'D0384E7D-BAC3-4797-8F14-CBA229B392B5';
        'CommonOEMLinks' = 'C1BAE2D0-10DF-4334-BEDD-7AA20B227A9D';'CommonPrograms' = '0139D44E-6AFE-49F2-8690-3DAFCAE6FFB8';'CommonStartMenu' = 'A4115719-D62E-491D-AA7C-E74B8BE3B067';
        'CommonStartup' = '82A5EA35-D9CD-47C5-9629-E15D2F714E6E';'CommonTemplates' = 'B94237E7-57AC-4347-9151-B08C6C32D1F7';'ComputerFolder' = '0AC0837C-BBF8-452A-850D-79D08E667CA7';
        'ConflictFolder' = '4bfefb45-347d-4006-a5be-ac0cb0567192';'ConnectionsFolder' = '6F0CD92B-2E97-45D1-88FF-B0D186B8DEDD';'Contacts' = '56784854-C6CB-462b-8169-88E350ACB882';
        'ControlPanelFolder' = '82A74AEB-AEB4-465C-A014-D097EE346D63';'Cookies' = '2B0F765D-C0E9-4171-908E-08A611B84FF6';'Desktop' = @('B4BFCC3A-DB2C-424C-B029-7FE99A87C641');
        'Documents' = @('FDD39AD0-238F-46AF-ADB4-6C85480369C7','f42ee2d3-909f-4907-8871-4c22fc0bf756');'Downloads' = @('374DE290-123F-4565-9164-39C4925E467B','7d83ee9b-2244-4e70-b1f5-5393042af1e4');
        'Favorites' = '1777F761-68AD-4D8A-87BD-30B759FA33DD';'Fonts' = 'FD228CB7-AE11-4AE3-864C-16F3910AB8FE';'Games' = 'CAC52C1A-B53D-4edc-92D7-6B2E8AC19434';
        'GameTasks' = '054FAE61-4DD8-4787-80B6-090220C4B700';'History' = 'D9DC8A3B-B784-432E-A781-5A1130A75963';'InternetCache' = '352481E8-33BE-4251-BA85-6007CAEDCF9D';
        'InternetFolder' = '4D9F7874-4E0C-4904-967B-40B0D20C3E4B';'Links' = 'bfb9d5e0-c6a9-404c-b2b2-ae6db6af4968';'LocalAppData' = 'F1B32785-6FBA-4FCF-9D55-7B8E7F157091';
        'LocalAppDataLow' = 'A520A1A4-1780-4FF6-BD18-167343C5AF16';'LocalizedResourcesDir' = '2A00375E-224C-49DE-B8D1-440DF7EF3DDC';'Music' = @('4BD8D571-6D19-48D3-BE97-422220080E43','a0c69a99-21c8-4671-8703-7934162fcf1d');
        'NetHood' = 'C5ABBF53-E17F-4121-8900-86626FC2C973';'NetworkFolder' = 'D20BEEC4-5CA8-4905-AE3B-BF251EA09B53';'OriginalImages' = '2C36C0AA-5812-4b87-BFD0-4CD0DFB19B39';
        'PhotoAlbums' = '69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C';'Pictures' = @('33E28130-4E1E-4676-835A-98395C3BC3BB','0ddd015d-b06c-45d5-8c4c-f59713854639');
        'Playlists' = 'DE92C1C7-837F-4F69-A3BB-86E631204A23';'PrintersFolder' = '76FC4E2D-D6AD-4519-A663-37BD56068185';'PrintHood' = '9274BD8D-CFD1-41C3-B35E-B13F55A758F4';
        'Profile' = '5E6C858F-0E22-4760-9AFE-EA3317B67173';'ProgramData' = '62AB5D82-FDC1-4DC3-A9DD-070D1D495D97';'ProgramFiles' = '905e63b6-c1bf-494e-b29c-65b732d3d21a';
        'ProgramFilesX64' = '6D809377-6AF0-444b-8957-A3773F02200E';'ProgramFilesX86' = '7C5A40EF-A0FB-4BFC-874A-C0F2E0B9FA8E';'ProgramFilesCommon' = 'F7F1ED05-9F6D-47A2-AAAE-29D317C6F066';
        'ProgramFilesCommonX64' = '6365D5A7-0F0D-45E5-87F6-0DA56B6A4F7D';'ProgramFilesCommonX86' = 'DE974D24-D9C6-4D3E-BF91-F4455120B917';'Programs' = 'A77F5D77-2E2B-44C3-A6A2-ABA601054A51';
        'Public' = 'DFDF76A2-C82A-4D63-906A-5644AC457385';'PublicDesktop' = 'C4AA340D-F20F-4863-AFEF-F87EF2E6BA25';'PublicDocuments' = 'ED4824AF-DCE4-45A8-81E2-FC7965083634';
        'PublicDownloads' = '3D644C9B-1FB8-4f30-9B45-F670235F79C0';'PublicGameTasks' = 'DEBF2536-E1A8-4c59-B6A2-414586476AEA';'PublicMusic' = '3214FAB5-9757-4298-BB61-92A9DEAA44FF';
        'PublicPictures' = 'B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5';'PublicVideos' = '2400183A-6185-49FB-A2D8-4A392A602BA3';'QuickLaunch' = '52a4f021-7b75-48a9-9f6b-4b87a210bc8f';
        'Recent' = 'AE50C081-EBD2-438A-8655-8A092E34987A';'RecycleBinFolder' = 'B7534046-3ECB-4C18-BE4E-64CD4CB7D6AC';'ResourceDir' = '8AD10C31-2ADB-4296-A8F7-E4701232C972';
        'RoamingAppData' = '3EB685DB-65F9-4CF6-A03A-E3EF65729F3D';'SampleMusic' = 'B250C668-F57D-4EE1-A63C-290EE7D1AA1F';'SamplePictures' = 'C4900540-2379-4C75-844B-64E6FAF8716B';
        'SamplePlaylists' = '15CA69B3-30EE-49C1-ACE1-6B5EC372AFB5';'SampleVideos' = '859EAD94-2E85-48AD-A71A-0969CB56A6CD';'SavedGames' = '4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4';
        'SavedSearches' = '7d1d3a04-debb-4115-95cf-2f29da2920da';'SEARCH_CSC' = 'ee32e446-31ca-4aba-814f-a5ebd2fd6d5e';'SEARCH_MAPI' = '98ec0e18-2098-4d44-8644-66979315a281';
        'SearchHome' = '190337d1-b8ca-4121-a639-6d472d16972a';'SendTo' = '8983036C-27C0-404B-8F08-102D10DCFD74';'SidebarDefaultParts' = '7B396E54-9EC5-4300-BE0A-2482EBAE1A26';
        'SidebarParts' = 'A75D362E-50FC-4fb7-AC2C-A8BEAA314493';'StartMenu' = '625B53C3-AB48-4EC1-BA1F-A1EF4146FC19';'Startup' = 'B97D20BB-F46A-4C97-BA10-5E3608430854';
        'SyncManagerFolder' = '43668BF8-C14E-49B2-97C9-747784D784B7';'SyncResultsFolder' = '289a9a43-be44-4057-a41b-587a76d7e7f9';'SyncSetupFolder' = '0F214138-B1D3-4a90-BBA9-27CBC0C5389A';
        'System' = '1AC14E77-02E7-4E5D-B744-2EB1AE5198B7';'SystemX86' = 'D65231B0-B2F1-4857-A4CE-A8E7C6EA7D27';'Templates' = 'A63293E8-664E-48DB-A079-DF759E0509F7';
        'TreeProperties' = '5b3749ad-b49f-49c1-83eb-15370fbd4882';'UserProfiles' = '0762D272-C50A-4BB0-A382-697DCD729B80';'UsersFiles' = 'f3ce0f7c-4901-4acc-8648-d5d44b04ef8f';
        'Videos' = @('18989B1D-99B5-455B-841C-AB7C74E4DDFC','35286a68-3c57-41a1-bbb1-0eae73d76c95');'Windows' = 'F38BF404-1D43-42F2-9305-67DE0B28FC23';
    }

347 348 349 350
    `$Type = ([System.Management.Automation.PSTypeName]'KnownFolders').Type
    If (-not `$Type) {
        `$Signature = @'
[DllImport(`"shell32.dll`")]
Jos Lieben's avatar
Jos Lieben committed
351 352
public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, IntPtr token, [MarshalAs(UnmanagedType.LPWStr)] string path);
'@
353
        `$Type = Add-Type -MemberDefinition `$Signature -Name 'KnownFolders' -Namespace 'SHSetKnownFolderPath' -PassThru
Jos Lieben's avatar
Jos Lieben committed
354 355
    }

356 357
	If (!(Test-Path `$Path -PathType Container)) {
		New-Item -Path `$Path -Type Directory -Force -Verbose
Jos Lieben's avatar
Jos Lieben committed
358 359
    }

360 361 362 363 364 365 366
    If (Test-Path `$Path -PathType Container) {
        ForEach (`$guid in `$KnownFolders[`$KnownFolder]) {
            Write-Verbose `"Redirecting `$KnownFolders[`$KnownFolder]`"
            `$result = `$Type::SHSetKnownFolderPath([ref]`$guid, 0, 0, `$Path)
            If (`$result -ne 0) {
                `$errormsg = `"Error redirecting `$(`$KnownFolder). Return code `$(`$result) = `$((New-Object System.ComponentModel.Win32Exception(`$result)).message)`"
                Throw `$errormsg
Jos Lieben's avatar
Jos Lieben committed
367 368 369
            }
        }
    } Else {
370
        Throw New-Object System.IO.DirectoryNotFoundException `"Could not find part of the path `$Path.`"
Jos Lieben's avatar
Jos Lieben committed
371 372
    }
	
373 374
	Attrib +r `$Path
    Return `$Path
Jos Lieben's avatar
Jos Lieben committed
375 376 377 378
}

Function Get-KnownFolderPath {
    Param (
379
            [Parameter(Mandatory = `$true)]
Jos Lieben's avatar
Jos Lieben committed
380 381
            [ValidateSet('AdminTools','ApplicationData','CDBurning','CommonAdminTools','CommonApplicationData','CommonDesktopDirectory','CommonDocuments','CommonMusic',`
            'CommonOemLinks','CommonPictures','CommonProgramFiles','CommonProgramFilesX86','CommonPrograms','CommonStartMenu','CommonStartup','CommonTemplates',`
382
            'CommonVideos','Cookies','Downloads','Desktop','DesktopDirectory','Favorites','Fonts','History','InternetCache','LocalApplicationData','LocalizedResources','MyComputer',`
Jos Lieben's avatar
Jos Lieben committed
383 384
            'MyDocuments','MyMusic','MyPictures','MyVideos','NetworkShortcuts','Personal','PrinterShortcuts','ProgramFiles','ProgramFilesX86','Programs','Recent',`
            'Resources','SendTo','StartMenu','Startup','System','SystemX86','Templates','UserProfile','Windows')]
385
            [string]`$KnownFolder
Jos Lieben's avatar
Jos Lieben committed
386
    )
387 388 389 390 391
    if(`$KnownFolder -eq `"Downloads`"){
        Return `$Null
    }else{
        Return [Environment]::GetFolderPath(`$KnownFolder)
    }
Jos Lieben's avatar
Jos Lieben committed
392 393 394 395
}

Function Redirect-Folder {
    Param (
396 397
        `$GetFolder,
        `$SetFolder,
398 399
        `$Target,
        `$CopyContents
Jos Lieben's avatar
Jos Lieben committed
400 401
    )

402
    `$Folder = Get-KnownFolderPath -KnownFolder `$GetFolder
403 404 405
    If (`$Folder -ne `$Target) {
        Write-Verbose `"Redirecting `$SetFolder to `$Target`"
        Set-KnownFolderPath -KnownFolder `$SetFolder -Path `$Target
406
        if(`$CopyContents -and `$Folder){
407
            Get-ChildItem -Path `$Folder -ErrorAction Continue | Copy-Item -Destination `$Target -Recurse -Container -Force -Confirm:`$False -ErrorAction Continue
Jos Lieben's avatar
Jos Lieben committed
408
        }
409
        Attrib +h `$Folder
Jos Lieben's avatar
Jos Lieben committed
410
    } Else {
411
        Write-Verbose `"Folder `$GetFolder matches target. Skipping redirection.`"
Jos Lieben's avatar
Jos Lieben committed
412 413 414
    }
}

415 416 417
if(`$detectedFolderPath -and `$redirectFoldersToOnedriveForBusiness){
    `$listOfFoldersToRedirectToOnedriveForBusiness | % {
        Write-Output `"Redirecting `$(`$_.knownFolderInternalName) to `$detectedFolderPath\`$(`$_.desiredSubFolderNameInOnedrive)`"
Jos Lieben's avatar
Jos Lieben committed
418
        try{
Jos Lieben's avatar
Jos Lieben committed
419
            `$Target = Join-Path `$detectedFolderPath -ChildPath `$_.desiredSubFolderNameInOnedrive
420
            Redirect-Folder -GetFolder `$_.knownFolderInternalName -SetFolder `$_.knownFolderInternalIdentifier -Target `$Target -CopyContents = `$_.copyContents
421
            Write-Output `"Redirection succeeded`"
Jos Lieben's avatar
Jos Lieben committed
422
        }catch{
423 424
            Write-Error `"Failed to redirect this folder!`" -ErrorAction Continue
            Write-Error `$_ -ErrorAction Continue     
Jos Lieben's avatar
Jos Lieben committed
425 426 427
        }
    }
}
428 429
Stop-Transcript
Exit
430 431 432 433
"

$localScriptContent | Out-File $desiredBootScriptPath -Force

434
Stop-Transcript
435

436
Start-ScheduledTask -TaskName "OnedriveAutoConfig"
437

438
Exit