Automatically syncing Teams/SharePoint libraries

There’s been a Group Policy setting to sync Team/SharePoint libraries for a while although last time I looked at it the functionality didn’t actually work yet – I think it was meant to be available from Windows 10 1909 but didn’t quite make it. Besides the fact that the setting didn’t do anything, all the documentation claimed it could take “up to 8 hours” for the library to appear in the user’s sync client/Explorer – clearly this is no use especially if you’re in an environment where people hot desk and share machines. I’ve had another look at it to see if it’s any better now.

Using the GPO Setting

First of all we need to have the OneDrive policy templates. You can find these on a Windows 10 PC running the sync client in %localappdata%\Microsoft\OneDrive\version\adm. Copy OneDrive.admx into your central policy definitions store, or if you don’t have one into c:\windows\policydefinitions, and put Onedrive.adml into your language folder within the policy store.

Now open a Group Policy Object in the editor and go to User Configuration > Policies > Administrative Templates > OneDrive. The setting you need to find is Configure team site libraries to sync automatically.

This will want you to provide the library name and library ID. To get the ID, go to the library you want to sync in SharePoint (so if it’s in a Team, open the Team’s files in SharePoint). Press Sync, then cancel the “Open in OneDrive” prompt, then click Copy library ID. The chances of this screen actually appearing seem to be notoriously hit or miss, but if you are logged in as a global or SharePoint admin it should appear. I’m logged in as a global admin and using Edge and it worked fine.

You should now have a library ID on your clipboard which looks something like “tenantId=xxx&siteId=xxx&webId=xxx&listId=xxx&webUrl=httpsxxx&version=1”. It’s got some URL encoded characters that we need to remove before we can feed this into the GPO so open PowerShell and run the following:

[uri]::UnescapeDataString(“paste-in-the-library-ID-string-here”)

Copy the unescaped string and paste it into the GPO editor in the Value column, and put the library name in the Value name column.

Enter a friendly name for the site in the first column, and paste the unescaped library ID string into the Value column

So does it work? Well, there’s still an “up to 8 hour” wait so it’s still only really suitable for a 1:1 device deployment where it’s always the same person logged on and they can put up with a delay on their first logon.

An alternative way to add libraries

If you have a look in the registry at what happens when you click the Sync button in the browser, you’ll notice it launches the grvopen: or odopen: protocols, which in turn run “onedrive.exe /url:%1”. If you replace OneDrive.exe with a program which just echos out the arguments passed to it, you’ll notice this format:

odopen://sync/?userId=xxxxxxxx%2Dxxxx%2Dxxxx%2Dxxxx%2Dxxxxxxxxxxxx
&userEmail=katy%40xxxxxxxxxxxxx%2Exx&isSiteAdmin=1&siteId=%7Bxxxxx
xxx%2Dxxxx%2Dxxxx%2Dxxxx%2Dxxxxxxxxxxxx%7D&webId=%7Bxxxxxxxx%2Dxxx
x%2Dxxxx%2Dxxxx%2Dxxxxxxxxxxxx%7D&webTitle=xxxxxxxxxxxxxxxx&webTem
plate=64&webLogoUrl=%5Flayouts%2F15%2Fimages%2Fsiteicon%2Epng&webU
rl=https%3A%2F%2Fxxxxxxxxxxxxx%2Esharepoint%2Ecom%2Fsites%2Fxxxxxx
xxxxxxx&onPrem=0&libraryType=3&listId=%7Bxxxxxxxx%2Dxxxx%2Dxxxx%2D
xxxx%2Dxxxxxxxxxxxx%7D&listTitle=Documents&folderId=xxxxxxxx%2Dxxx
x%2Dxxxx%2Dxxxx%2Dxxxxxxxxxxxx&folderName=General&folderUrl=https%
3A%2F%2Fxxxxxxxxxxxxx%2Esharepoint%2Ecom%2Fsites%2Fxxxxxxxxxxxxx%2
FShared%20Documents%2FGeneral&scope=OPENFOLDER

