Probablemente, si se le preguntara a algún administrador de la familia de servidores de Microsoft, cuál es la herramienta sin la cual no podría vivir, éste le diría Windows PowerShell. Y hablamos de un producto que se puede considerar relativamente “nuevo”. No obstante, desde su lanzamiento el 25 de Abril de 2006, ya se vio el potencial de este intérprete de comandos (shell), que permitía automatizar tareas administrativas de una manera rápida, sencilla y eficiente.
Los administradores y desarrolladores de SharePoint, tuvieron que esperar hasta la versión 2010 para ver qué se estaban perdiendo. Si bien anteriormente contaban con la herramienta STSADM* para realizar ciertas operaciones administrativas, el cambio a Windows PowerShell, me atrevería a decir, fue comparable al cambio que se produjo a principios del siglo pasado al pasar de los vehículos tirados por caballos, a los nuevos vehículos a motor (dentro de su contexto, obviamente).

NOTA: La herramienta STSADM no se ha eliminado. Sigue presente incluso en SharePoint 2013. La podemos encontrar bajo la ruta C:Program FilesCommon Filesmicrosoft sharedWeb Server Extensions15BIN

Lo que se pretende en el siguiente artículo, es conocer las bondades que ofrece el intérprete de comandos Windows PowerShell, pero enfocado al desarrollador SharePoint. Al cabo del día/semana/mes, un desarrollador de SharePoint se enfrenta a tareas comunes, tales como el desarrollo de elementos webs (WebParts) y su posterior despliegue en una o varias páginas web, el despliegue del paquete de una solución, la modificación masiva de elementos de listas por cualquier motivo, etc. Si bien estas tareas, pueden ser resueltas “como toda la vida se ha hecho”, la ayuda de Windows PowerShell supone un aumento de la productividad increíble, al ver reducida dicha tarea, a un guion o script de PowerShell, que puede ser lanzado cuando venga en gana, para realizar exactamente lo que se pretende, en el orden que se pretende. Recuerdo en mis años de juventud (de esto no hará tanto…), cuando el despliegue en producción de un elemento web (WebPart) que debía aparecer en un cierto número de páginas, se volvía la tarea más tediosa del mundo. El día que hice mi primer script, para hacer esa misma tarea en segundos, me di cuenta de cuántas horas de mi vida había perdido. Por ello, considero muy necesario que todo desarrollador SharePoint debe tener al menos nociones básicas sobres el manejo de Windows PowerShell. No se trata de convertirse en maestros del scripting, pero sí contar con unos conocimientos básicos sobre Windows PowerShell para que, llegado el momento, poder desarrollar un script que permita realizar en segundos, tareas que de otro modo podrían llevar horas.

¿Por qué Windows PowerShell?

Si bien el lector de este artículo puede saber de antemano qué es Windows PowerShell y para quién va destinado, considero que es interesante comentar de dónde surge por parte de Microsoft la necesidad de crear otro entorno de línea de comandos (recordemos que CMD.exe existe desde los tiempos de Windows NT), y cuáles son sus principales características.
Así pues, frecuentemente se le ha criticado a Microsoft el hecho de no proporcionar en sus sistemas operativos un intérprete de comandos (shell) con el cual se pudiera gestionar el 100% de las características del entorno. Era evidente, que la comparación del intérprete de comandos entre entornos UNIX y Windows, no dejaba en buen lugar al segundo. Una explicación de por qué en un principio Microsoft no prestó demasiada atención a su intérprete de comandos, es por que históricamente, Microsoft puso todo su esfuerzo en el desarrollo de la interfaz gráfica. Microsoft debió pensar que al usuario medio no le preocupa demasiado el intérprete de comandos. Pero es notorio, que si bien esta estrategia ha resultado muy exitosa comercialmente, ha alejado de los entornos Windows a los profesionales IT y administradores que han exigido siempre una mejora en este ámbito. Por ello, y en la estrategia seguida por Microsoft en los últimos años, de mejorar notablemente aquellos puntos más débiles de sus sistemas, surgió Windows PowerShell.
Es importante aclarar que Windows PowerShell engloba con su nombre tanto un intérprete de comandos (shell), como un lenguaje de scripting propiamente dicho, siendo la principal característica del mismo su orientación a objetos. Esto es: tradicionalmente, los intérpretes de comandos reciben texto como parámetros de entrada, e igualmente devuelven texto como resultado. En Windows PowerShell, los parámetros de entrada y salida, son instancias de objetos .NET, lo que le convierte en una herramienta infinitamente más versátil y capaz. Los encargados de procesar dichos parámetros de entrada y salida son los cmdlets (se pronuncia “command-let”), que se podrían definir como pequeñas clases .NET que el usuario percibe como comandos clásicos. Existen alrededor de unos 1300 cmdlets en una instalación básica de Windows 8.1. Y este número se incrementa si contamos todos los entornos que añaden cmdlets propios (como es el caso de SharePoint). Un ejemplo de cmdlet sería el siguiente:

