Reputation: 65
This PowerShell script works (not mine, I found it - data has been changed to dummy data here) - it Syncs Documents from a SharePoint Site to the users OneDrive:
#region Functions
function Sync-SharepointLocation {
param (
[guid]$siteId,
[guid]$webId,
[guid]$listId,
[mailaddress]$userEmail,
[string]$webUrl,
[string]$webTitle,
[string]$listTitle,
[string]$syncPath
)
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 $uri.ToString()
start-process -filepath $($uri.ToString())
}
catch {
$errorMsg = $_.Exception.Message
}
if ($errorMsg) {
Write-Warning "Sync failed."
Write-Warning $errorMsg
}
else {
Write-Host "Sync completed."
while (!(Get-ChildItem -Path $syncPath -ErrorAction SilentlyContinue)) {
Start-Sleep -Seconds 2
}
return $true
}
}
#endregion
#region Main Process
try {
#region Sharepoint Sync
[mailaddress]$userUpn = cmd /c "whoami/upn"
$params = @{
#replace with data captured from your sharepoint site.
siteId = "{11111111-1111-1111-11111111111111111}"
webId = "{22222222-2222-2222-22222222222222222}"
listId = "{33333333-3333-3333-33333333333333333}"
userEmail = $userUpn
webUrl = "https://somecompany.sharepoint.com/sites/graphics"
webTitle = "graphics"
listTitle = "Documents"
}
$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."
}
}
else {
Write-Host "Location already syncronized: $($params.syncPath)" -ForegroundColor Yellow
}
#endregion
}
catch {
$errorMsg = $_.Exception.Message
}
finally {
if ($errorMsg) {
Write-Warning $errorMsg
Throw $errorMsg
}
else {
Write-Host "Completed successfully.."
}
}
#endregion
But I need do this for several SharePoint Sites, but I'd like to avoid having to run 10 different PowerPoint Scripts, if possible.
What I've tried:
I've made an array where I've defined the variables for all the sites, like this (with the correct data):
$params = @(
[pscustomobject]@{
siteId = "SiteID";
webId = "webId";
listId = "listId";
userEmail = $userUpn;
webUrl = "webUrl";
webTitle = "webTitle";
listTitle = ""Documents"
}
[Repeated for each Site]
)
I've then altered this part of the original code, to do a ForEach loop:
#region Main Process
try {
#region Sharepoint Sync
[mailaddress]$userUpn = cmd /c "whoami/upn"
$params | ForEach-Object {
$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."
}
}
else {
Write-Host "Location already syncronized: $($params.syncPath)" -ForegroundColor Yellow
}
}
#endregion
}
But it's not working as expected: Only the first Site in my Array is synced.
I'm a PowerShell beginner, so please help me: What am I doing wrong?
Thanks!
Upvotes: 1
Views: 206
Reputation: 366
When looping through all the objects inside the $params array using a ForEach-Object, the object that you want to reference will be $_ .. not $params. So, where you are referencing $params.webTitle, etc., you should be referencing $_.webTitle, $_.listTitle, etc.
If you're new to Powershell, I would recommend you setting a variable like $paramObj for each instance using foreach ($parmObj in $params) {...} to make it clear what you are referencing, making the code look like:
# replaces the ForEach-Object
ForEach ($paramObj in $params) {
Write-Host "SharePoint params:"
$paramObj | Format-Table
# i didn't see a syncPath in your $params custom object.. better if you set a local variable
$syncPath = "$(split-path $env:onedrive)\$($userUpn.Host)\$($paramObj.webTitle) - $($paramObj.listTitle)"
if (!(Test-Path $($syncPath))) {
Write-Host "Sharepoint folder not found locally, will now sync.." -ForegroundColor Yellow
$sp = Sync-SharepointLocation @paramObj
if (!($sp)) {
Throw "Sharepoint sync failed."
}
}
else {
Write-Host "Location already syncronized: $syncPath" -ForegroundColor Yellow
}
}
Upvotes: 2