FromTheField

Real world experiences of SharePoint PFE and CTS engineers from Microsoft UK

February, 2014

  • Office 365 - PowerShell Script to Upload Files to a Document Library using CSOM

    UPDATE: The script now supports uploading files larger than 2MB.

    Another PowerShell sample script for you. This one uploads all files within a specified local directory to a Document Library within a Site in an O365 tenant.

    All you need to run this script is an O365 tenant, the SharePoint client components SDK installed on the machine running the script - http://www.microsoft.com/en-us/download/details.aspx?id=35585 and to update the $User, $SiteURL, $DocLibName (name of the destination Document library) and $Folder (path to the local folder containing the files to upload) variables. When the script is executed it will prompt for the password of the user specific in the $User variable.

    One thing to point out is that CSOM has a maximum upload size of 2MB.

    #Specify tenant admin and site URL
    $User = "admin@tenant.onmicrosoft.com"
    $SiteURL = "https://tenant.sharepoint.com/sites/site"
    $Folder = "C:\FilesToUpload"
    $DocLibName = "DocLib"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString

    #Bind to site collection
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
    $Context.Credentials = $Creds

    #Retrieve list
    $List = $Context.Web.Lists.GetByTitle($DocLibName)
    $Context.Load($List)
    $Context.ExecuteQuery()

    #Upload file
    Foreach ($File in (dir $Folder))
    {
    $FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
    $FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
    $FileCreationInfo.Overwrite = $true
    $FileCreationInfo.ContentStream = $FileStream
    $FileCreationInfo.URL = $File
    $Upload = $List.RootFolder.Files.Add($FileCreationInfo)
    $Context.Load($Upload)
    $Context.ExecuteQuery()
    }


    Brendan Griffin

  • Office 365 - Retrieve User Profile Properties using CSOM with PowerShell

    Update 12/04/14 - I have added an example that demonstrates how to export User Profile Properties to a CSV file at the end of this post.

    The example PowerShell script below can be used to retrieve all user profile properties for all users within a Site Collection. It doesn't appear to be possible to connect to the User Profile Service Application and retrieve profile properties for all users with the tenant using CSOM, the only approach is to perform this at a Site Collection level, you could of course add a ForEach loop to iterate through all Site Collections however additional effort would be required to remove duplicate profile data from the output as it's likely that each user will have permission to multiple Site Collections therefore would be retrieved multiple times using this approach.

    It requires two variables to be updated - $User which is the tenant admin and $SiteURL which is the URL for the Site Collection that you wish to retrieve User Profile data from.

    #Please install the SharePoint client components SDK - http://www.microsoft.com/en-us/download/details.aspx?id=35585 prior to running this script.

    #Specify tenant admin and URL
    $User = "admin@tenant.onmicrosoft.com"

    #Configure Site URL and User
    $SiteURL = "https://tenant.sharepoint.com/sites/site"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)

    #Bind to Site Collection
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Context.Credentials = $Creds

    #Identify users in the Site Collection
    $Users = $Context.Web.SiteUsers
    $Context.Load($Users)
    $Context.ExecuteQuery()

    #Create People Manager object to retrieve profile data
    $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Context)
    Foreach ($User in $Users)
        {
        $UserProfile = $PeopleManager.GetPropertiesFor($User.LoginName)
        $Context.Load($UserProfile)
        $Context.ExecuteQuery()
        If ($UserProfile.Email -ne $null)
            {
            Write-Host "User:" $User.LoginName -ForegroundColor Green
            $UserProfile.UserProfileProperties
            Write-Host ""
            } 
        }


    Here is an example of the output.

    If you only need to retrieve a selection of user profile properties rather than everything, the script can be easily updated - simply replace $UserProfile.UserProfileProperties with $UserProfile | Select (Property Names). The following properties can be retrieved using this approach:

    • AccountName
    • DirectReports
    • DisplayName
    • Email
    • PersonalURL
    • PictureURL
    • Title
    • UserURL

    To retrieve AccountName,Email and PictureURL the following command can be used - $UserProfile | Select AccountName,Email,PictureURL

    If you need to retrieve other profile properties you will need to use the following approach - $UserProfile.UserProfileProperties.PropertyName, for example to retrieve the department for a user the following can be used $UserProfile.UserProfileProperties.Department.

    Below is an example of how to export User Profile Properties to a CSV file - which you may find a little more useful than outputting to the console. Simply replace the last section of the script above with the script below, you need to update the $Output variable to specify the location to output the CSV file to.

    If you need to add any additional properties, two lines in the script need to be updated (highlighted). The first line specifies the headings of the CSV file, the order of which need to match exactly the properties specified in the second line that is highlighted.

    The second line that is highlighted specifies the actual properties to output for each user. The $UserProfile and $UPP variables can be used to select the properties, $UPP is $UserProfile.UserProfileProperties. My example contains both types of properties.

    #Create People Manager object to retrieve profile data
    $Output = "D:\Output.csv"
    $Headings = "Name","Email","OneDrive URL","Phone","Job Title","Department"
    $Headings -join "," | Out-File -Encoding default -FilePath $Output

    $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Context)
    Foreach ($User in $Users)
        {
        $UserProfile = $PeopleManager.GetPropertiesFor($User.LoginName)
        $Context.Load($UserProfile)
        $Context.ExecuteQuery()
        If ($UserProfile.Email -ne $null)
            {
            $UPP = $UserProfile.UserProfileProperties
            $Properties = $UserProfile.DisplayName,$UserProfile.Email,$UserProfile.PersonalUrl, $UPP.WorkPhone,$UPP.'SPS-JobTitle',$UPP.Department
            $Properties -join "," | Out-File -Encoding default -Append -FilePath $Output
            } 
        }

     The example outputs the following properties:

    • Name
    • Email
    • OneDrive URL
    • Phone
    • Job Title
    • Department

    Here is the output file that is created:

    Hopefully this gives you enough basic information to make a start using PowerShell to retrieve user profile information.

    Brendan Griffin - @brendankarl

  • PowerShell Snippets

    PowerShell Snippets

    As Premier Field Engineers, we often find that our customers need assistance creating PowerShell scripts that can help automate administrative processes; or retrieve information from their various SharePoint farms.

    Whilst each of our customers are different and have unique environments; many scripts have requirements that are similar, if not the same regardless of the environment or the actions that the script will perform.

    This blog post (the first of a series of blog posts that I am aiming to write) takes a look at some of these common scripting requirements, with the aim of providing you with some useful ‘snippets’ of code. As with all blog posts that we write, the code has not been tested in your environment, so do use caution and fully test anything that you use.

     

    (1) Event Logging

    “When we run a script; we want to ensure that we log/ capture who runs it in the server event log…”

    This requirement is pretty common. Being able to keep a record of who is running what on your servers is useful; not just for those ‘oops’ moments, but really useful in general :)

     

    Script example: Creating a new entry in the Application Log

    # Get the current logged in user

    $userObj = [System.Security.Principal.WindowsIdentity]::GetCurrent()

    $user = $userObj.name 

    # Set up the event log variables

    $eventLog = Get-EventLog –List | Where-Object {$_.Log –eq ‘Application’}

    $eventLog.MachineName = “.”

    $eventLog.Source = “Contoso IT Department”

    # Write an entry into the Application Log

    $eventLog.WriteEntry(“The script was started by $user.”,”Information”,2014)

     


    Fig 1: Log entry created in Application log


     

    Fig 2: Log entry detail


     

    (2) Showing Script Progress

    “When we run the script, we want to be able to see its progress rather than stare at a blinking cursor…”

    This is a pretty common requirement too; especially on scripts that query a large collection of objects. The good news is that PowerShell provides us with a great cmdlet to do just this (Write-Progress):

    Script example: iterating through all sub-webs in a site collection

    $collWeb = Get-SPWeb –identity http://intranet.contoso.com/sites/sitecollection1

    [int]$i = 0 

    Foreach ($web in $collWeb)
    {

        $i++
        Write-Progress –activity “Collecting all sub webs” –status “Status: “ –percentComplete (($i / $collWeb.count)*100)
    }

     

    Fig 3: Showing progress bar


     

    That’s all for now, I hope that this has been useful.

    Cheers, Steve
    @moss_sjeffery

  • Download language packs for SharePoint 2013

    Hi all,

    I've been working with a customer recently to help them deploy a multi-lingual SharePoint 2013 environment.
    This can be a little time consuming, so I helped automate this process with PowerShell:

    Here is the script:

    # Import BITS module

    Import-Module BITSTransfer

    # Path to download language packs to

    $downloadPath = "C:\SPLanguagePacks"

    # hashtable for language packs

    $lPacks = @{

    Arabic = "http://download.microsoft.com/download/3/2/C/32C97E8A-E1C4-4BC3-B4B5-1E85B2E0A571/serverlanguagepack.img"

    ChineseSimp = "http://download.microsoft.com/download/4/7/7/477BFB7A-C9C2-4B1D-8408-D70D4AF52DBA/serverlanguagepack.img"

    ChineseTrad = "http://download.microsoft.com/download/F/2/D/F2D67EBD-C9AE-482E-83FA-C4669F058073/serverlanguagepack.img"

    English = "http://download.microsoft.com/download/7/E/C/7EC7E73F-F172-453F-877C-640AF0B82D26/serverlanguagepack.img"

    Kazakh = "http://download.microsoft.com/download/0/D/1/0D1FD1A6-9104-4E57-A531-DDD26EE82E8F/serverlanguagepack.img"

    Korean = "http://download.microsoft.com/download/0/0/D/00D60DFF-E7D2-4EA2-BF6B-0FD591ED7AC3/serverlanguagepack.img"

    }

    # loop through each hashtable item

    $lPacks.GetEnumerator() | ForEach-Object {

    $lang = $_.Name

    $link = $_.Value

    # create folder for each languge

    $destination = New-Item -Path "$downloadPath\$lang" -ItemType Directory

    # start download of language pack

    Start-BitsTransfer -Source $link -Destination $destination -DisplayName "Downloading $lang SharePoint Language Pack" -Priority High

    }

  • Office 365 - PowerShell Script to Create a List, Add Fields and Change the Default View all using CSOM

    I'm my continued quest to get to grips with the Client Side Object Model (CSOM) in SharePoint 2013, I have put together a sample script below that connects to a Site Collection within an O365 tenant and does the following:

    • Creates a list using the "Custom" list template
    • Adds two Site Columns to the list (City and Company)
    • Adds these fields to the default view
    • Adds an item to the list

    You may find this useful as a reference! The usual disclaimers apply :)

    All you need to run this script is an O365 tenant, the SharePoint client components SDK installed on the machine running the script - http://www.microsoft.com/en-us/download/details.aspx?id=35585 and to update the $User, $SiteURL and $ListTitle variables. When the script is executed it will prompt for the password of the user specific in the $User variable.

    #Specify tenant admin and site URL
    $User = "admin@tenant.onmicrosoft.com"
    $SiteURL = https://tenant.sharepoint.com/sites/site
    $ListTitle = "List Title"

    #Add references to SharePoint client assemblies and authenticate to Office 365 site - required for CSOM
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
    Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
    $Password = Read-Host -Prompt "Please enter your password" -AsSecureString
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)

    #Bind to site collection
    $Context = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($User,$Password)
    $Context.Credentials = $Creds

    #Retrieve lists
    $Lists = $Context.Web.Lists
    $Context.Load($Lists)
    $Context.ExecuteQuery()

    #Create list with "custom" list template
    $ListInfo = New-Object Microsoft.SharePoint.Client.ListCreationInformation
    $ListInfo.Title = $ListTitle
    $ListInfo.TemplateType = "100"
    $List = $Context.Web.Lists.Add($ListInfo)
    $List.Description = $ListTitle
    $List.Update()
    $Context.ExecuteQuery()

    #Retrieve site columns (fields)
    $SiteColumns = $Context.Web.AvailableFields
    $Context.Load($SiteColumns)
    $Context.ExecuteQuery()

    #Grab city and company fields
    $City = $SiteColumns = $Context.Web.AvailableFields | Where {$_.Title -eq "City"}
    $Company = $SiteColumns = $Context.Web.AvailableFields | Where {$_.Title -eq "Company"}
    $Context.Load($City)
    $Context.Load($Company)
    $Context.ExecuteQuery()

    #Add fields to the list
    $List.Fields.Add($City)
    $List.Fields.Add($Company)
    $List.Update()
    $Context.ExecuteQuery()

    #Add fields to the default view
    $DefaultView = $List.DefaultView
    $DefaultView.ViewFields.Add("City")
    $DefaultView.ViewFields.Add("Company")
    $DefaultView.Update()
    $Context.ExecuteQuery()

    #Adds an item to the list
    $ListItemInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
    $Item = $List.AddItem($ListItemInfo)
    $Item["Title"] = "New Item"
    $Item["Company"] = "Contoso"
    $Item["WorkCity"] = "London"
    $Item.Update()
    $Context.ExecuteQuery()


    Brendan Griffin