Get-Process

Con dicho cmdlet se obtienen todos los procesos que se están ejecutando en un momento dado. Una característica importante de los cmdlets, es que semánticamente están compuestos por un verbo (“Get”) y un nombre (“Process”), lo cual permite “adivinar”  cuál es la acción que realiza.

Mientras tanto, en SharePoint 2007…

Mientras tanto en SharePoint 2007 existía (y sigue existiendo) una herramienta de línea de comandos llamada STSADM. Hasta la llegada de SharePoint 2010, era el único medio que tenía el administrador de SharePoint para automatizar tareas frecuentes como copias de seguridad, restauración de las mismas, manejo de las características (features), etc.
Como se ha dicho, SharePoint 2010 vino con la integración a Windows PowerShell bajo el brazo, por lo que la pregunta se hacía evidente: “¿Qué pasa con STSADM?” El mensaje que lanzó Microsoft fue algo tal que así: tienes un coche de toda la vida, con el que has compartido buenos momentos, no te ha fallado demasiado, ha estado en momentos importantes de tu vida (ese primer amor), pero…la familia crece, y necesitas un coche nuevo, más potente y grande. Por lo que ahora tienes uno nuevo que te permite hacer todo lo que hacías con el anterior, y otras muchísimas cosas que no podías hacer. ¿Por qué ibas a seguir usando el viejo? Por lo tanto, como el coche viejo, y a donde quiero llegar, STSADM quedó condenado a quedar en el olvido más pronto que tarde. En resumen, STSADM sigue existiendo incluso en SharePoint 2013, pero únicamente por cuestiones de compatibilidad. Para nuevos desarrollos, Microsoft insta a usar Windows PowerShell. Existe además un documento muy útil, en el que se detallan las equivalencias de comandos entre STSADM y PowerShell .

Y llegó SharePoint 2010

Ya lo hemos comentado en varias ocasiones: desde SharePoint 2010 tenemos integración con Windows PowerShell, ¿pero hasta dónde llega dicha integración? ¿Qué se puede y no se puede hacer? Bien, basta con echar un vistazo a todos los cmdlets que SharePoint trae consigo , cerca de los 800 (frente a los 200 comandos de STSADM), para darse cuenta que con Windows PowerShell es posible prácticamente gestionarlo todo. Más aun teniendo en cuenta que Windows PowerShell es además un lenguaje de scripting, por lo que contamos con las sentencias habituales de bucles, condiciones, variables etc. Combinando todo esto, los cmdlets, más las estructuras típicas de programación, se puede automatizar prácticamente cualquier tarea para SharePoint. Como se suele decir, el límite es la imaginación: Microsoft te ofrece todas las piezas habidas y por haber, de tu habilidad como desarrollador depende lo que construyas con ellas.

¿En qué nivel estamos?

Como dice mi santa madre: “a todo hay quien gane”. Queriendo decir la mujer, que no importa cuán bueno seas en algo, siempre hay alguien mejor (sí, positivismo de andar por casa). A lo cual pienso yo: igual no necesito/quiero ser mejor. Me explico: me gusta jugar al fútbol, lo practico con frecuencia, pero obviamente, hay miles de personas que viven de ello, que son infinitamente mejores que yo, y obviamente, no me planteo competir con ellos. Simplemente, con las habilidades que tengo me es suficiente, para las tareas que tengo que realizar. Igual ocurre en el mundo del scripting. Uno puede tener distintos niveles de habilidad y manejo, según también las necesidades que tenga. Exactamente, para Windows PowerShell, yo distingo los siguientes niveles:

????????????????

 

Este artículo está orientado a alcanzar el segundo nivel. Usar cmdlets para consultar propiedades de elementos SharePoint es lo básico. No se requieren habilidades especiales en programación, tan solo saber qué es lo que se quiere consultar, y qué cmdlet usar. Obviamente no es necesario (ni sano) saber de memoria todos los cmdlets disponibles, ya que existen multitud de recursos disponibles para consultar.

El tercer nivel, es para aquellos desarrolladores o administradores, que trabajan a diario con Windows PowerShell y quieren un paso más en cuanto a personalización y automatización de procesos. Para ello diseñan sus propios cmdlets, para realizar o bien tares muy específicas, o un conjunto de ellas. Existe mucha documentación al respecto.

Las “cuatro” cosas que debes saber

Como decía anteriormente, Windows PowerShell es también un lenguaje de scripting, y por tanto, cualquier desarrollador va a poder hacer uso de sus sentencias de iteración, condicionales, objetos etc., sin mucha dificultad. Como decían algunos profesores de universidad, “si sabes programar en un lenguaje, sabes programar en todos”. No obstante, hay unas cuantas funcionalidades de Windows PowerShell que sí debes conocer, porque a partir de ellas, se puede sacar mucho partido a Windows PowerShell, y construir prácticamente cualquier script.