We can then run on logon “onedrive.exe /url:” and the above URL to have the sync client add the library, no waiting around for “up to 8 hours”. Most of the URL will be static but there’s a user-specific bit we need to work out how to obtain. A lot of the parameters are optional – as a minimum we need to obtain the following:

  • userEmail. We can look up the current user’s UserPrincipalName in PowerShell
  • siteID: Go to https://tenancy.sharepoint.com/sites/SiteName/_api/site/id and it’ll tell you the site ID. This is a GUID enclosed in curly braces
  • webID: Go to https://tenancy.sharepoint.com/sites/SiteName/_api/web/id and it’ll tell you the web ID, another GUID in braces.
  • webTitle: The name of the Team/SharePoint site, used when the client builds the folder structure.
  • webUrl: The URL to the site. You can see this at https://tenancy.sharepoint.com/sites/SiteName/_api/web/url however it’s usually just https://tenancy.sharepoint.com/sites/SiteName.
  • listId: The SharePoint library’s ID. Open the library in a web browser, click on the Settings button near the top right, then pick Library Settings. The List ID will be at the end of the URL of the Settings page – a GUID in braces.
  • listTitle: The document library name.

webTitle and listTitle are optional, and they do not have to match the actual names on SharePoint. The sync client will create a folder named after the tenancy, and within that will be a folder named webTitle – listTitle, which contains the synced library. If you don’t include these at all it will just call it Documents.

Putting all this together, I’ve written a PowerShell script which can be used as a logon script which will map a library if it isn’t already mapped. For this to work you’ll need to have already configured the OneDrive sync client to automatically log in and sync the user’s OneDrive.

$userEmail = ([ADSI]"LDAP://<SID=$([System.Security.Principal.WindowsIdentity]::GetCurrent().User.Value)>").UserPrincipalName
$siteID = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
$tenantName = "KatysTechBlog"
$webID = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
$webTitle = "Tech Blog"
$webUrl = "https://katystechblog.sharepoint.com/sites/KatysTechBlog"
$listId = "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
$listTitle = "Library"


if (-not ((Test-Path -Path "HKCU:\SOFTWARE\Microsoft\OneDrive\Accounts\Business1\Tenants\$tenantName") -and (Get-ItemProperty -Path "HKCU:\SOFTWARE\Microsoft\OneDrive\Accounts\Business1\Tenants\$tenantName" -Name "$env:USERPROFILE\$tenantName\$webTitle - $listTitle"))) {
    $URL = "/url:odopen://sync/?userEmail=" + [uri]::EscapeDataString($userEmail) + "&siteId=" + [uri]::EscapeDataString($siteID) + "&webId=" + [uri]::EscapeDataString($webID) + "&webTitle="+ [uri]::EscapeDataString($webTitle) + "&webUrl="+ [uri]::EscapeDataString($webUrl) + "&listId="+ [uri]::EscapeDataString($listId) + "&listTitle="+ [uri]::EscapeDataString($listTitle)
    Start-Process "$env:LOCALAPPDATA\Microsoft\OneDrive\Onedrive.exe" -ArgumentList "/url:$URL"
}

This script will grab the current user’s UserPrincipalName (without needing any optional modules installed – I got this one liner from this post) and put together all the different parameters into an URL, and then runs onedrive if the library isn’t already synced. If you’ve got multiple libraries you want to sync, with different combinations for different users, I’d probably recommend just having multiple scripts – one per library – and then linking the appropriate scripts to the appropriate GPO.

 

Further Reading:

2 Replies to “Automatically syncing Teams/SharePoint libraries”

  1. Firstly your script works great. The issue I’m having with it is that when a user first logs onto a machine it doesn’t work as OneDrive hasn’t started/sync’d yet before the script runs. I know I could add a sleep delay, but is it possible to make the script not run until OneDrive is sync’d or is it possible for a scripted to include signing the user in first?

    not sure the best way to go about this

    1. Don’t think there is a way to get the status of onedrive via script (there wasn’t last time I looked at this – when trying to prevent logoff until it had finished any pending uploads).

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.