Update a SharePoint List remotely with PowerShell

Yesterday I got a comment on my blog post Update a SharePoint List with PowerShell asking if it is possible to remotely update a SharePoint list. This means that you have to execute the UpdateListItem method of the Lists.asmx web service of SharePoint.

It is possible to work with the SharePoint web services from within SharePoint. There are already some good posts around:

- Calling a Web Service from PowerShell which explains the steps to take before you can consume a Web Service

- Consuming SharePoint Web Services from PowerShell which explains how to get a list from the Lists Web Service.

In this post I'll explain the steps how to execute the UpdateListItem method.

First load the Visual Studio tools into your Powershell environment:

$env:VSINSTALLDIR="C:\Program Files\Microsoft Visual Studio 8"

$env:VCINSTALLDIR="C:\Program Files\Microsoft Visual Studio 8\VC"

$env:DevEnvDir="$env:VSINSTALLDIR\Common7\IDE"

$env:FrameworkSDKDir="$env:VSINSTALLDIR\SDK\v2.0"

$FrameworkPath=$([System.Runtime.InteropServices.RuntimeEnvironment]::GetRuntimeDirectory())

$env:FrameworkDir=$(split-path $FrameworkPath -Parent)

$env:FrameworkVersion=$(split-path $FrameworkPath -Leaf)

$env:PATH="$env:VSINSTALLDIR\Common7\IDE;$env:VCINSTALLDIR\BIN;$env:VSINSTALLDIR\Common7\Tools;$env:VSINSTALLDIR\Common7\Tools\bin;$env:VCINSTALLDIR\PlatformSDK\bin; $env:FrameworkSDKDir\bin;$env:FrameworkDir\$env:FrameworkVersion;$env:VCINSTALLDIR\VCPackages;$env:PATH"

$env:INCLUDE="$env:VCINSTALLDIR\ATLMFC\INCLUDE; $env:VCINSTALLDIR\INCLUDE;$env:VCINSTALLDIR\PlatformSDK\include;$env:FrameworkSDKDir\include;$env:INCLUDE"

$env:LIB="$env:VCINSTALLDIR\ATLMFC\LIB; $env:VCINSTALLDIR\LIB;$env:VCINSTALLDIR\PlatformSDK\lib;$env:FrameworkSDKDir\lib;$env:LIB"

$env:LIBPATH="$FrameworkPath; $env:VCINSTALLDIR\ATLMFC\LIB"

As explained in other posts, you can put this in your profile so that these tools are loaded each time you run Powershell.

Then execute the following commands to compile the Lists web service:

PS>wsdl http://[site url]/_vti_bin/Lists.asmx

PS>csc /t:library Lists.cs

PS>[Reflection.Assembly]::LoadFrom("Lists.dll")

Once this is done you can place the following statement in your profile so that it is executed each time you run Powershell:

[void][Reflection.Assembly]::LoadFrom("Lists.dll")

Instantiate the lists web service:

PS> $listservice = New-Object Lists

You have to be authenticated to contact the web service:

$listservice.Credentials=[System.Net.CredentialCache]::DefaultCredentials

My example uses a computers list:

powershell updatelistitems before

There is a mistake in the title of the second item, which need to be corrected.

The method you need to use to update a list item is the UpdateListItems. This method asks for 2 arguments: the name of the list and a batch query. First a string is build with the CAML needed to update the list item and then the UpdateListItems method is executed:

PS>$query = "<Batch OnError='Continue'><Method ID='1' Cmd='Update'><Field Name='ID'>2</Field><Field Name='Title'>Laptop 2</Field></Method></Batch>"

PS>$listservice.UpdateListItems("Computers", $query)

In fact the second argument of the UpdateListItems method is an xml node but if the query string contains valid xml, it is implicitly converted into an xml node before it is passed to the UpdateListItems method. If you want to explicitly use an xml node you can write the following:

PS>[xml]$query = "<Batch OnError='Continue'><Method ID='1' Cmd='Update'><Field Name='ID'>2</Field><Field Name='Title'>Laptop 2</Field></Method></Batch>"

And here is the result of the udpate:

powershell updatelistitems after

For more information about working with xml nodes, i refer to the post of Dan Sullivan.

As you can see I can use CAML in a lot of different ways :)