Definición de variables

Para definir variables en Windows PowerShell lo único que hay que tener en cuenta es que se definen usando el carácter reservado “$”.

$var = Get-Process

Y no olvidar que almacenan objetos y no texto (a diferencia de otros lenguajes de scripting). Es por eso que a una variable se le puede asignar el resultado de la operación de algún cmdlet, para usarlo más tarde.

Pipelines (“tuberías”)

Prácticamente, todo el potencial de Windows PowerShell, viene de la posibilidad de concatenar la salida de un cmdlet a la entrada de otro. Esta explicación tan parca, es en resumen lo que hacen los pipelines. Recordemos que la principal característica de Windows PowerShell es que trabaja con objetos, en vez de con texto planto, y es por ello que los pipelines cobran aquí una vital importancia. Veamos un ejemplo. Supongamos que tenemos un cmdlet, que devuelve figuras geométricas en distintos colores:

Get-Figuras

Y devuelve una colección de figuras tal que así:

FigurasCZaragozaWP

¿Cómo haríamos para obtener solo las figuras de color azul? ¿O cómo haríamos para escribir un informe de todas las figuras en un documento de texto? Para ello tenemos los pipelines o tuberías:

Get-Figuras | Where-Object {$_.Color –eq “Azul”}

Como vemos, lo que define un pipeline o tubería es el carácter vertical (AltGr + 1). En el momento que escribimos ese carácter, lo que estamos diciendo es: “todas las figuras geométricas obtenidas por el comando anterior, las pasamos como parámetro de entrada al comando siguiente”. En este caso el comando siguiente es el cmdlet “Where-Object”. ¿Qué es lo que hace este cmdlet? Vamos al tercer punto 🙂

Where-Object

Si nos fijamos en la sentencia del ejemplo anterior, prácticamente está todo dicho acerca de lo que el comando o cmdlet Where-Object hace. Dada una colección de objetos, permite filtrar entre ellos. Así de simple. Así de potente. Hay que tener en cuenta que la combinación de caracteres “$_” sirve para hacer referencia al objeto actual (algo así como el “this” de toda la vida) y que hay que utilizar los operadores lógicos y de comparación propios de Windows PowerShell.
???????????????????????????????????
Supongamos ahora que, siguiendo con el ejemplo anterior de las figuras, queremos hace lo siguiente: obtener primer todas las figuras, a continuación, filtrar entre ellas para obtener las que son de color naranja, y finalmente, modificar el color de estas por el color verde. Es decir, necesitamos iterar el resultado obtenido tras el filtrado ¿Cómo hacemos esto? Vamos al siguiente punto.

ForEach-Object

La situación que comentaba en el punto anterior se resolvería de la siguiente manera:
Get-Figuras | Where-Object {$_.Color –eq “Naranja”} | Foreach-Object {$_.SetColor –color “verde”}

Volvemos a usar un pipeline para pasar los resultados del cmdlet Where-Object al cmdlet ForEach-Object, y es éste el que internamente se encarga de iterar por todas las figuras, y llamar a su método correspondiente para cambiar el color.

ForEach-Object vs Foreach

Hay un asunto que crea confusión en los desarrolladores que se inician en Windows PowerShell, y es que existen dos formas de realizar iteraciones o bucles dentro de una colección de objetos. Podemos usar la sentencia ForEach-Object que comentábamos anteriormente, o bien podemos usar la sentencia Foreach. Parecen iguales, pero no lo son. ¿Cuál es la diferencia entonces? ¿Cuál debemos usar? Veamos ejemplos de uso de cada uno. Para un vector de números como el que sigue:
$nums = 1,2,3,4,5,6,7,8,9,10,12,14,15,56,35,88

Podemos iterar a través de ellos con Foreach-Object tal que así:

$nums | ForEach-Object { Write-Host “Num: “ $_}

Y de la siguiente forma con ForEach:

Foreach ($num in $nums) { Write-Host “Num: “ $_}
La principal diferencia es que mientras el cmdlet ForEach-Object puede recibir la colección de objetos mediante un pipeline, la sentencia Foreach necesita que dicha colección de objetos esté almacenada en memoria.  ForEach-Object no necesita que los objetos de la colección estén en memoria para poder procesarlos, si no que va iterando secuencialmente por ellos conforme van llegado desde el pipeline. Es decir, volviendo al ejemplo anterior de las figuras:
Get-Figuras | Where-Object {$_.Color –eq “Rojo”} | Foreach-Object {$_.SetColor –color “verde”}
ForEach-Object no necesita que el cmdlet Where-Object haya terminado de filtrar todas las figuras, y enviar el resultado a continuación, si no que uno a uno, se envían los objetos a ForEach-Object. En contrapuesta, la sentencia Foreach itera más rápido entre una colección de objetos. ¿Conclusión? Si la colección de sitios a iterar está almacenada en memoria, usar Foreach; si por el contrario la colección de objetos es el resultado de un procesamiento previo, como un filtrado, etc., usar ForEach-Object.

