I want to create an example folder in a Document Library of a created Teamsite on Sharepoint Online using Powershell but am running into an error.
After I have created the Teamsite I use the following script:
#Retrieve list
$DocLibName = "Dokumente"
$FolderTitle = "Beispiel"
$List = $ctx.Web.Lists.GetByTitle($DocLibName)
$folder = $list.AddItem("", [Microsoft.SharePoint.SPFileSystemObjectType]::Folder)
$folder["Title"] = $FolderTitle
$folder.Update();
$ctx.Load($List)
$ctx.ExecuteQuery()
Error Message
The type [Microsoft.SharePoint.SPFileSystemObjectType] was not found : Make sure that the assembly that contains this type is loaded.
Line:79 Char:1
+ $ Folder = $ List.addItem ("" [Microsoft.SharePoint.SPFileSystemObjectType ] :: Folde ...
It is not possible to use an index to a null array.
Line:80 Char:1
+ $ Folder ["Title"] = $FolderTitle
It is not possible to call a method for an expression of the NULL .
Line:81 Char:1
+ $Folder.Update();
How can this be resolved?
You are getting this error since Microsoft.SharePoint.SPFileSystemObjectTypetype belongs to SharePoint Server Side API which is not compatible with Office 365.
Below is demonstrated how to create a folder in SharePoint Online site via PowerShell (utilizes SharePoint CSOM API)
Function Create-Folder()
{
Param(
[Parameter(Mandatory=$True)]
[Microsoft.SharePoint.Client.Folder]$ParentFolder,
[Parameter(Mandatory=$True)]
[String]$FolderName
)
$folder = $ParentFolder.Folders.Add($folderName)
$ParentFolder.Context.Load($folder)
$ParentFolder.Context.ExecuteQuery()
return $folder
}
Function Get-Context($Url,$Username,$Password){
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$ctx.Credentials = $credentials
return $ctx
}
Usage
$Url = "https://contoso.sharepoint.com/"
$UserName = "jdoe#contoso.onmicrosoft.com"
$Password = ""
$TargetFolderName = "Archive2016"
$ctx = Get-Context -Url $Url -Username $Username -Password $Password
$parentFolder = $ctx.Web.Lists.GetByTitle("Documents").RootFolder
$folder = Create-Folder -ParentFolder $parentFolder -FolderName $TargetFolderName
Write-Host "Folder [$TargetFolderName] has been created succesfully. Url: $($folder.ServerRelativeUrl)"
For creating a folder hierarchy the following script could be utilized:
Function Create-FolderHierarchy()
{
Param(
[Parameter(Mandatory=$True)]
[Microsoft.SharePoint.Client.Folder]$ParentFolder,
[Parameter(Mandatory=$True)]
[String]$FolderUrl
)
$folderNames = $FolderUrl.Trim().Split("/",[System.StringSplitOptions]::RemoveEmptyEntries)
$folderName = $folderNames[0]
$curFolder = $ParentFolder.Folders.Add($folderName)
$ParentFolder.Context.Load($curFolder)
$ParentFolder.Context.ExecuteQuery()
if ($folderNames.Length -gt 1)
{
$curFolderUrl = [System.String]::Join("/", $folderNames, 1, $folderNames.Length - 1)
return Create-FolderHierarchy -ParentFolder $curFolder -FolderUrl $curFolderUrl
}
return $curFolder
}
If you are interested in scenario for uploading files while preserving a folder structure, take a look at How to: Upload files into Office 365 via PowerShell post, it contains ready made script for that purpose.
Related
I would like to create a workflow that automatically copies files which were uploaded to a Sharepoint-Site onto another SharePoint-Site (for file exchange with customers). Therefore I created a Logic App that triggers a Runbook with following content:
param(
[Parameter (Mandatory = $true)][string]$FilePath,
[Parameter (Mandatory = $true)][string]$FileName
)
$Client = "C:\Modules\User\Microsoft.SharePoint.Client\Microsoft.SharePoint.Client.dll"
$ClientRT = "C:\Modules\User\Microsoft.SharePoint.Client\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path $Client
Add-Type -Path $ClientRT
Creds = Get-AutomationPSCredential -Name "SharepointCreds"
#Set parameter values
$TargetSiteURL="https://domain.SharePoint.com/sites/site1"
$SourceSiteURL="https://domain.Sharepoint.com/sites/site2"
#Set Source and Destination File URL
$SourceFileURL="/sites/Sitename1/$Filepath/$FileName"
$TargetFileURL="/sites/Sitename2/$Filepath/$FileName"
#Setup Credentials to connect
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Creds.UserName, $Creds.Password)
#Setup the contexts
$SourceCtx = New-Object Microsoft.SharePoint.Client.ClientContext($SourceSiteURL)
$SourceCtx.Credentials = $Credentials
$TargetCtx = New-Object Microsoft.SharePoint.Client.ClientContext($TargetSiteURL)
$TargetCtx.Credentials = $Credentials
#Get the Source File
$FileInfo = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($SourceCtx, $SourceFileURL)
#Copy File to the Target location
[Microsoft.SharePoint.Client.File]::SaveBinaryDirect($TargetCtx, $TargetFileURL, $FileInfo.Stream,$True)
Anyways I keep receiving following error: Cannot send a content-body with this verb-type
How can I resolve this issue? Is there a better approach?
In sharepoint, we could use the MoveCopyUtil Class to copy file between sites
For example:
$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SourceSiteURL)
$Ctx.Credentials = $Credentials
#Copy the File
$MoveCopyOpt = New-Object Microsoft.SharePoint.Client.MoveCopyOptions
$Overwrite = $True
[Microsoft.SharePoint.Client.MoveCopyUtil]::CopyFile($Ctx, $SourceFileURL, $TargetFileURL, $Overwrite, $MoveCopyOpt)
$Ctx.ExecuteQuery()
Reference: https://www.sharepointdiary.com/2017/02/sharepoint-online-copy-file-between-document-libraries-using-powershell.html#ixzz7CSvEyjEc
I have a powershell script which i got somewhere from the internet that creates a folder in SharePoint. It works as it can create a folder when i tested it but, i would like like to know how can i modify this script to check if the folder that i am creating does not exist yet? can someone please help?
function CreateFolder {
param
(
$SPSite,
$SiteUrl,
$FolderName,
$User,
$Password
)
$ErrorActionPreference = "Stop"
$DocLibName = "Documents"
$FullSPPath = $SPSite+ $SiteUrl
#Connect Office 365 SharePoint Online Site
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($SPSite)
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
$Context.Credentials = $Creds
$List = $Context.Web.Lists.GetByTitle($DocLibName)
$Context.Load($List)
#Get the List Root Folder
$ParentFolder=$Context.web.GetFolderByServerRelativeUrl($FullSPPath)
#Create New Folder
$Folder = $ParentFolder.Folders.Add($FolderName)
$ParentFolder.Context.Load($Folder)
$ParentFolder.Context.ExecuteQuery()
Write-host "New Folder Created Successfully!"
}
You can do pretty much the same as what you are doing to get the rootfolder. So if the new folder is called NewFolder in the root of your library it would look like:
$newFolder = $Context.Web.GetFolderByServerRelativeUrl("/sites/site/library/NewFolder")
$context.Load($newFolder)
$context.ExecuteQuery()
Now all you need to do is check the exists property on the Folder object:
if (!$newFolder.Exists) {
#do stuff here
}
I need to be able to script folder creation from a csv into a SharePoint Online document library with each folder with permission inheritance disabled and for different user to each folder to be added.
The following code can create the folders and disable the inheritance but it seems to try add a group but not a user. How to make it add a user instead?
Thanks.
### Get the user credentials
$credential = Get-Credential
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
### Input Parameters
$url = 'URL HERE'
$csvfilepath='C:\Scripts\data.csv'
$libname ='BUS61'
### References
# Specified the paths where the dll's are located.
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.dll'
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.Runtime.dll'
### CreateFolder with Permissions Function
function CreateFolderWithPermissions()
{
# Connect to SharePoint Online and get ClientContext object.
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$clientContext.Credentials = $credentials
Function GetRole
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 1)]
[Microsoft.SharePoint.Client.RoleType]$rType
)
$web = $clientContext.Web
if ($web -ne $null)
{
$roleDefs = $web.RoleDefinitions
$clientContext.Load($roleDefs)
$clientContext.ExecuteQuery()
$roleDef = $roleDefs | Where-Object { $_.RoleTypeKind -eq $rType }
return $roleDef
}
return $null
}
# Get the SharePoint web
$web = $clientContext.Web;
$clientContext.Load($web)
#Get the groups
$groups = $web.SiteGroups
$clientContext.Load($groups)
$clientContext.ExecuteQuery()
#Read CSV File and iterate
$csv = Import-CSV $csvfilepath
foreach ($row in $csv)
{
#Create Folder
$folder = $web.Folders.Add($libname + "/" + $row.Folder)
$clientContext.Load($folder)
$clientContext.ExecuteQuery()
#Assign Role
$group = $groups.GetByName($row.Group)
$clientContext.Load($group)
$clientContext.ExecuteQuery()
$roleType= $row.Role
$roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
$roleObj = GetRole $roleTypeObject
$usrRDBC = $null
$usrRDBC = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($clientContext)
$usrRDBC.Add($roleObj)
# Remove inherited permissions
$folder.ListItemAllFields.BreakRoleInheritance($false, $true)
$clientContext.Load($folder.ListItemAllFields.RoleAssignments.Add($group, $usrRDBC))
$folder.Update()
$clientContext.ExecuteQuery()
# Display the folder name and permission
Write-Host -ForegroundColor Blue 'Folder Name: ' $folder.Name ' Group: '$row.Group ' Role: ' $roleType;
}
}
#Execute the function
CreateFolderWithPermissions
Let's assume that you will define user login in your CSv file. Than you have to change the line:
$group = $groups.GetByName($row.Group)
to
$user = $web.EnsureUser($row.User)
and replace all references to $group variable with $user
More generic approach for searching for a user (with for example display name) would be using Utility.ResolvePrincipal method:
[Microsoft.SharePoint.Client.Utilities.Utility]::ResolvePrincipal($clientContext, $web, "DisplayName", ([Microsoft.SharePoint.Client.Utilities.PrincipalType]::User), ([Microsoft.SharePoint.Client.Utilities.PrincipalSource]::All), $null, $false)
I'm learning powershell to create a script that uploads files to a sub-site library inside SharePoint. I managed to get it working and uploading .doc files to my library, however I also want fill in any metadata specified in additional columns with the file at the same time. I'm not using the SharePoint snap-in and instead using the webclient functions. Here is the simple powershell script
# create the Variable Path and Pass the source folder path
$path = "THE FILE"
# create the Variable destination and pass the URL of the SharePoint List
$destination = "SharePoint SubSite"
# Store the current user default credentials in the Variable Credentials
$credentials = [System.Net.CredentialCache]::DefaultCredentials;
# Create the object of the Webclient
$webclient = New-Object System.Net.WebClient;
$webclient.Credentials = $credentials;
$webclient.UploadFile($destination + “/” + "Filename", “PUT”, TheFile)
This code works however I don't know how to use the webclient functions to pass metadata to custom columns. When the file is uploaded I noticed the only first two columns are updated but the custom fields are left blank.
If this is even possible let me know.
Much thanks for your help
Basically three options are available here (it is assumed SharePoint 2010 is used):
consume SharePoint 2010 REST interface
consume SharePoint Web Services
consume SharePoint 2010 Client SDK
How to consume SharePoint 2010 REST Interface via PowerShell
The following function demonstrates how to perform CRUD operations using SharePoint 2010 REST interface:
<#
.Synopsis
Sends an HTTP or HTTPS request to a SharePoint 2010 REST-compliant web service.
.DESCRIPTION
This function sends an HTTP or HTTPS request to a Representational State
Transfer (REST)-compliant ("RESTful") SharePoint Online web service.
.EXAMPLE
Invoke-SPRestMethod -Url "https://contoso.sharepoint.com/_vti_bin/ListData.svc/Projects"
#>
Function Invoke-SPRestRequest()
{
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$ListName,
[Parameter(Mandatory=$False)]
[int]$ItemId,
[Parameter(Mandatory=$False)]
[String]$QueryOptions,
[Parameter(Mandatory=$False)]
[Microsoft.PowerShell.Commands.WebRequestMethod]$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get,
[Parameter(Mandatory=$False)]
[System.Net.ICredentials]$Credentials,
[Parameter(Mandatory=$False)]
[String]$Payload,
[Parameter(Mandatory=$False)]
[String]$ETag,
[Parameter(Mandatory=$False)]
[String]$XHTTPMethod,
[Parameter(Mandatory=$False)]
[System.String]$Accept = "application/json;odata=verbose",
[Parameter(Mandatory=$False)]
[String]$ContentType = "application/json;odata=verbose"
)
#Construct Endpoint URL
$endpointUrl = $WebUrl + "/_vti_bin/listdata.svc/" + $ListName
if($ItemId){
$endpointUrl = $endpointUrl + "(" + $ItemId + ")"
}
if($QueryOptions){
$endpointUrl = $endpointUrl + $QueryOptions
}
$client = New-Object System.Net.WebClient
if($Credentials) {
$client.Credentials = $Credentials
}
$client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$client.Headers.Add("Content-Type",$ContentType)
$client.Headers.Add("Accept",$Accept)
if($Method -eq "Get") {
$result = $client.DownloadString($endpointUrl) | ConvertFrom-Json
}
elseif ($Method -eq "Post") {
if($ETag) {
$client.Headers.Add("If-Match", $ETag)
}
if($XHTTPMethod) {
$client.Headers.Add("X-HTTP-Method", $XHTTPMethod)
}
if($Payload) {
$client.UploadString($endpointUrl,$Method,$Payload)
}
else {
$client.UploadString($endpointUrl,$Method)
}
}
$client.Dispose()
return $result
}
Gist: Invoke-SPRestRequest.ps1
Example
The following example demonstrates how to upload a file into SharePoint 2010 and set metadata properties. It consists of:
Upload a file operation
Find the uploaded list item associated with uploaded file
Update list item properties
Code:
$UserName = "username"
$Password = Read-Host -Prompt "Enter the password"
$WebUrl = "https://contoso.sharepoint.com/project"
$FolderUrl = "/project/Shared Documents/Archive"
Function Find-ListItem([string]$WebUrl,[System.Net.ICredentials]$Credentials,[string]$ListName,[string]$QueryOptions)
{
$result = Invoke-SPRestRequest -WebUrl $WebUrl -ListName $ListName -QueryOptions $QueryOptions -Credentials $Credentials
return $result.d.results
}
Function Update-ListItem([string]$WebUrl,[System.Net.ICredentials]$Credentials,[string]$ListName,[int]$ItemId)
{
$itemPayload = #{
"DocumentStatusValue" = "Close";
} | ConvertTo-Json
Invoke-SPRestRequest -WebUrl $WebUrl -ListName $ListName -ItemId $ItemId -Credentials $Credentials -Method Post -Payload $itemPayload -ETag "*" -XHTTPMethod "MERGE"
}
Function Upload-File([string]$WebUrl,[System.Net.ICredentials]$Credentials,[string]$FolderUrl, [string]$FileName)
{
$client = New-Object System.Net.WebClient
#$client.Credentials = $Credentials
$client.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$siteUri = New-Object Uri($WebUrl)
$fileUri = New-Object Uri($siteUri, ($FolderUrl + "/" + [System.IO.Path]::GetFileName($FileName)))
$result = $client.UploadFile($fileUri, "PUT", $FileName)
$client.Dispose()
}
#1.Upload a File
Upload-File -WebUrl $WebUrl -FolderUrl $FolderUrl -FileName "D:\tmp\SharePoint User Guide.docx"
#2.Find an associated List Item for a File
$query = "?`$filter=Path eq '" + $FolderUrl + "'"
$ListItem = Find-ListItem -WebUrl $WebUrl -ListName "Documents" -QueryOptions $query
#3.Update List Item properties
Update-ListItem -WebUrl $WebUrl -ListName "Documents" -ItemId $ListItem.Id
References
SharePoint Foundation REST Interface
I have written this code
$spSiteUrl = "http://mysharepoint/sites/site/web/"
$cmd = "_api/web/lists/getbytitle('$docLib')/rootfolder/files/add(url='" + $file.Name + "', overwrite=true)"
$digest = "got valid digest through code";
$mediaType = new-object("System.Net.Http.Headers.MediaTypeWithQualityHeaderValue") "application/json"
$handler = new-object("System.Net.Http.HttpClientHandler")
$handler.UseDefaultCredentials= $true
$client = New-Object("System.Net.Http.HttpClient") $handler
$client.BaseAddress = $spSiteUrl
$client.DefaultRequestHeaders.Accept.Clear()
$client.DefaultRequestHeaders.Accept.Add($mediaType);
$client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose")
$content = $null
$client.DefaultRequestHeaders.Add("X-HTTP-Method", "PUT")
$client.DefaultRequestHeaders.Add("X-RequestDigest", $digest)
$fileStream = [System.IO.File]::OpenRead($file.FullName)
$streamContent = new-object ("System.Net.Http.StreamContent") $fileStream
$task = $client.PostAsync($cmd, $streamContent)
$response = $task.Result
$content = $response.Content.ReadAsStringAsync().Result
Write-Host $content
$fileStream.Close()
$fileStream.Dispose()
$response = $response.EnsureSuccessStatusCode()
$client.Dispose()
Here I already have a valid digest value which I got from doing a POST to _api/contextinfo
But when I execute this code I get an error
{"error":{"code":"-2147024891, System.UnauthorizedAccessException","message":{"lang":"en-US","value":"Access denied. You do not have permission to perform this action or access this resource."}}}
_api/web/lists/getbytitle('test')/rootfolder/files/add(url='BaselineFinishTag_2014_06.log', overwrite=true)
Here as you can see that I am using UseDefaultCredentials to true. This code is running with an account which is the farm admin and site collection administrator and has complete ownership of the site where this code is being run.
Can you tell me what I have missed in this code which is causing me to get UnAuthorizedException?
Consuming the SharePoint 2013 REST API from PowerShell article describes how to perform CRUD operations using REST API in PowerShell.
The following function demonsrtates how to upload files via SharePoint 2013 REST using Invoke-RestSPO.ps1 function from the specified article:
How to upload File using REST API in PowerShell
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
. ".\Invoke-RestSPO.ps1" #Load Invoke-RestSPO function
Function Upload-SPOFile(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$True)]
[String]$Password,
[Parameter(Mandatory=$True)]
[String]$FolderUrl,
[Parameter(Mandatory=$True)]
[System.IO.FileInfo]$FileInfo
)
$Url = $WebUrl + "/_api/web/GetFolderByServerRelativeUrl('" + $FolderUrl + "')/Files/add(url='" + $FileInfo.Name + "',overwrite=true)"
$FileContent = [System.IO.File]::ReadAllBytes($FileInfo.FullName)
$contextInfo = Get-SPOContextInfo $WebUrl $UserName $Password
Invoke-RestSPO -Url $Url -Method Post -UserName $UserName -Password $Password -Body $FileContent -RequestDigest $contextInfo.GetContextWebInformation.FormDigestValue
}
#Usage: upload file into SharePoint Online
$UserName = "username#contoso.onmicrosoft.com"
$Password = Read-Host -Prompt "Enter the password"
$WebUrl = "https://contoso.sharepoint.com/"
$FolderUrl = "/Shared Documents"
$UploadFileInfo = New-Object System.IO.FileInfo("C:\Users\user\Documents\SharePoint User Guide.docx")
Upload-SPOFile -WebUrl $WebUrl -UserName $UserName -Password $Password -FolderUrl $FolderUrl -FileInfo $UploadFileInfo
References
Invoke-RestSPO.ps1
Consuming the SharePoint 2013 REST API from PowerShell