La idea de este post es doble:
Mostrar como desde Powershell podemos obtener información de Sharepoint ayudándonos con programación .Net
- Concretamente Web Services en este caso
- Reutilizar más adelante este módulo en un ejemplo más complejo
Hemos visto en un post anterior que podemos invocar nuestras propias librerías desde Powershell y que mediante una simple instrucción ( [appdomain]::currentdomain.getassemblies() ) podemos saber que librerías .Net están disponibles.
Si así lo hacemos una línea del output dirá [True v2.0.50727 C:\Windows\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System.Xml.dll] lo cual nos da la pauta de que podemos utilizar System.Xml sin agregar ninguna referencia (lo cual era de esperar dada la naturaleza de Powershell).
Ya Lluis Franco ha creado un artículo interesante en el que – entre otras cosas – y bajo el título Agregando referencias a los servicios Web de SharePoint muestra como referenciar dichos servicios.
Vamos a utilizar esos servicios para consultar una lista de Sharepoint.
En este caso porque considero que Visual Basic es más práctico que C# para usar LINQ to Xml crearemos un proyecto de librería en dicho lenguaje y allí agregaremos la referencia.
Para vincular objetos de System. Xml con LINQ utilizo una versión de las extensiones a XElement y XmlNode creadas por Eric White:
Código del módulo de extensión
Imports System.Xml
Module modLinqXML
<System.Runtime.CompilerServices.Extension()> _
Public Function GetXmlNode(ByRef element As XElement) As XmlNode
Using xmlReader As XmlReader = element.CreateReader()
Dim xmlDoc As XmlDocument = New XmlDocument
xmlDoc.Load(xmlReader)
Return xmlDoc
End Using
End Function
<System.Runtime.CompilerServices.Extension()> _
Public Function GetXElement(ByRef node As XmlNode) As XElement
Dim xDoc = New XDocument()
Using wri As XmlWriter = xDoc.CreateWriter()
node.WriteTo(wri)
End Using
Return xDoc.Root
End Function
End Module
En cuanto al código
que obtiene los registros es muy sencillo y está basado en la función GetListItems del servicio Web, aquí va la clase completa:
Imports System.Xml
Imports System.Xml.Linq
Imports System.Net
Imports WSClientVB.listService
Public Class Reader
Shared listsSVC As New Lists
Public Shared Function GetRecords (ByVal urlWeb As String, ByVal listName As String) As XmlNode
listsSVC.Credentials = CredentialCache.DefaultCredentials
'Elementos XML requeridos por GetListItems
Dim queryOptions As XElement = _
<QueryOptions>
<Folder/>
<IncludeMandatoryColumns>true</IncludeMandatoryColumns>
</QueryOptions>
Dim viewFields = <ViewFields>
<FieldRef Name="ID"/>
<FieldRef Name="FirstName"/>
<FieldRef Name="MiddleName"/>
<FieldRef Name="LastName"/>
<FieldRef Name="EmailAddress"/>
<FieldRef Name="Phone"/>
<FieldRef Name="ModifiedDate"/>
<FieldRef Name="EncodedAbsUrl"/>
</ViewFields>
Dim qry = <query></query>
'Elementos XML requeridos por GetListItems
Dim rowLimit = Convert.ToString(50) 'Manejamos la cantidad de registros que queremos manejar
Dim lista = listsSVC.GetListItems(listName, "", Nothing, viewFields.GetXmlNode, rowLimit, queryOptions.GetXmlNode, "")
Return lista
End Function
End Class
Ya con estos elementos podemos escribir el script de Powershell
necesario para cumplir con nuestros objetivos:
$SPClientLib=[System.Reflection.Assembly]::Loadfile("M:\Training\Screencasts\Office y Sharepoint\Code\OOXML_WS\WSClientVB\bin\Debug\WSClientVB.dll")
function Format-XML ([xml]$xml, $indent=2)
{
$StringWriter = New-Object System.IO.StringWriter
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
$xmlWriter.Formatting = "indented"
$xmlWriter.Indentation = $Indent
$xml.WriteContentTo($XmlWriter)
$XmlWriter.Flush()
$StringWriter.Flush()
Write-Output $StringWriter.ToString()
}
[System.Xml.XmlNode]$Contactos = [WSClientVB.Reader]::GetRecords("http://moss:20001", "Contacts")
Format-XML $Contactos.OuterXml -indent 4
Y ya con todo este material visto pueden pasar al video asociado:
Reutilizaremos este material en un próximo post, hasta luego.