6. Dónde empiezo a escribir?

Ya hemos hecho un breve repaso sobre las características de Windows PowerShell, ya sabemos algo más de sus inicios, y de su alianza con SharePoint desde la versión 2010. El siguiente paso es empezar a hacer uso de él, y esto nos plantea la siguiente pregunta: ¿Dónde y cómo empiezo a escribir y ejecutar mis scripts para SharePoint? Tenemos varias opciones:

SharePoint 2013 Management Shell

 SharePoint-2013-Management-Shell
Este sería nuestra primera toma de contacto con los cmdlets de SharePoint. Se trata de una línea de comandos de Windows PowerShell, donde podemos ejecutar directamente cmdlets. La particularidad de esta línea de comandos es que carga inicialmente, de manera automática, todos los cmdlets propios de SharePoint. ¿Cómo lo hace? Para responder a esta pregunta, primero tendríamos que aclarar un concepto previo: los snapins.
Windows PowerShell funciona con el uso de los snapins. Básicamente un snapin es una DLL instalada en la GAC que implementa una interfaz. Lo cual significa que es posible desarrollar snapins propios para realizar cualquier tarea que se desee. Así pues, todos los cmdlets de SharePoint se encuentran en la DLL Microsoft.SharePoint.PowerShell.dll
Por lo que, para explicar cómo funciona internamente Microsoft SharePoint 2013 Management Shell (lo mismo aplica para la versión 2010, SharePoint 2010 Management Shell), debemos ver a éste como un “mero” acceso directo a Windows PowerShell, que cuando es lanzado, carga un script que se encuentra en la siguiente ruta* :
C:Program FilesCommon Filesmicrosoft sharedWeb Server Extensions15CONFIGPOWERSHELLRegistrationsharepoint.ps1
*Nota: En SharePoint 2010, dicho script se encuentra en la misma ruta, solo que bajo la carpeta “14”.
En dicho script, podemos encontrar entre otras, la siguiente instrucción:
Add-PSSnapin Microsoft.SharePoint.PowerShell
Y como podrás suponer, es mediante el cmdlet Add-PSSnapin como se pueden cargar nuevos snapins al intérprete de comandos, en este caso, la DLL Microsoft.SharePoint.PowerShell necesaria.
Para empezar a escribir un script, podemos usar el editor con el que más cómodo nos sentamos (desde el Blog de Notas de toda la vida, hasta Visual Studio), y una vez terminado guardar el mismo en un archivo con extensión PS1. Después accedemos a la localización de este archivo desde el intérprete, y ejecutamos el mismo. Hay otra opción, que veremos más adelante, que integra en un mismo entorno, un editor de scripts y el intérprete de comandos de Windows PowerShell.

Windows  PowerShell

Windows-PowerShellCzaragoza

 

Otra opción, es usar la línea de comandos que viene incluido desde Windows 7. Esta línea de comandos es, a mi juicio, más potente, ya que permite acciones como por ejemplo seleccionar texto, pegar texto haciendo clic con el botón derecho, posicionar el cursor con el ratón, etc. Además, el fondo de pantalla por defecto (es configurable) en azul resulta más amigable, aunque aquí también entran en juego los gustos personales de cada uno. Por otro lado, no vienen incluidos los cmdlets de SharePoint, por lo que el primer paso sería escribir el siguiente comando:

Add-PSSnapin Microsoft.SharePoint.PowerShell

Más adelante, veremos cómo es posible crear lo que se conoce como “perfiles”, para que de manera similar a SharePoint 2013 Management Shell, se incluyan los cmdlets de SharePoint en todas las líneas de comandos de Windows PowerShell. Nuevamente, los scripts los escribiríamos en el editor con que nos sentamos más cómodos, y después los ejecutaríamos desde esta línea de comandos.

Windows PowerShell ISE

Windows-PowerShellCzaragoza

ISE son las siglas de Integrated Scripting Environment. La definición más detallada es la que encontramos en la documentación de Microsoft:

“Windows PowerShell ISE es una interfaz gráfica de usuario para Windows PowerShell que permite ejecutar comandos, así como escribir, editar, ejecutar, probar y depurar scripts en la misma ventana. Ofrece hasta ocho entornos de ejecución independientes e incluye un depurador integrado, funciones de edición de varias líneas, ejecución selectiva, sintaxis de colores, numeración de líneas y columnas y ayuda contextual.”

