6

I'm trying to grant a user permission to a SharePoint site using PowerShell and the client object model. The code I'm using is as follows:

# Setup context
$context=New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$web=$context.Web

# New user object
$user=$web.EnsureUser("domain\username");

# Role definition
$rd = $web.RoleDefinitions.GetByName("Full Control")

# Create role definition binding collection
$rdbc=New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context)
$context.ExecuteQuery();
$rdbc.Add($rd)

$context.Web.RoleAssignments.Add($user, $rdbc)

$context.ExecuteQuery();

This fails on the $context.Web.RoleAssignments.Add($user, $rdbc) line with the following exception:

The collection has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested. At :line:0 char:0

I've tried placing additional ExecuteQuery statements around the RoleAssignments.Add call but the result is the same.

Any ideas?

  • You actually get that at every line that creates a SharePoint object. All the properties of $web, etc are that way... – Robert Kaucher Aug 23 '12 at 17:44
5

I have been looking at your problem and it seems that the issue is the Load method on the ClientContext object. You cannot use it because it is an extension method expecting a type. PowerShell does not get along well with generics. See MSDN article here.

public void Load<T>(
    T clientObject,
    params Expression<Func<T, Object>>[] retrievals
)
where T : ClientObject

This article explains how to get the managed client side object model code to work with PowerShell. If you ask me, it is just too much work.

http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/15/using-powershell-to-get-data-from-a-sharepoint-2010-list.aspx

EDIT:

Here is an image showing the $web variable and its properties... They all have that error because $web has not been loaded via $context.Load().

enter image description here

Edit 2:

I tried getting this to work with some inline C# in a PowerShell script but it just wasn't useful. If you don't have a copy of VisualStudio you can download Visual C# Express 2010 for free. Just create a new project, add the SharePoint.Client DLLs and here is the C# code to do what you want. You can make it a console app that takes params if you want.

class Program
    {
        static void Main(string[] args)
        {
            ClientContext ctx = new ClientContext("http://domain-dev/");
            Web web = ctx.Web;
            ctx.Load(web);
            ctx.ExecuteQuery();
            Console.WriteLine(web.Title);

            User user = web.EnsureUser("domain\\bdobbs");
            ctx.Load(user);
            ctx.ExecuteQuery();

            Console.WriteLine(user.Email);

            var rd = web.RoleDefinitions.GetByName("Full Control");
            ctx.Load(rd);
            ctx.ExecuteQuery();

            Console.WriteLine(rd.Description);

            RoleDefinitionBindingCollection rdbc = new RoleDefinitionBindingCollection(ctx);
            ctx.Load(rdbc);
            ctx.ExecuteQuery();

            rdbc.Add(rd);
            web.RoleAssignments.Add(user, rdbc);
            web.Update();
            ctx.ExecuteQuery();

            Console.Read();


        }
    }
7

I was able to get it working in PowerShell with the CSOM via the following code. It's basically the same as Robert Kaucher's (in PowerShell format) with a minor change towards the end.

Add-Type -Path "C:\Program Files\Common Files\microsoft shared\SharePoint Client\Microsoft.SharePoint.Client.dll" 
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\SharePoint Client\Microsoft.SharePoint.Client.Runtime.dll"

$Ctx = New-Object Microsoft.SharePoint.Client.ClientContext("SharePointSiteURL")

$Web = $Ctx.Web

$Ctx.Load($Web)
$Ctx.ExecuteQuery()
Write-Host $Web.Title

$User = $Web.EnsureUser("domain\UserID")
$Ctx.Load($User)
$Ctx.ExecuteQuery()
Write-Host $User.Email

$RD = $Web.RoleDefinitions.GetByName("Full Control")
$Ctx.Load($RD)
$Ctx.ExecuteQuery()
Write-Host $RD.Description

$RDBC = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Ctx)
$Ctx.Load($RDBC)
$Ctx.ExecuteQuery()

$RDBC.Add($RD)
$ctx.Load($Web.RoleAssignments.Add($User, $RDBC))
$Web.Update()
$Ctx.ExecuteQuery()
  • 1
    Wow - that seems so much easier than switching languages. Thanks! – Josiah May 3 '16 at 21:29
  • 1
    Thanks - that really helped. I was getting hung up because I wasn't doing a $ctx.Load on the new role assignment (3rd to last line of your code). – Kirk Liemohn Jul 14 '16 at 18:28
  • 1
    The trick with context.Load the query deserves this post to be upvoted ! – Hybris95 Oct 3 '16 at 8:20
0

can you check this link out and see if it can help you as he is doing somthing similar to you!

http://www.mavention.nl/blog/granting-permissions-user-profile-service-application-powershell

and this:

http://emmettlynch.wordpress.com/2012/01/06/add-a-sharepoint-or-ad-groupuser-to-all-sites-in-a-site-collection-using-powershell/

0

You will need to ClientContext.Load() the objects which you will be modifying. Namely, I will suggest you try this following code:

# Setup context
$context=New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$web=$context.Web

//Load the $web object here.

# New user object
$user=$web.EnsureUser("domain\username");

//load the $user object here.

# Role definition
$rd = $web.RoleDefinitions.GetByName("Full Control")

# Create role definition binding collection
$rdbc=New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context)

//load the $rdbc object here.

$context.ExecuteQuery();

$rdbc.Add($rd)

$context.Web.RoleAssignments.Add($user, $rdbc)

$context.ExecuteQuery();

Here is a link which is pure client object model code to achieve what you are trying to do. Please modify the syntax for powershell as necessary. http://blogs.technet.com/b/speschka/archive/2009/11/01/using-the-sharepoint-2010-client-object-model-part-5.aspx

  • 1
    this cannot be done in pure PowerShell. See my answer above. The load method just doesn't work in PowerShell. – Robert Kaucher Aug 23 '12 at 19:01
0

For me it was enough to place RoleAssignments.Add() operation inside $context.Load():

# User or group name
$name = "User1"

# Principal
$principalInfo = [Microsoft.SharePoint.Client.Utilities.Utility]::ResolvePrincipal($context, $context.Web, $name, [Microsoft.SharePoint.Client.Utilities.PrincipalType]::All, [Microsoft.SharePoint.Client.Utilities.PrincipalSource]::All, $null, $true)
$context.ExecuteQuery()
if ($principalInfo.Value.PrincipalType -eq [Microsoft.SharePoint.Client.Utilities.PrincipalType]::User) {
    $principal = $context.Web.EnsureUser($principalInfo.Value.LoginName);
} else {
    $principal = $context.Web.SiteGroups.GetById($principalInfo.Value.PrincipalId);
}

# Role
$roleDefinition = $context.Web.RoleDefinitions.GetByName("Full Control")
$roleDefinitionBindings = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($context)
$roleDefinitionBindings.Add($roleDefinition)

# Add Principal with Role
$context.Load($roleAssignments.Add($principal, $roleDefinitionBindings))
0

instead of just adding the Assignments, assign the result to a variable, like so :

$roleAssignments= $web.RoleAssignments

$result=$RoleAssignments.Add($user,$rdbc)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.