Return SPListItems using CSOM and PowerShell without writing CAML

I recently tweeted about my triumph when trying to accomplish returning all SharePoint List Items without the use of CAML or LINQ. The reason I wanted to do this might be strange, but I’ll try to explain my process and methodology and why I got to a point of wanting to make SharePoint do things it didn’t want to do. 🙂

As a very advanced SharePoint Scripter, I do a TON of PowerShell. If you’ve read this blog, follow me on Twitter or talk to me in person you probably knew that. Having said that, there are times when I want to iterate through all list items – either looking for a match or just to return all values. It’s not super common but it happens. Well it’s a very easy thing to do with server side code (read: PowerShell and the Microsoft.SharePoint.PowerShell snap-in).

Getting List Items using standard PowerShell

As you see on line 3, there is an Items collection property on the List object. This is great, end of story – IF you’re using server-side PowerShell code. However, I’ve been focusing a lot lately on integrating PowerShell into the CSOM space – specifically to manage SharePoint Online with PowerShell. If you’ve written any CSOM code, you know that things are done a little differently. Here’s an example of how to return a list item using PowerShell on the client-side – note that I’ve omitted about 12 lines of code that must take place before this to load the Microsoft.SharePoint.Client* assemblies, create ClientContext, get the SPWeb, etc.:

Getting a List Item using PowerShell Client-Side Code

That’s great, but if I wanted to return all items – the Client Object Model won’t give me List.Items. In reading MSDN, there are C# examples of how to write CAML queries to return all list items – but the whole point is that I don’t want to write CAML. Here’s the C# example – which I could have certainly translated to PowerShell if I wanted to do so:

Using C# to get all List Items

// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
ClientContext context = new ClientContext("http://SiteUrl");
// Assume the web has a list named "Announcements".
List announcementsList = context.Web.Lists.GetByTitle("Announcements");
// This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll"
// so that it grabs all list items, regardless of the folder they are in.
CamlQuery query = CamlQuery.CreateAllItemsQuery(100);
ListItemCollection items = announcementsList.GetItems(query);
// Retrieve all items in the ListItemCollection from List.GetItems(Query).
context.Load(items);
context.ExecuteQuery();
foreach (ListItem listItem in items)
{
// We have all the list item data. For example, Title.
label1.Text = label1.Text + ", " + listItem["Title"];
}

So that’s great, but here’s how I went about getting all list items without writing CAML! I’ll break it down section by section, but if you’re impatient the whole solution is at the bottom. 🙂

Creating our Context

The first thing we need to do when working with SharePoint from the Client Side is create ClientContext. To do so using PowerShell, here is some example code:

Getting our SPList

$SPList = $GLOBAL:Web.Lists.GetByTitle("BigListLotsOfItems") #Note that BigListLotsOfItems is my List Title

Using the For loop to iterate through all items

And this is where the magic happens as they say. For anyone who has done any level of development or scripting, you know that the best way to loop while also allowing for modification of the array with which you’re looping is to use a For loop.

For ($i=0; $i -le $SPList.ItemCount; $i++)
{
}

This is a pretty standard implementation of the For loop, what I want to call out though is the use of Try/Catch/Finally. As a dabbling developer, I’m not sure if this is the intended use of Try/Catch/Finally – so if this is bad practice forgive me. 🙂

Essentially I start out by creating the ListItem variable, and then calling the Load method of the ClientContext variable. I do that before entering the Try/Catch/Finally. I then use Try {} to run the Context.ExecuteQuery method, and if that fails the loop will go into the Catch {} block – where I will increment the array by 1 ($i++) and then run the GetItemById(), Load() and ExecuteQuery() methods against the next $i in the loop.

Why did I do this? Well it’s really pretty simple. Since I have to use the GetItemById() method, I have to know the ListItemID of each ListItem. If someone has deleted an item, the ItemCount property won’t match the highest ID in the list – right? So if there are 5 items but someone deleted a few at one point or another – the highest ID might be 7 or 8, without incrementing by 1 on a failure, we’ll never get to 7 or 8…

And so now that we’ve discussed all of that, here’s the final example script.

10 thoughts on “Return SPListItems using CSOM and PowerShell without writing CAML”

Isn’t be a bit chatty with server ? in your loop if you call load / execute query for each items, it has to call the server each time. If we use CAML query then it will be executed in a single shot from the server and you can retrieve the items as a batch.

Thanks for your reply. You are correct, this is definitely not a recommended solution for Production servers. This was more or less a proof-of-concept, I wanted to prove that it could be done without CAML.

This is a different request altogether, so I’m not sure that saying it would be better is fair – just different. In any case, if you’re trying to view security details on list items via CSOM, check out MSDN for the specific Methods and Properties available in the API. That should get you going, thanks!