Personalmente, considero que es la mejor opción para escribir scripts de manera profesional. Permite depuración, de manera similar a como se haría desde un entorno de Visual Studio, estableciendo puntos de ruptura, y con ejecuciones paso a paso, lo que lo hace realmente útil.

 

Carga automática de los cmdlets de SharePoint 2010 en Windows PowerShell ISE

Windows PowerShell 3.0 y Windows PowerShell ISE 3.0 vienen instalados por defecto en Windows Server 2012. Por el contrario, en Windows Server 2008/R2 tenemos que instalar el ISE manualmente. Vamos a ver paso a paso cómo sería dicha instalación en un servidor Windows Server 2008 R2, y a continuación veremos el procedimiento para incluir automáticamente, cuando se inicia el entorno, los cmdlets de SharePoint.

– Instalar Windows PowerShell ISE en Windows Server 2008 R2     
  1. Acceder a  Server Manager.
  2. Clic en el nodo de “Características” (“Features”).
  3. Clic en el enlace a “Añadir Característica” (“Add Features”).
  4. Marcar la casilla “Windows PowerShell Integrated Scripting Environment”.
  5. Clic en “siguiente” (“Next”), para iniciar la instalación.
  6. Y finalmente, esperar a que el proceso de instalación termine.

Una vez instalada la herramienta, podemos acceder a ella desde el menú Inicio, accediendo a “Todos los programas”, y una vez allí, “Accesorios”, y lo encontramos en la carpeta “PowerShell”.

El siguiente paso es conseguir que cuando se ejecute el ISE, se carguen automáticamente los cmdlets de SharePoint, añadiendo para ello el snapin correspondiente. Para ello, vamos a hacer uso del concepto de los “perfiles” (“profiles”) mencionado anteriormente. Básicamente, un perfil es un script que se ejecuta cuando se inicia Windows PowerShell ISE, con el objeto de crear y tener accesibles variables, alias, funciones, o comandos que el usuario usa con frecuencia. Conviene tener en cuenta el “alcance” de dicho perfil, es decir, para qué usuarios va destinado, incluso para qué máquinas de una red. En la siguiente tabla, se citan todas las posibilidades. La variable $profile, y sus variantes, contiene la dirección física hacia el archivo .PS1 que constituye el perfil.

 – Crear un perfíl para usuario actual, en la máquina actual.
  1. Abrimos un instancia de Windows PowerShell ISE como administrador, y lanzamos lo siguiente:

    if (!(test-path $profile.AllUsersCurrentHost)) {new-item -type file –path $profile.AllUsersCurrentHost -force}
  2. Seguidamente, lanzamos el siguiente comando, para editar el nuevo perfil:

    psEdit $profile.AllUsersCurrentHost
  3. En el documento profile.ps1, añadimos el siguiente fragmento de código, para cargar el snapin Microsoft.Microsoft.SharePoint, en caso de que no esté actualmente incluido:
    If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue) -eq $null ) { Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell }
  4. Guardamos el profile.ps1, y cerramos Windows PowerShell ISE.
  5. Abrimos nuevamente Windows PowerShell ISE, y lanzamos el siguiente cmdlet para verificar que efectivamente, el snapin Microsoft. SharePoint.PowerShell está cargado:
    Get-Command Get-SP*

PowerGUI

 

PowerGUICZaragoza
PowerGUI es una alternativa no oficial, pero libre, para desarrollar scripts en Windows PowerShell. Es una versión vitaminada del entorno Windows PowerShell ISE. Su principal atractivo, es que como su nombre indica (“GUI: graphical user interface”), es una herramienta gráfica, que permite escribir scripts prácticamente a golpe de ratón. Cuenta con una gran comunidad aportando módulos con scripts predefinidos para muchos sistemas (incluido SharePoint), y en general, es una herramienta muy completa como alternativa al Windows PowerShell ISE, siempre y cuando tengamos permitido en nuestro entorno instalar herramientas de terceros, lo cual no siempre es posible, y menos aún, en entornos de producción.

Acceso remoto con Windows PowerShell

Si bien lo frecuente sería lanzar los cmdlets o scripts de Windows PowerShell, desde el propio servidor donde tenemos instalado SharePoint, podría resultar interesante poder ejecutar dichos scripts o comandos remotamente, desde otra máquina. Desde Windows PowerShell 2.0 tenemos acceso remoto, mediante WinRM (Windows Remote Management), un nuevo estándar de Microsoft para la administración remota, que emplea HTTP o HTTPS en vez de RPC.
No pretendo profundizar en los entresijos de dicha tecnología, pero sí ver cuáles son los pasos a seguir, para configurar un acceso remoto mediante Windows PowerShell, y así poder administrar un SharePoint 2013 o 2010, desde la comodidad del hogar (o donde se antoje). Así pues, vamos a ir paso a paso, por la configuración necesaria, primero en el servidor, o máquina objetivo (target que dirían los ingleses), y a continuación la configuración necesaria en la máquina local. Es importante que los comandos y procedimientos que se relatan a continuación, se ejecuten con una cuenta de usuario que tenga permisos de administrador.

