Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 108 additions & 44 deletions Sync-SharepointFolder/Sync-SharepointFolder.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -12,76 +12,140 @@ function Sync-SharepointLocation {
)
try {
Add-Type -AssemblyName System.Web
#Encode site, web, list, url & email
[string]$siteId = [System.Web.HttpUtility]::UrlEncode($siteId)
[string]$webId = [System.Web.HttpUtility]::UrlEncode($webId)
[string]$listId = [System.Web.HttpUtility]::UrlEncode($listId)
[string]$userEmail = [System.Web.HttpUtility]::UrlEncode($userEmail)
[string]$webUrl = [System.Web.HttpUtility]::UrlEncode($webUrl)
#build the URI

$uri = New-Object System.UriBuilder
$uri.Scheme = "odopen"
$uri.Host = "sync"
$uri.Query = "siteId=$siteId&webId=$webId&listId=$listId&userEmail=$userEmail&webUrl=$webUrl&listTitle=$listTitle&webTitle=$webTitle"
#launch the process from URI

Write-Host "Starting sync: $webTitle - $listTitle"
Write-Host $uri.ToString()
start-process -filepath $($uri.ToString())
Start-Process -FilePath $($uri.ToString())
}
catch {
$errorMsg = $_.Exception.Message
Write-Warning "Sync failed for $webTitle - $listTitle"
Write-Warning $_.Exception.Message
return $false
}
if ($errorMsg) {
Write-Warning "Sync failed."
Write-Warning $errorMsg

# Wait for sync folder with timeout
$timeout = 120
$elapsed = 0
while (!(Get-ChildItem -Path $syncPath -ErrorAction SilentlyContinue)) {
Start-Sleep -Seconds 2
$elapsed += 2
if ($elapsed -ge $timeout) {
Write-Warning "Timed out waiting for: $syncPath"
return $false
}
}
else {
Write-Host "Sync completed."
while (!(Get-ChildItem -Path $syncPath -ErrorAction SilentlyContinue)) {
Start-Sleep -Seconds 2
Write-Host "Sync completed: $syncPath" -ForegroundColor Green
return $true
}

function Wait-ForOneDrive {
param ([int]$TimeoutSeconds = 120)
$elapsed = 0
while (!(Get-Process OneDrive -ErrorAction SilentlyContinue)) {
Start-Sleep -Seconds 5
$elapsed += 5
if ($elapsed -ge $TimeoutSeconds) {
Throw "OneDrive not running after ${TimeoutSeconds}s"
}
return $true
}
}
# Allow time for full initialization
Start-Sleep -Seconds 10
}
#endregion
#region Main Process
try {
#region Sharepoint Sync
[mailaddress]$userUpn = cmd /c "whoami/upn"
$params = @{
#replace with data captured from your sharepoint site.

#region Configuration
$libraries = @(
@{
siteId = "{00000000-0000-0000-0000-000000000000}"
webId = "{00000000-0000-0000-0000-000000000000}"
listId = "{00000000-0000-0000-0000-000000000000}"
webUrl = "https://contoso.sharepoint.com/sites/Finance"
webTitle = "Finance"
listTitle = "Shared Documents"
},
@{
siteId = "{00000000-0000-0000-0000-000000000000}"
webId = "{00000000-0000-0000-0000-000000000000}"
listId = "{00000000-0000-0000-0000-000000000000}"
webUrl = "https://contoso.sharepoint.com/sites/HR"
webTitle = "HR"
listTitle = "Policies"
},
@{
siteId = "{00000000-0000-0000-0000-000000000000}"
webId = "{00000000-0000-0000-0000-000000000000}"
listId = "{00000000-0000-0000-0000-000000000000}"
userEmail = $userUpn
webUrl = "https://example.sharepoint.com"
webTitle = "Title"
listTitle = "FolderName"
webUrl = "https://contoso.sharepoint.com/sites/Operations"
webTitle = "Operations"
listTitle = "Templates"
}
)
#endregion

#region Main Process
Start-Transcript -Path "$env:TEMP\SharePointSync.log" -Append
try {
[mailaddress]$userUpn = cmd /c "whoami /upn" 2>$null
if (!$userUpn) {
$userUpn = (Get-ItemProperty -Path "HKCU:\Software\Microsoft\OneDrive\Accounts\Business1" -ErrorAction Stop).UserEmail
}
$params.syncPath = "$(split-path $env:onedrive)\$($userUpn.Host)\$($params.webTitle) - $($Params.listTitle)"
Write-Host "SharePoint params:"
$params | Format-Table
if (!(Test-Path $($params.syncPath))) {
Write-Host "Sharepoint folder not found locally, will now sync.." -ForegroundColor Yellow
$sp = Sync-SharepointLocation @params
if (!($sp)) {
Throw "Sharepoint sync failed."

Wait-ForOneDrive

$oneDriveRoot = Split-Path $env:OneDrive
$results = @{ Success = @(); Failed = @(); Skipped = @() }

foreach ($lib in $libraries) {
$lib.userEmail = $userUpn
$lib.syncPath = "$oneDriveRoot\$($userUpn.Host)\$($lib.webTitle) - $($lib.listTitle)"

if (Test-Path $lib.syncPath) {
Write-Host "Already synced: $($lib.webTitle) - $($lib.listTitle)" -ForegroundColor Yellow
$results.Skipped += "$($lib.webTitle) - $($lib.listTitle)"
continue
}

Write-Host "Syncing: $($lib.webTitle) - $($lib.listTitle)" -ForegroundColor Cyan
$success = Sync-SharepointLocation @lib

if ($success) {
$results.Success += "$($lib.webTitle) - $($lib.listTitle)"
}
else {
$results.Failed += "$($lib.webTitle) - $($lib.listTitle)"
}

# Stagger syncs to avoid overwhelming OneDrive
Start-Sleep -Seconds 5
}
else {
Write-Host "Location already syncronized: $($params.syncPath)" -ForegroundColor Yellow

# Summary
Write-Host "`n===== Sync Summary =====" -ForegroundColor Cyan
Write-Host "Synced: $($results.Success.Count)" -ForegroundColor Green
Write-Host "Skipped: $($results.Skipped.Count)" -ForegroundColor Yellow
Write-Host "Failed: $($results.Failed.Count)" -ForegroundColor Red

if ($results.Failed.Count -gt 0) {
Write-Warning "Failed libraries: $($results.Failed -join ', ')"
Throw "One or more libraries failed to sync."
}
#endregion
}
catch {
$errorMsg = $_.Exception.Message
Write-Warning $_.Exception.Message
Stop-Transcript
exit 1
}
finally {
if ($errorMsg) {
Write-Warning $errorMsg
Throw $errorMsg
}
else {
Write-Host "Completed successfully.."
}
Stop-Transcript
}
#endregion
#endregion