For quite a while now I’ve been pointing out the lack of cmdlets that are available for working with Office 365 and SharePoint 2013 (SharePoint Online) and I’ve mentioned several times that someone should really do something about that and that I’d love to be that person if only I had the time. Well, as it turns out, over Christmas break I managed to find some free time so I went ahead and got started on my own custom cmdlets for SharePoint Online which I’m now officially releasing with this post.
If you refer back to my earlier post where I detailed the SharePoint Online cmdlets provided by Microsoft, you’ll note that there are currently only 30 cmdlets – with my new offering I just about double that number by adding an additional 27 cmdlets. I’m only going to briefly outline my design goals and a couple simple examples in this article so I encourage you to visit the releases page to download the installer and/or source code for the project.
In creating the cmdlets I had two core goals that I wanted to achieve: first I wanted to add some basic retrieval functionality for common objects such as
SPList objects so that I could do some simple discovery type operations just as I would with SharePoint on-premises cmdlets; second, I wanted to make working with the cmdlets and the objects returned by them much more like working with the on-premises API so that you don’t have to think about calling the Load and ExecuteQuery methods every time you try to do something. To accomplish these goals I had to not only create the actual cmdlets themselves (which was the easy part) but I also had create custom wrapper objects for several of the objects in the Microsoft.SharePoint.Client namespace. For example, when you call my
Get-SPOWeb cmdlet what you get back is an
SPOWeb object, not a
Microsoft.SharePoint.Client.Web object. By taking this approach I an avoid the common uninitialized property errors that you’d see when you output the object to the PowerShell console. These errors makes working with the native objects nearly impossible as it requires you to know which properties are initialized and which ones aren’t – by creating a wrapper object I can hide this issue and make working with the objects very simple. I can also do things like create an Update method which handles the calling of the ExecuteQuery method as well as the refresh of the object, again, taking a lot of the nuances of working with the .NET CSOM API out of the picture. For those of you not familiar with working with the .NET CSOM API (and for those that are) the point to take away from all my technical babbling is that using my cmdlets will make working with SharePoint Online very similar to working with SharePoint on-premises.
Let’s take a look at how we can use my cmdlets. First off you need to download and install the cmdlets – I’ve created the cmdlets so that they work just like the Microsoft provided SharePoint Online cmdlets in that I just created a PowerShell V3 module manifest which references a binary assembly (dll) that contains all the cmdlets. All the installer does is put all the required files (dependent Microsoft.SharePoint.Client dlls, my assembly containing the cmdlets themselves, and the PowerShell help and format file) into an appropriate directory and then adds the path to that directory to the PSModulePath environment variable. This makes cmdlets available without having to manually load the module and is just like what the Microsoft SharePoint Online cmdlets do. Note that Microsoft provides a shortcut for the SharePoint Online Management Shell which is simply a PowerShell console with the module explicitly loaded but use of the management shell is completely unnecessary so I don’t bother creating an equivalent shortcut. To see that the module is installed correctly simply open any PowerShell console and run the
Get-Module cmdlet passing in the
-ListAvailable parameter. You should see the module listed as shown below:
With the cmdlets installed you can now connect to a Site Collection using the
Connect-SPOSite cmdlet. Note that the majority of my cmdlets are scoped to a single Site Collection and you must establish a connection to that Site Collection before you can do anything else; if you need to work on a different Site Collection then you’ll need to call
Connect-SPOSite again. In this example I’m connecting to a site by providing my username and the Site Collection to connect to:
1Connect-SPOSite -Credential "firstname.lastname@example.org" -Url "https://contoso.sharepoint.com"
I recommend you actually create a variable to store you credential information (
$cred = Get-Credential) so that you can reuse the information each time you connect to a different Site Collection. Oh, and as a bonus, though the default behavior is to connect to SharePoint Online, if you pass in the
–NetworkCredentials switch parameter then you can use these cmdlets against SharePoint on-premises – you’re welcome. To kill a connection use the
Disconnect-SPOSite cmdlet (I particularly recommend you do this when creating scripts, not much point if you’re just doing something one-off in the console but if you writing a script you want to make sure you kill your context so someone can’t come behind you and hijack your credentials – this is absolutely the same pattern that the Microsoft SharePoint Online cmdlets follow so if you’re familiar with them this should not be new to you).
Once you’ve established a connection you’re ready to start using the other cmdlets. If you’d like to retrieve the root Site (
SPWeb) or a child Site you can use the Get-SPOWeb cmdlet as shown:
1$rootWeb = Get-SPOWeb –Identity "/" -Detail 2 3$childWeb = Get-SPOWeb –Identity "/test" -Detail
–Detail parameter which is useful when you want to see as much information as possible. If you’re just looking for a list Sites then I would omit the parameter so that you’re bringing back less information which should help it to run a little faster (to see all the Sites omit the
When you get back an object I encourage you to use the Get-Member cmdlet (aliased as gm) to see the list of properties and methods available. All of my cmdlets will return my own SPO* wrapper object you can always get back to the original
Microsoft.SharePoint.Client object via a property on my object. The fact is I couldn’t wrap every single sub-object or every single property and method so there will be times when you’ll have to use the native object but hopefully what I did provide will at least cover a 80% of the common use cases (I hope). The following screenshot shows the members for the SPOWeb object:
Notice the highlighted Web property which you can use to get to the original
Microsoft.SharePoint.Client.Web object. If you need to update any properties on the object you can either use the
Set-SPOWeb cmdlet or update the property directly on the object and then call the
Update() method – no need to call
ExecuteQuery and then refresh the object, it’s all handled for you.
I don’t want to spend time going through every cmdlet and object that I’ve created as I detail each of the cmdlets on my command index page and the object members are easily discovered using the
Get-Member cmdlet so to wrap up I want to simply point out that this is definitely a work in progress and will hopefully grow over time. Also, I don’t claim to be a .NET CSOM expert so there may be some areas that can be improved upon from a performance point of view so if you download the code and see something that can be improved please share you feedback, or if you see anything else that can be improved again, please share (note that I’m absolutely horrible when it comes to responding to comments on my blog but I do eventually get to them all, just not necessarily very quickly).
Have fun and happy PowerShelling!