Configuración en Servidor Remoto

Habilitamos el acceso remoto en el servidor al que queremos acceder:

Enable-PSRemoting

Con este cmdlet lo que conseguimos es iniciar el servicio WinRM y establecer el modo de inicio a automático. También añade una excepción al firewall para las comunicaciones con el servicio WS-Management. Finalmente, se crea un “listener” para aceptar peticiones desde cualquier dirección IP. El resultado del comando anterior, será similar a lo siguiente:

WinRM Quick Configuration
Running command "Set-WSManQuickConfig" to enable this machine for remote management through WinRM service. This includes:    
1. Starting or restarting (if already started) the WinRM service    
2. Setting the WinRM service type to auto start    
3. Creating a listener to accept requests on any IP address    
4. Enabling firewall exception for WS-Management traffic (for http only). Do you want to continue?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y
WinRM has been updated to receive requests.
WinRM service type changed successfully.
WinRM service started. Configured LocalAccountTokenFilterPolicy to grant administrative rights remotely to local users. WinRM has been updated for remote management. Created a WinRM listener on HTTP://* to accept WS-Man requests to any IP on this machine. WinRM firewall exception enabled.

Para verificar, que el acceso remoto está funcionando en el servidor, pruebe a lanzar el siguiente comando:

Enter-PSSession localhost

Si todo funciona correctamente, debería obtener por línea de comandos algo tal que así:

[localhost]: PS > C:UsersAdministratorDocuments>

A continuación, hacemos saber a la maquina “servidora” o máquina remota, cuál va a ser su rol en la comunicación que pretendemos establecer, entre nuestra máquina local y ésta. Es decir, que va a actuar como servidor. Para ello lanzamos el siguiente cmdlet.

Enable-WsmanCredSSP –Role Server

Finalmente, vamos a configurar la opción de WinrRM, MaxMemoryPerShellMB. Esta opción limita la cantidad de memoria que puede usar un solo proceso remoto. Es conveniente modificar el valor por defecto (150MB), para permitir que los comandos de larga duración se ejecuten sin generar excepciones del tipo OutOfMemory. Para ello lanzamos el siguiente comando:

Set-Item WSMan:localhostShellMaxMemoryPerShellMB 1024

Permisos necesarios para administrar SharePoint con Windows PowerShell

Ahora que ya hemos configurado el servidor al que pretendemos acceder remotamente, el siguiente paso es configurar nuestra máquina local, la que pretende hacer de puente. Pero antes vamos a detenernos a comprobar si cumplimos los requisitos necesarios en cuanto a permisos y seguridad que SharePoint requiere. Es decir, obviamente, cualquier usuario no puede ejecutar comandos de PowerShell contra SharePoint, es necesaria una cuenta de usuario con una serie de permisos y roles muy concretos. Éstos son:

  • Debe ser miembro del grupo de seguridad local WSS_ADM_WGP en el equipo que se ejecuta los comandos.
  • Debe ser miembro del rol SharePoint_Shell_Access SQL Server en la base de datos de configuración (SharePoint_Config).
  • Debe tener acceso a la base de contenidos que desea manipular (WSS_Content_XXX).

Además, si la aplicación web a la que queremos acceder mediante Windows PowerShell, está configurada con autenticación basada en notificaciones (Claims Based Authenticacion), en vez de con autenticación Windows, es necesario que la cuenta de usuario que se use para conectarse remotamente, sea también la cuenta de usuario que se usa para ejecutar el proceso de la application pool del IIS.

En caso de no cumplir alguna de estas restricciones, puede incluir manualmente al usuario en cuestión en los citados grupos de permisos. No obstante, existe un cmdlet cuyo cometido es principalmente ese, otorgar permisos a un usuario para administrar SharePoint con Windows PowerShell, añadiendo al usuario en los grupos necesarios. Se trata del cmdlet Add-SPShellAdmin:

Add-SPShellAdmin –UserName SP2013User1

El cmdlet se encarga de añadir el usuario al rol SharePoint_Shell_Access, teniendo en cuenta lo siguiente:

  • Si sólo se indica el usuario como parámetro de entrada del comando, se agrega al rol únicamente de la base de datos de configuración (SharePoint_Config).
  • Usando el parámetro database se agrega al usuario en el rol SharePoint_Shell_Access, en la base de datos de configuración (SharePoint_Config), en la base de datos de la Administración Central (SharePoint_AdminContent_XXX), y en la base de datos de contenido especificada (WSS_Content_XXX). Es recomendable usar el parámetro database, ya que la gran mayoría de operaciones administrativas requieren acceso a la base de datos de la Administración Central.

