EDIT: THIS PROJECT IS CONTINUED ON CODEPLEX!
Due to the success of this post I continued this as a project on CodePlex: https://sharepointpowershell.codeplex.com
But if you still want to continue reading this post, go ahead.
How it works
Download this file and extract the DLL to an easy location to reach from PowerShell. Because this assembly uses the Client Object Model you need to install the COM Redistributable as well.
These are the PowerShell commands to run:
You need to run PowerShell in single-threaded mode (the authentication requires it).
powershell -STA
Import the DLL.
[Reflection.Assembly]::LoadFile("D:\ClaimsAuth.dll")
Instantiate a new SPOContext providing your SharePoint Online site URL. (Don’t forget the https)
$spoContext = new-object SPOContext("https://jeffreypaarhuis.sharepoint.com")
Now, let’s test it:
$spoContext = new-object SPOContext("https://jeffreypaarhuis.sharepoint.com") $web = $spoContext.Web $spoContext.Load($web) $spoContext.ExecuteQuery() Write-Host $web.Title
As you already might understand, this solution is based on the SharePoint Client Object Model. This means that everything that’s possible with the COM is possible to script. This post explains how to work with Sites, Permissions, Documents, etc. with the COM. It is written in C# but it’s fairly easy to translate to PowerShell.
Samples
------------------- Init spoContext ------------------- powershell -sta [Reflection.Assembly]::LoadFile("D:\ClaimsAuth.dll") $spoContext = New-Object SPOContext("https://mysharepointonline.sharepoint.com") ------------------- Print sitename ------------------- $web = $spoContext.Web $spoContext.Load($web) $spoContext.ExecuteQuery() $web.Title ------------------- Add property to bag ------------------- $web.AllProperties.FieldValues.Add("propA","Property A") $spoContext.ExecuteQuery() $web.AllProperties.Item("propA") ------------------- Show features ------------------- $site = $spoContext.Site $spoContext.Load($site) $spoContext.ExecuteQuery() $features = $site.Features $spoContext.Load($features) $spoContext.ExecuteQuery() $features ------------------- Permissions stuff ------------------- Function GetWeb { $ctx.ExecuteQuery() Return $ctx.Web } Function GetList ($name) { $web = GetWeb if ($web -ne $null) { $lists = $web.Lists $ctx.Load($lists) $ctx.ExecuteQuery() $list = $lists | where {$_.Title -eq $name} return $list } return $null } Function GetRole ($rType) { $web = GetWeb if ($web -ne $null) { $roleDefs = $web.RoleDefinitions $ctx.Load($roleDefs) $ctx.ExecuteQuery() $roleDef = $roleDefs | where {$_.RoleTypeKind -eq $rType} return $roleDef } return $null } Function GetPrincipal ($name) { $web = GetWeb if ($web -ne $null) { $principal = $web.EnsureUser($name) $ctx.Load($principal) $ctx.ExecuteQuery() return $principal } return $null } Function GetGroup ($name) { $web = GetWeb if ($web -ne $null) { $groups = $web.SiteGroups $ctx.Load($groups) $ctx.ExecuteQuery() $group = $groups | where {$_.Title -eq $name} return $group } return $null } Function GetDocumentLibrary ($name) { $web = GetWeb if ($web -ne $null) { $docLibs = $web.Lists $ctx.Load($docLibs) $ctx.ExecuteQuery() $docLib = $docLibs | where {$_.Title -eq $name} return $docLib } return $null } $web = GetWeb $web.BreakRoleInheritance($true, $false); $principal = GetGroup "MyGroup" $roleType = [Microsoft.SharePoint.Client.RoleType]"Contributor" $role = GetRole $roleType $collRdb = new-object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx) $collRdb.Add($role) $collRoleAssign = $web.RoleAssignments $collRoleAssign.Add($principal, $collRdb) $ctx.ExecuteQuery() $list = GetList "Shared Documents" $list.BreakRoleInheritance($false, $false); $roleType = [Microsoft.SharePoint.Client.RoleType]"Reader" $role = GetRole $roleType $collRdb = new-object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($ctx) $collRdb.Add($role) $collRoleAssign = $list.RoleAssignments $collRoleAssign.Add($principal, $collRdb) $ctx.ExecuteQuery()
Errors?
You might see the following errors from time to time, which aren’t a big deal:
– “The requested site does not appear to have claims enabled or the Login Url has not been set.”.
Problem: This usually means that no session can be instantiated (SharePoint Online bug).
Solution: Navigate to your site in Internet Explorer, when your site doesn’t show, refresh it a few times until it shows, or go to https://portal.microsoftonline.com. When you get a login page, go back to your script.
– “The remote name could not be resolved: ‘mysp.sharepoint.com'”
Problem: During scripting, the context timed out.
Solution: Re-instantiate the $spoContext object. When running a script in one go, this error shouldn’t pop because the Context will not prematurely expire.
Under the hood
How does it work under the hood? What’s in the DLL? What makes SharePoint Online so difficult?
In line with this one I’ve written a post that explains what the problem with SharePoint Online is and how to build your own DLL. Read it here.
UPDATE (11-7-2012):
Forgot to mention you need to install the COM Redistributable.
UPDATE (3-9-2012):
Added samples.
Pingback: PowerShell for SharePoint Online: Under the hood | Jeffrey Paarhuis SharePoint Blog
Hi there,
I’m trying to follow these instructions and I am getting the following error:
New-Object : Cannot find type [SPOContext]: make sure the assembly containing this type is loaded.
Even though it claims the DLL is loaded:
GAC Version Location
— ——- ——–
False v2.0.50727 c:\ClaimsAuth.dll
I am have tried running PS as Admin or normal user and also tried the -STA mode.
Any ideas as to what I am doing wrong?
Hi Alan,
Can you tell me if you’re running from a 32-bit environment? This assembly is compiled for a 64-bit system.
Thanks
Yep 32 bit. Ah well.
I’ve updated my post with a 32-bit assembly, check it out!
I get the same error. Did you change the version of the DLL? The Version number is coming up the same
PS C:\> .\get-sharepointstats.ps1
GAC Version Location
— ——- ——–
False v2.0.50727 c:\ClaimsAuth.dll
New-Object : Cannot find type [SPOContext]: make sure the assembly containing this type is loaded.
Hi,
i get the same error, tested on 32 bit machine with the 32 bit dll, and the 64 bit dll on a 64 bit machine.
The DLL claims to load ok..
I would be SO great if i can access our sharepoint through PS….
PS C:\Users\Administrator> $spoContext = new-object SPOContext(“https://******.sharepoint.com”)
New-Object : Cannot find type [SPOContext]: make sure the assembly containing this type is loaded.
Sorry guys, I forgot to mention you have to install the Client Object Model Redistributable.
My bad! You can install it from here: http://www.microsoft.com/en-us/download/details.aspx?id=21786
Thanks Jeffrey, it works now! 😉
very cool.
Pingback: What is PowerShell and why should I use it?
Thanks! Awesome article!
Is it possible to automate the credential login that appears when instantiating a new SPOContext, say passing a PSCredential?
The CSOM needs a session that can only be instantiated via the HTML form of Office 365. That’s why you’re getting the popup. However, I think it might be possible with some kind of JavaScript insertion or a scripted https/html poster in powershell (don’t know if it exists). Either way, there’s no neat solution to this. But if you got it working, please let me know, cause it’s always one less step to take.
I always get the error with loading the ClaimsAuth.dll:
Exception calling “LoadFile” with “1” argument(s): “An attempt was made to load an assembly from a network location which would have caused the assembly to be sandboxed in previous versions of the .NET Framework. This release of the .NET Framework does not enable CAS policy by default, so this load may be dangerous. If this load is not intended to sandbox the assembly, please enable the loadFromRemoteSources switch. See http://go.microsoft.com/fwlink/?LinkId=155569 for
more information.”
At C:\Scripts\Deployment\Deploy.ps1:XX char:XX
+ $assembly = [Reflection.Assembly]::LoadFile <<<< ($file); + CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : DotNetMethodException
I already tried to create a new powershell.exe.config file. What am i doin wrong?
Thx in advance…
What happens if you run the [Reflection.Assembly]::LoadFile(“xxx\ClaimsAuth.dll”) straight from the powershell console?
It happens the same. Same Error. How can i enable the CAS policy.
I see what the issue is. Rightclick ClaimsAuth.dll > properties > unblock.
Seems to be a security feature of Microsoft that blocks all downloaded DLL´s.
I also encountered this issue! But unblocking it did the trick! Thanks, Jeffrey!
Hi !
first of all.. awesome article !
I use this trick a lot.
However, there is something I can’t get done. I don’t know if it’s feasible or not.
When I retrieve a SPWeb with the Load method of the client object model, not all properties are returned. By example “HasUniqueRoleAssignments” is missing. This is the normal behaviour.
I know there is a way using c# or javascript
http://msdn.microsoft.com/en-us/library/ee534974(v=office.14).aspx
but I can’t manage to convert it to PowerShell…
Have you heard about this issue ?
Thanks
Thanks!
About the missing properties, you can make it possible. Have you looked at my “under the hood” post? Here is it: http://jeffreypaarhuis.com/2012/06/14/powershell-for-sharepoint-online-under-the-hood/
You can build your own DLL and write a function in the SPOContext class that retrieves your missing properties.
Please let me know if you need any help.
Thanks for your reply ! I will try your technique pretty soon.
I just tested it and… it worked 🙂 !
I took the liberty to post the code here because it took me some time to figure out how to do this.
Here is an example of Load function that can be used to retrieve “HasUniqueRoleAssignments” property.
I put it in SPOContext class and could use it in powershell instead of the traditionnal Load method.
public void LoadSPWebWithBreakRoleInheritance(ClientObject objectToLoad)
{
Web webToRetrieve = (Web) objectToLoad;
base.Load(webToRetrieve, website => website.Title, website => website.HasUniqueRoleAssignments);
}
The “website => website.Title,” part is useless because the Title is retrieved by default, but you can retrieve other properties instead.
Again thanks for sharing your discoveries.
Hi!
We’re using Sharepoint Online with AD Integration, and if i try to authenticate, I get an http error 401:
1 first broweser call is working korrektly, but if i enter my username
2 press tap
3 got the message that I’ll be redirected to loginpage of my organisation
4 got the http error 401
At the moment there’s no federated AD support. The authentication requires another technique. However I’m looking into making this possible.
Hi,
Superb and very helpful article, though I have got myself stuck in a little problem.
I am trying to get sites created within the site collection using this method.
I am presuming it is possible since client object model supports it.
Using your examples I have the following code working:
[Reflection.Assembly]::LoadFile(“D:\ClaimsAuth.dll”)
$spoContext = new-object SPOContext(“https://xxx.sharepoint.com/sites/Main”)
$web = $spoContext.Web
$spoContext.Load($web)
$spoContext.ExecuteQuery()
$web = $spoContext.Web
$spoContext.Load($web)
$spoContext.ExecuteQuery()
$webs = $web.Webs
$spoContext.Load($webs)
$spoContext.ExecuteQuery()
I have a class (WCInformation) which has a method (GetCreationInfo) that returns a WebCreationInformation object which is valid and is being used as:
$wcInfo = new-object WCInformation
$testSite = $wcInfo.GetCreationInfo(“test”)
$webs.Add($testSite)
The final line is causing the issue.
webs is not null but is returning:
format-default : 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.
Any help or wisdom would be much appreciated.
Many thanks
Chris
If I were you, I would find the C# or VB method for this and then translate it to PowerShell. I believe there are some examples on the MSDN. Let me know if you can get it working.
Hi Jeffrey,
Thanks for your reply.
We currently use C# to create sites on feature activation.
The code used is:
rootWeb.Webs.Add(url, siteName, siteDesc, Convert.ToUInt16(1033), siteTemplate, false, false);
Unfortunately, as the requirement is SharePoint Online, we get awful timeouts and have to split the site creation into multiple manually activated features.
Could the above code be used as I believe that the client object model would be the only way forward with PowerShell.
Many thanks for your time
Chris
Well, if the timeouts are the problem, then I might have a workaround for that because I’ve faced the same limitation with SharePoint online.
What I’ve used is JavaScript on the page created that does the stuff you normally would use the feature receiver for. You can use Sharepoint ECMA-script for that.
Have you an sample with download file from document library?
I know this is possible with a stream, but I have no sample code for you unfortunately.
Hi,
this script seems to work for attachments of list items. So if you have the url of your document it should work for document library files too.
http://social.msdn.microsoft.com/Forums/sharepoint/en-US/3f707e4f-ce26-4237-85d6-5ed47caf5a80/powershell-script-to-copy-a-list-attachment-to-a-file
I’m sorry, the link I posted doesn’t work for sharepoint online. But I need this feature too for my script, working on it.. if you already solved the problem don’t hesitate to post it 😉
Beginner here so real quick: How is the variable $ctx set? Is it the same as $spoContext?
thanks for this though – great stuff
yes $ctx and $spoContext are essentially the same
Pingback: Using Powershell and CSOM to remotely manager Office365 | asksven
Hi,
A massive thanks for this page. It helped me a lot but….
I’m getting an error for the roledefinationcollection which is “new-object : Cannot find an overload for “RoleDefinitionBindingCollection” and the argument count: “1”.
At C:\scripts\SharepointScripts\authPerm.ps1:115 char:12
+ $collRdb = new-object Microsoft.SharePoint.Client.RoleDefinitionBindingCollectio …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand”
Can you tell me what happening?
Thanks
Mark
Hi. I was wondering if you could help me. I’ve been trying to use you and adapt it for my need. I simply want to add a group to the library and web but I get an error, I think with the principal part. I’ve posted over at stack overflow and wondered if you could have a look.
http://stackoverflow.com/questions/21767514/powershell-csom-sharepoint-online-list-permission
thanks
Mark
Mark, I’ve been working on a codeplex project that is an evolution of the things I describe in this blog. It still needs a lot of other features, but the things you ask about are already there: https://sharepointpowershell.codeplex.com
Hello,
i followed your instructions, but it doesn’t seem to work.
First of all, i get the “False” Message from the DLL:
GAC Version Location
— ——- ——–
False v2.0.50727 c:\ClaimsAuth.dll
Doesn’t matter if i try running Powershell as admin, use powershell -STA or using Powershell for SharePoint online.
I am running from a 64 bit environment, the COM Redistributable are installed too.
The connection with SharePoint Online works, but if i want to add properties – like your Add Property to a bag sample:
$web.AllProperties.FieldValues.Add(“propA”,”Property A”)
$spoContext.ExecuteQuery()
$web.AllProperties.Item(“propA”)
there is no saving of the changes. Powershell shows the added properties in the first run (it is in the cache i assume) but when i open a new shell and want to log in again, the properties are no longer found.
Do you have maybe any hint, what the problem could be?
Possibly the “False” with the DLL would be my guess, but how can i change this?
Thanks in advance for your help,
Andrew
Andrew, I really recommend you to look at my project https://sharepointpowershell.codeplex.com which can do the same.
If you have any trouble with that, please let me know.
– Jeffrey
This is great stuff..do you know i can get all the items in a library
when i try to do
$list = $SPOcontext.Web.Lists.GetByTitle(“Documents”)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(10000, ‘UniqueId’,’ID’,’Created’,’Modified’,’FileLeafRef’,’Title’)
i get an error
Cannot convert argument “query_”, with value: “Microsoft.SharePoint.Client.CamlQuery”, for “GetItems” to type “Microsoft.SharePoint.Client.CamlQuery”: “Cannot convert the
“Microsoft.SharePoint.Client.CamlQuery” value of type “Microsoft.SharePoint.Client.CamlQuery” to type “Microsoft.SharePoint.Client.CamlQuery”.”
any ideas will be much appreciated