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)
Related
I am creating a LIST in SharePoint using PowerShell via a CSV file. I am able to create the list as well as add items successfully, although I need to validate that the item (row) that I add to the list does not already exist in the list, prior to updating the list.
In the code I am not able to get $ItemExist correctly. It always returns a Null value. ($MaxItems currently has a value of 2 as there are 2 items in the list "list_DLs").
(I have already checked all other posts on the site for the same issue and did not find a fix)
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass
$Path_SpFiles = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI"
Add-Type -path "$Path_SpFiles\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -path "$Path_SpFiles\Microsoft.SharePoint.Client.dll"
# ------- Connect to SharePoint Site and fetch List Items ----------------
[Net.ServicePointManager]::SecurityProtocol = 'TLS11','TLS12','ssl3'
$site = "https://xyz.sharepoint.com/sites/mco"
$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminName, $Pass)
$context.Credentials = $credentials
$ListName="list_DLs"
$list = $context.Web.Lists.GetByTitle($ListName)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(5000)
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()
$MaxItems = $items.count
$SourceFile = "C:\Temp\list_DLs.csv"
$CSVData = Import-CSV -path $SourceFile
foreach ($row in $CSVData)
{
#----------------------------------------------
#Check if the item has previously been added
if ($MaxItems -ne 0)
{
$ItemExist = $items | where{$_.Title -eq $row.PrimarySmtpAddress}
if($ItemExist -ne $null) {Continue}
}
#----------------------------------------------
$ListItemInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
$Item = $list.AddItem($ListItemInfo)
$Item["Title"] = $row.PrimarySmtpAddress
$Item.Update()
$Context.ExecuteQuery()
Break
}
I know that the $items in being returned correctly, because if I run this snippet of code to iterate through the items I am able to see them correctly. I am just not able to get $ItemExist to work correctly
ForEach ($item in $items)
{
$b = $item["Title"]
$b
Break
}
You can use a CAML query to check if the item is already in the list.
CAML query:
$caml="
<View>
<Query>
<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>1</Value></Eq></Where>
</Query>
</View>
"
$ItemExist = Get-PnPListItem -List $targetList -Query $caml
My test result:
I am trying to run a PowerShell script that would generate the site colletion on the SharePoint tenant. However, whenever I am trying to execute the site collection creation, I get an error:
Exception calling "ExecuteQuery" with "0" argument(s): "Unknown Error"
At C:\projects\SP\Scripts\Taxonomy\Add-NavigationTerms1.ps1:120 char:5
+ $TenantContext.ExecuteQuery()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ServerException
How would I go around this error? How can I fix it? Thank you very much for all your help!
Here is the code:
param (
[Parameter(Mandatory = $false)]
[string] $sourceWeb = '',
[string] $destinationWeb = '',
[Parameter(Mandatory = $false)]
[string] $sourceListName = 'CurrentSites', #$sourceListName = 'O365 Sites',
[Parameter(Mandatory = $false)]
[string] $sharepointAdmin = ''
)
<#
Add-Type -Path "C:/Program Files/SharePoint Client Components/Assemblies/Microsoft.Online.SharePoint.Client.Tenant.dll"
Add-Type -Path "C:/Program Files/Common Files/microsoft shared/Web Server Extensions/16/ISAPI/Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:/Program Files/Common Files/microsoft shared/Web Server Extensions/16/ISAPI/Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:/Program Files/Common Files/microsoft shared/Web Server Extensions/16/ISAPI/Microsoft.SharePoint.Client.UserProfiles.dll"
#>
$path = 'C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/15/ISAPI/'
$simpleLinkUrlPropertyName = '_Sys_Nav_SimpleLinkUrl'
$assemblies = 'Microsoft.SharePoint.Client.dll',
'Microsoft.SharePoint.Client.Runtime.dll',
'Microsoft.SharePoint.Client.Taxonomy.dll'
$assemblies | % { Add-Type -Path (Join-Path $path $_) }
Add-Type -Path "C:/Program Files/SharePoint Client Components/Assemblies/Microsoft.Online.SharePoint.Client.Tenant.dll"
#$context = New-Object Microsoft.SharePoint.Client.ClientContext($sourceWeb)
#$password = Read-Host -Prompt 'Please enter your password' -AsSecureString
#$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($sharepointAdmin,$password)
$password = ''
#[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client")
#[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint.Client.Runtime")
Function Get-SPOContext([string]$Url, [string]$UserName, [string]$Password) {
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$context = New-Object Microsoft.SharePoint.Client.ClientContext($Url)
$context.Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
return $context
}
Function Get-ListItems([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $Context.Web.Lists.GetByTitle($listTitle)
$Context.Load($list)
$Context.ExecuteQuery()
$qry = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($qry)
$Context.Load($items)
$Context.ExecuteQuery()
return $items
}
Function Create-Site-Collection([String]$url, [String]$title) {
$TenantURL = ''
$Title = 'New Published Collection List';
[string]
$TenantUserName = '';
[Security.SecureString]
#$TenantPassword = ConvertTo-SecureString 'Anew6731' -AsPlainText -Force
$TenantPassword = convertto-securestring "Anew6731" -asplaintext -force
#Open the Tenant Administration Context with the Tenant Admin Url
$TenantContext = Get-SPOContext -Url $TenantUrl -UserName $TenantUserName -Password "Anew6731"
#$TenantContext = New-Object Microsoft.SharePoint.Client.ClientContext($TenantUrl)
#$TenantCredentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($TenantUserName, $TenantPassword)
#$TenantContext.Credentials = $TenantCredentials
#Get the tenant object
$Tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($TenantContext)
#Set the Site Creation Properties values
$TenantProperties = New-Object Microsoft.Online.SharePoint.TenantAdministration.SiteCreationProperties
#$TenantProperties.Url = $url
$TenantProperties.Template = "CMSPUBLISHING#0 "
$TenantProperties.Owner = $TenantUserName
$TenantProperties.StorageMaximumLevel = 1000
$TenantProperties.UserCodeMaximumLevel = 300
$TenantProperties.Title = $title
$TenantContext.Load($Tenant)
$TenantContext.ExecuteQuery()
#$TenantContext.Load($TenantProperties)
#$TenantContext.ExecuteQuery()
#Create the site using the properties
$Tenant.CreateSite($TenantProperties) | Out-Null
Write-Host "Creating site collection "
#Create the site in the tennancy
#$TenantContext.Load($Tenant)
#$TenantContext.Load($spOnlineOperation)
$TenantContext.ExecuteQuery()
#$TenantContext.Dispose()
}
$UserName = $sharepointAdmin
#$Password = Read-Host -Prompt "Enter the password"
$Url = $sourceWeb
$context = Get-SPOContext -Url $Url -UserName $UserName -Password $Password $items = Get-ListItems -Context $context -ListTitle "O365 Sites"
foreach ($item in $items) {
$Context.Load($item)
$Context.ExecuteQuery()
Write-Host $item["NEWURL"]
Write-Host $item["Title"]
#Write-Host $item.FieldValues
Create-Site-Collection -URL $item["NEWURL"] -Title $item["Title"]
#Write-Hsost $item.DisplayName
}
$context.Dispose()
I am honestly not sure what went wrong but this code/method worked just fine
Function Create-Site-Collection([String]$fullUrl, [Microsoft.SharePoint.Client.ClientContext] $TenantContext)
{
Write-Host "Now configuring the new Site Collection"
#Get the tenant object
$tenant = New-Object Microsoft.Online.SharePoint.TenantAdministration.Tenant($TenantContext)
#Set the Site Creation Properties values
$properties = New-Object Microsoft.Online.SharePoint.TenantAdministration.SiteCreationProperties
$properties.Url = $fullUrl
$properties.Template = "BLANKINTERNETCONTAINER#0"
$properties.Owner = $AdminSiteUsername
$properties.StorageMaximumLevel = 1000
#$properties.UserCodeMaximumLevel = 100
$properties.TimeZoneId = 10 # (UTC-05:00) Eastern Time (US and Canada)
#Create the site using the properties
$tenant.CreateSite($properties) | Out-Null
$TenantContext.ExecuteQuery()
Write-Host "Creating site collection"
#Create the site in the tennancy
try
{
$TenantContext.ExecuteQuery()
Write-Host "Site Creation request completed. Note that the creation process is asynchronous and provisioning may take a short while."
}
Catch [Exception]
{
Write-host $_.Exception.Message -f Red
}
}
How do I reference a specific email address in this code it always directs to
the default email account. I have multiple email accounts in my outlook and I want to download emails from a different account which I want to reference by that email address . I have a feeling
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
has to be changed please give suggestions.
`[CmdletBinding(DefaultParameterSetName="All")] `
`Param(
[Parameter(Mandatory=$true,
Position=0,
HelpMessage='Folder path to store emails. Do not use quotation marks even if the path has spaces.',
ValueFromPipelineByPropertyName=$true
)]
[Alias("Destination", "Dest", "FullName")]
[String]$DestinationPath, `
[Parameter(ParameterSetName="All")]
[Parameter(Mandatory=$true,ParameterSetName="Unread")]
[Switch]$UnreadOnly,
[Parameter(ParameterSetName="Unread")]
[Switch]$MarkRead
)
#Removes invalid Characters for file names from a string input and outputs
the clean string
` #Similar to VBA CleanString() Method
#Currently set to replace all illegal characters with a hyphen (-)
Function Remove-InvalidFileNameChars {`
param(
[Parameter(Mandatory=$true, Position=0)]
[String]$Name
)
return [RegEx]::Replace($Name, "[{0}]" -f ([RegEx]::Escape([String][System.IO.Path]::GetInvalidFileNameChars())), '-')
}
#Test for destination folder nonexistence
if (!(Test-Path $DestinationPath)) {
#Set values for prompt and menu
$yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", `
"Confirmation Choice"
$no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", `
"Negative Response"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no)
$title = "Invalid Destination"
$message = "The folder you entered does not exist. Would you like to create the folder?"
#Prompt for folder creation and store answer
$result = $host.UI.PromptForChoice($title, $message, $options, 0)
#If yes, create.
if ($result -eq 0) {
New-Item $DestinationPath -ItemType Directory | Out-Null
Write-Host "Directory created."
}
#If no, exit
else {exit}
}
#Add a trailing "\" to the destination path if it doesn't already
if ($DestinationPath[-1] -ne "\") {
$DestinationPath += "\"
}
#Add Interop Assembly
Add-type -AssemblyName "Microsoft.Office.Interop.Outlook" | Out-Null
#Type declaration for Outlook Enumerations, Thank you Hey, Scripting Guy! blog for this demonstration
$olFolders = "Microsoft.Office.Interop.Outlook.olDefaultFolders" -as [type]
$olSaveType = "Microsoft.Office.Interop.Outlook.OlSaveAsType" -as [type]
$olClass = "Microsoft.Office.Interop.Outlook.OlObjectClass" -as [type]
#Add Outlook Com Object, MAPI namespace, and set folder to the Inbox
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNameSpace("MAPI")
#Future Functionality to Receive Email before saving - Still Needs Testing
#$outlook.Session | Out-Null
#$outlook.Session.SendAndReceive($false) | Out-Null
$folder = $namespace.getDefaultFolder($olFolders::olFolderInBox)
#Iterate through each object in the chosen folder
foreach ($email in $folder.Items) {
#Get email's subject and date
[string]$subject = $email.Subject
[string]$sentOn = $email.SentOn
#Strip subject and date of illegal characters, add .msg extension, and combine
$fileName = Remove-InvalidFileNameChars -Name ($sentOn + "-" + $subject + ".msg")
#Combine destination path with stripped file name
$dest = $DestinationPath + $fileName
#Test if object is a MailItem
if ($email.Class -eq $olClass::olMail) {
#Test if UnreadOnly switch was used
if ($UnreadOnly) {
#Test if email is unread and save if true
if ($email.Unread) {
#Test if MarkRead switch was used and mark read
if ($MarkRead) {
$email.Unread = $false
}
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
#UnreadOnly switch not used, save all
else {
$email.SaveAs($dest, $olSaveType::olMSG)
}
}
}
Think You can do something like this:
$outlook = New-Object -ComObject Outlook.Application
$namespace =$outlook.GetNameSpace("MAPI")
$namespace.Logon("Profilename","profilepassword",$false,$false)
Also you can use Assembly - Microsoft.Exchange.WebServices.dll and do something like this:
[Reflection.Assembly]::LoadFile("C:\Program Files (x86)\Microsoft\Exchange\Web Services\2.0\Microsoft.Exchange.WebServices.dll") > $nul
$getref = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2010_SP2)
$getref.Credentials = New-Object Net.NetworkCredential('Account', 'Password', 'domain.local')
$getref.AutodiscoverUrl("Account#domain.com")
$inbox = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($getref,[Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox)
#Write-Host "Total Messages:" $inbox.TotalCount
$psPropset = new-object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::FirstClassProperties)
$ivItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView($inbox.TotalCount)
$fiItems = $getref.FindItems($Inbox.Id,$ivItemView)
[Void]$getref.LoadPropertiesForItems($fiItems,$psPropset)
foreach($Item in $fiItems.Items){
if ($Item.From -EQ "Somemail#domain.com") {
New-Object -TypeName PSObject -Property #{
Emails = $Item.From
} | select Emails
}
}
Hello! You can load a body text (to html) something like this:
foreach($Item in $fiItems.Items){
if ($Item.Subject -match "Something special") {
$Item.Load()
$Save = ((Get-Date -Format "yyMMdd") + "-" + $Item.Subject[0] + ".html")
New-Item -Path "C:\file\exch\" -name $Save -ItemType file -value $Item.Body.Text
}
}
I have a report that is copied to a number of different servers. It is imported manually and the data source properties are altered to match the current server's specs. I would like to be able to automate the process by enabling users to open a the SSRS report and dynamically alter it's shared data source properties through PowerShell. I hope you could help. You may see reference below.
The script would accept an input parameter for servername, username and password. Also, the save my password must be ticked.
I couldn't believe I managed to create a script for this. You may make use of the script below as future reference. Comments are available for each part and anything that needs to be altered has a "here" keyword , ex. Your_database_name_here .
Import-Module SqlPs
#Input parameter to get Server\Instancename of your Datasource
$Servername = Read-Host "Please enter your Servername"
$Instancename = Read-Host "Please enter your Instancename. For default instance please press enter"
Write-host ""
if ($Instancename -eq ""){
$ServerInstance = $Servername
}
Else {
$ServerInstance = $Servername +"\"+ $InstanceName
}
#Setting up SSRS Target URL. This is the location where your reports would be deployed.
if ($Instancename -eq ""){
$ReportServerUri = "http://$Servername/ReportServer//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports"
}
Else {
$ReportServerUri = "http://$Servername/ReportServer_$Instancename//ReportService2010.asmx?wsdl"
$TargetURL = "http://$Servername/Reports_$Instancename"
}
$global:proxy = New-WebServiceProxy -Uri $ReportServerUri -UseDefaultCreden
#We would make use of SQL Server Authentication for the reports shared datasource so you need to supply a username and password.
Write-Host " SQL Server Authentication:"
$Username = Read-Host " Username"
$Password = Read-Host -AsSecureString "Password"
$type = $Proxy.GetType().Namespace
$datatype = ($type + '.Property')
$property =New-Object ($datatype);
$property.Name = “NewFolder”
$property.Value = “NewFolder”
$numproperties = 1
$properties = New-Object ($datatype + '[]')$numproperties
$properties[0] = $property;
$newFolder = $proxy.CreateFolder("Reports”, “/”, $properties);
$newFolder = $proxy.CreateFolder("Data Sources”, “/”, $properties);
$Children =$proxy.ListChildren("/",$false)
$DBname = 'Your_Database_Name_Here'
# Creating Datasource through powershell
Write-Host " Creating Datasource ..."
$Name = "Name_Your_Datasource_here"
$Parent = "/Data Sources"
$ConnectString = "data source=$Servername\$Instancename;initial catalog=$DBname"
$type = $Proxy.GetType().Namespace
$DSDdatatype = ($type + '.DataSourceDefinition')
$DSD = new-object ($DSDdatatype)
if($DSD -eq $null){
Write-Error Failed to create data source definition object
}
$CredentialDataType = ($type + '.CredentialRetrievalEnum')
$Cred = new-object ($CredentialDataType)
$CredEnum = ($CredentialDataType).Integrated
$Cred.value__=1
$DSD.CredentialRetrieval =$Cred
$DSD.ConnectString = $ConnectString
$DSD.Enabled = $true
$DSD.EnabledSpecified = $false
$DSD.Extension = "SQL"
$DSD.ImpersonateUserSpecified = $false
$DSD.Prompt = $null
$DSD.WindowsCredentials = $false
$DSD.UserName = $Username
$DSD.Password = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password))
$newDSD = $proxy.CreateDataSource($Name,$Parent,$true,$DSD,$null)
#Deploying RLD files to Target URL
Write-Host " Deploying RDL files ..."
$stream = Get-Content 'D:\Your_RDL_path_here.rdl' -Encoding byte
$warnings =#();
$proxy.CreateCatalogItem("Report","Report_Name_here","/Reports",$true,$stream,$null,[ref]$warnings)
#Let's make use of the datasource we just created for your RDL files.
$Items = $global:proxy.listchildren("/Data Sources", $true)
foreach ($item in $items)
{
$DatasourceName = $item.Name
$DatasourcePath = $item.Path
}
$RDLS = $global:proxy.listchildren("/Reports", $true)
foreach ($rdl in $rdls)
{
$report = $rdl.path
$rep = $global:proxy.GetItemDataSources($report)
$rep | ForEach-Object {
$proxyNamespace = $_.GetType().Namespace
$constDatasource = New-Object ("$proxyNamespace.DataSource")
$constDatasource.Name = $DataSourceName
$constDatasource.Item = New-Object ("$proxyNamespace.DataSourceReference")
$constDatasource.Item.Reference = $DataSourcePath
$_.item = $constDatasource.Item
$global:proxy.SetItemDataSources($report, $_)
Write-Host "Changing datasource `"$($_.Name)`" to $($_.Item.Reference)"
}
}
#Open a IE browser to view the report.
$IE=new-object -com internetexplorer.application
$IE.navigate2($TargetURL)
$IE.visible=$true
Write-Host ""
Write-Host "You may now view the Reports through the open IE browser."
Write-Host -ForegroundColor Green "**STEP COMPLETED!"
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.