Además, de manera automática, el usuario se agrega al grupo WSS_Admin_WPG, en todos los servidores cuando se agrega al rol SharePoint_Shell_Access. Si la base de datos no tuviera dicho rol creado, también se creará automáticamente.

Veamos un ejemplo de uso:

Get-SPDatabase | Where-Object {$_.Name -eq "WSS_Content"} | Add-SPShellAdmin –Username SP2013User1

Este ejemplo es interesante, ya que vemos como mediante el uso de pipelines, accedemos a todas las bases de datos de contenidos, filtramos entre ellas para obtener solo aquella cuyo nombre sea “WSS_Content”, y finalmente, le damos en esta base de datos permisos al usuario “SP2013User1”, mediante Add-SPShellAdmin. Finalmente, si queremos comprobar qué usuarios tienen permisos para lanzar comandos de Windows PowerShell contra SharePoint, podemos hacer uso del cmdlet Get-SPShellAdmin:

Get-SPShellAdmin 

El cual devuelve un listado con todos aquellos usuarios que tienen el rol SharePoint_Shell_Access. Se debe especificar una base de datos en cuestión como parámetro de entrada mediante –database, para consultar sobre una única base de datos. En caso de no especificar ningún valor, se consulta sobre la base de datos de configuración.

Configuración en Cliente

Quedan pocos pasos para terminar de configurar acceso remoto mediante Windows PowerShell, pero son tal vez los pasos más complicados. Pero como dicen en una de mis películas favoritas, “la noche es más oscura, justo antes del amanecer” .

En primer lugar, vamos a introducir el concepto de CredSSP (Credential Security Service Provider). Este es un concepto con el que ya hemos “coqueteado” anteriormente (sin saberlo), en la configuración para el servidor. Resumidamente, CredSSP permite a las aplicaciones delegar las credenciales de un usuario desde una máquina cliente, a una máquina “objetivo”, proceso que también se conoce como doble salto (double-hop). Esto permite presentar las credenciales a los cmdlets de SharePoint que se comunican con la máquina que tiene la instancia de Microsoft SQL Server. Así pues, se podría comparar a CredSSP con Kerberos, solo que el mecanismo de autenticación de CredSSP es notoriamente distinto. En CredSSP, las directivas de grupo (Group Policy), establecen qué credenciales deben ser delegadas, y a continuación se le pide al usuario que introduzca dichas credenciales mediante nombre de usuario y contraseña. Esto significa que el usuario tiene cierto control sobre si la delegación debe ocurrir o no, y en caso de que sea así, qué credenciales deben usarse. En Kerberos, únicamente pueden delegarse las credenciales del usuario que proceden del Active Directory®. Una vez autenticado el usuario, las credenciales no son delegadas hasta que el servidor objetivo es autenticado también mediante las directivas de grupo (Group Policy) de la máquina local.

Y eso es precisamente lo que vamos a hacer a continuación, editar las directivas de grupo usando gpedit.msc.

 local-group-policy-editorCZaragoza

 

Una vez estemos en la sección de la imagen anterior, habilitamos los siguientes:
• Allow Delegating Fresh Credentials.
• Allow Delegating Fresh Credentials with NTLM-only Server Authentication.
En ambos, debemos hacer clic en el botón “Show” para añadir servidores a la lista.

Show-contents-SharePointCZaragoza

 

Como vemos se puede usar el carácter *, para hacer referencia a todas las máquinas bajo un determinado dominio. En el ejemplo de la imagen, estaríamos otorgando permisos a todas los servidores que se encuentran en el dominio SP2013.local. Es importante, además, que si la máquina “local” se encuentra fuera de dominio, ésta conozca la ubicación de la máquina destino (dirección IP), bien mediante DNS, o bien, mediante una entrada en el fichero host.
Finalmente, para asegurarnos de que se apliquen los cambios, podemos actualizar las directivas de grupo lanzando el siguiente comando:

GPUpdate.exe

Volvemos a la línea de comandos de Windows PowerShell, y lanzamos el siguiente comando para habilitar el acceso remoto desde cliente:

Enable-PSRemoting
Y por último, lanzamos el siguiente comando, donde especificamos que nuestra máquina local va a tener el rol de cliente en la comunicación con el servidor, y además, a qué máquina queremos conectarnos.
Enable-WSManCredSSP –Role Client –DelegateComputer computerName.SP2013.local

Bueno, ha sido largo el camino, pero finalmente ya estaría configurado el acceso remoto. El último paso, obviamente, es comprobar que  todo funciona como se espera. Lanzamos el siguiente comando, que inicia una conexión remota:

Enter-PSSesion –ComputerName computerName.SP2013.local –Authenticaton CredSSP –Credential (Get-Credentials)

Se nos pedirá que introduzcamos los credenciales del usuario con el que iniciar la sesión remotamente. Y si obtenemos como resultado en línea de comandos, algo similar a esto:

[computerName.SP2013.local]: PS CUsersUserNameDocuments>
Quiere decir que ya estamos accediendo remotamente al servidor mediante PowerShell. Una prueba de ello sería en primera lugar, cargar los snapins de SharePoint, y a continuación lanzar un cmdlet como por ejemplo, Get-SPSite, que muestra en un listado todas las colecciones de sitios que tenemos creadas en el servidor. Finalmente, para cerrar la sesión, tecleamos “exit”.

Tu turno

Llegado a este punto, en el que ya hemos hablado largo y tendido de Windows PowerShell, es el momento en el que el lector debe sentarse delante de su PC y poner en práctica todo lo aprendido. Hemos visto qué es Windows PowerShell, cómo podemos sacarle el mejor partido, e incluso cómo podemos hacer uso de él remotamente. Sólo queda que el lector, presumiblemente un desarrollador SharePoint, le dé forma de script a esas tareas repetitivas que realiza frecuentemente.

Ejemplo práctico.

Una de esas tareas, por la cual se hace notorio la necesidad de realizar un script que permita automatizarla, es aquella que requiere de realizar cierta acción en todos los sub-sitios de una colección de sitios, o bien, en un gran número de ellos. Esto podría ser crear una lista en todos los sub-sitios, agregar un determinado elemento web en las páginas de bienvenida, activar alguna característica de SharePoint, etc. Este tipo de scripts tienen en común un esquema o patrón, y es que se ha dicho, se necesita recorrer todos los sitios y sub-sitios de una colección de sitios. Por lo que este script es fácilmente reutilizable, adaptando únicamente la acción o proceso a realizar.
A continuación, y a modo de ejemplo de lo visto en este artículo, y que a su vez, sirva como referencia para el modelo de script descrito, vamos a mostrar cómo sería el cuerpo de dicho script que recorre todos los sitios y sub-sitios de una colección de sitios. La forma de hacerlo será por medio de recursividad, de manera que en pocas líneas de código, se puede iterar por toda la estructura de sitios de SharePoint.
Vamos a ver el script.
param
(
#Parámetro de entrada (con valor por defecto) con la URL de la colección de sitios.
#Introduzca aquí otros parámetros de entrada, separados por coma. [string]$siteCollection = http://solidq.local/ );
#Contador para identar la salida por texto los sitios.
$count = 0;
function AccionRecursiva([Microsoft.SharePoint.SPWeb]$oWeb)
{
 #Información del sitio actual.
 for ($i = 0; $i -lt $count; $i++) {Write-Host "---" -Nonewline;}
 Write-Host "(*)" $oWeb.Title -Nonewline;
 if ($oWeb.Webs.Count -gt 0) {$count++;}
 
 <#
Escriba aquí, la acción que desea realizar en todos los sub-sitios.
Puede también discriminar entre sub-sitios, comparando por URL, título de sitio, si el sitio contiene cierta lista, etc. 
 #> 
 
 #Información visual de que la acción ha sido realizada correctamente. 
 Write-Host "...OK!" -ForeGroundColor green; 
 
 #Aplicamos la recursividad, iterando por los sitios hijo.
 $oWeb.Webs | ForEach-Object{AccionRecursiva($_)};
 
 $count--; 
}
#Se comprueba los parámetros de entrada.
if ($siteCollection -ne $null)
{
 #Obtenemos la colección de sitios
 $coleccionDeSitios = Get-SPSite $siteCollection;
 
 if ($coleccionDeSitios -ne $null)
 {
  try
  {
   #Accedemos recursivamente a todos los sub-sitios.
   $coleccionDeSitios.RootWeb | ForEach-Object{AccionRecursiva($_)}   
  }
  catch [System.Management.Automation.ExtendedTypeSystemException]
  {
   Write-Host $_.Exception.ToString();
  }
 }
}
else{Write-Host "Error: Faltan parámetros.";}

El resultado de ejecutar dicho script, dentro de la web de SolidQ, sería el siguiente.

Ejecutando-un-script-SharePoint-Cristian-Zaragoza-SolidQ

 

Se muestra por pantalla, cada uno de los sitios que componen la colección de sitios. Partiendo de dicho “esquema”, sería fácil realizar un script funcional, tan sólo adaptándolo a según qué necesidades. Obviamente, la mostrada sería la parte “fácil”. Quedaría por parte del lector o usuario de SharePoint la tarea de averiguar cómo traducir a lenguaje de Windows PowerShell, aquellas tareas que sabe que pueden hacerse, pero todavía no sabe cómo. Esa es sin duda la parte más bonita del camino: encontrarle la solución al problema. Y espero que este artículo, sea una pieza de esa solución.

9. Referencias.

 

 

Cristian Zaragoza

Cristian has more than three years of experience as SharePoint Developer. Cristian is a former SolidQ team member.