martes, 31 de diciembre de 2013

Caso Práctico:Depurando las dependencias no migradas en SharePoint 2010

Una de las plantillas encontradas en SharePoint 2007 que no todas pueden ser migradas a 2010 y mucho menos a 2013 son las plantillas de los 40 fantásticos, sino sabe de lo que hablo posiblemente no tiene de que preocuparse.

Las plantillas de los 40 fantásticos es una historia triste, ya que Microsoft no las adopto para las versiones posteriores de SharePoint y aunque algunas se adaptaron para 2010 estas no están disponibles para 2013.  Estas plantillas en el proceso generan muchos errores.   Si desea saber mas de las plantillas puede consultar los siguientes enlaces:

http://technet.microsoft.com/en-us/sharepoint/bb407286.aspx

http://blogs.technet.com/b/tothesharepoint/archive/2010/08/18/sharepoint-2010-products-upgrade-and-the-fabulous-40-application-templates.aspx

Para este caso vamos asumir que ya sea que sean plantillas de los 40 fantásticos o bien otras dependencias que no se lograron migrar de 2007 a 2010.  Si la migración reporto errores pero terminó y deseamos depurar las dependencias faltantes. Entonces ya hemos migrado de 2007 a 2010 una base de datos de contenido con varios errores de dependencias que no tenemos instaladas en la granja 2010 pero deseamos depurar los errores. Dependiendo de cada error se toman diferentes caminos (para más información puede ver el siguiente enlace:http://kancharla-sharepoint.blogspot.com/2013/08/resolving-missing-references-when.html) pero para este caso vamos a sumir que los sub-sitios que dieron error porque no están las plantillas instaladas eliminaremos dichos sub-sitios, para luego crear una nueva base de datos y allí migrar el contenido sin errores.  El procedimiento es el siguiente:

1. Crear una nueva aplicación Web (para operar cómodamente el contenido depurado)

New-SPWebApplication -ApplicationPool <String> -Name <String> [-DatabaseName <String>] [-DatabaseServer <String>] [-HostHeader <String>] [-Path <String>] [-Port <UInt32>] [-ServiceApplicationProxyGroup <SPServiceApplicationProxyGroupPipeBind>]

http://technet.microsoft.com/en-us/library/ff607931.aspx

Ejemplo: New-SPWebApplication –ApplicationPool “Nueva App Pool” –Name “SharePonit Web App temporal” –DatabaseName “wss_content_NuevoContenido” –HostHeader “” –Path “c:\temporal\Web4444” -Port 4444

2. Exportar el contenido al sistema de archivos

Export-SPWeb [-Identity] <SPWebPipeBind> -Path <String> [-IncludeUserSecurity <SwitchParameter>] [-IncludeVersions <LastMajor | CurrentVersion | LastMajorAndMinor | All>] [-NoFileCompression <SwitchParameter>]

http://technet.microsoft.com/en-us/library/ff607895.aspx

Ejemplo: Export-SPWeb –Idendity http://miwebmigrada –path “c:\temp\contenidodepurado” –IncludeUserSecurity – IncludeVerions All – NoFileCompression

3. Importar el contenido en la nueva aplicación Web

Import-SPWeb [-Identity] <SPWebPipeBind> -Path <String> [-IncludeUserSecurity <SwitchParameter>] [-NoFileCompression <SwitchParameter>] [-UpdateVersions <Append | Overwrite | Ignore>]

http://technet.microsoft.com/es-es/library/ff607613.aspx

Ejemplo: Import-SPweb –Identity “http://hostname:4444” –Path “c:\temp\contenidodepurado” –NoFileCompression –UpdateVerions Overwrite

4. Desmontar la base de datos de contenido de la aplicación Web nueva creada y de la migrada

Dismount-SPContentDatabase [-Identity] <SPContentDatabasePipeBind>

http://technet.microsoft.com/en-us/library/ff607764.aspx

Ejemplo: Dismount-SPContentDatabase –Identity “wss_content_NuevoContenido”

5. Montar la base de datos depurada en la aplicación web deseada

Mount-SPContentDatabase [-Name] <String> [-WebApplication] <SPWebApplicationPipeBind>

http://technet.microsoft.com/en-us/library/ff607581.aspx

Ejemplo: Mount-SPContentDatabase –Name wss_content_NuevoContenido –WebApplication “http://miwebmigrada

SharePoint4Fun!,

Juan Manuel Herrera Ocheita

sábado, 28 de diciembre de 2013

Tips para el proceso de migración de SharePoint 2007 a 2013

Primero lo primero no se puede pasar de SharePoint 2007 a 2013 de un solo con el procedimiento de base de datos acoplada o Attach data base, con herramientas de terceros es posible pero es un proceso lento y no esta libre de errores.  En 2007 hay dos procesos soportados In Place y Attached data base.  Pero el último es el adoptado y único para versiones posteriores, por lo que mantendremos esta tendencia desde 2007.

Para realizar la migración debemos de contar por lo menos con dos granjas una de SharePoint 2010 y otra de SharePoint 2013.

No es recomendado realizar un downgrade es decir una reducción de versión en el proceso de migración.  por ejemplo:  Tenemos una granja SharePoint 2007 Edición Enterprise y deseamos convertirla a SharePoint 2013 Edición Standard o a SharePoint Foundation. 

Lo contrario si es válido y posible, es decir hacer un upgrade o mejora de versión.  Por ejemplo de WSS 3.0 a SharePoint 2013 Enterprise o Standard.

A continuación una tabla de la ruta de migración posible del 2007 al 2013 en sus diferentes ediciones:

image

A continuación una tabla de la ruta de migración recomendada (en color amarillo):

image 

La recomendación se basa en que se utilice la misma edición de 2007 y hasta el final se utilice la edición deseada.  Abajo una tabla de las rutas no soportadas en las cuales se suponen escenarios de color rojo donde erróneamente se escoge una ruta de upgrade en el intermedio (en la versión 2010) y luego se decide equivocadamente hacer un downgrade, esto acarreará muchos errores en la etapa de migración de 2010 a 2013 que puede incluso impedir la migración.

image

Debemos de recordar el idioma en que esta instalado el SharePoint debe de ser el mismo a migrar o bien contar con el paquete de idioma instalado en las granjas de SharePoint a migrar que en este artículo hablamos de 2010 y 2013.

La configuración de las granjas es algo que no debe de tomarse a la ligera ya que esto puede desembocar en un proceso rápido y efectivo o lento y frustrante.

La configuración de Hardware debe de analizarse desde el misma granja de SharePoint 2007, ya que podemos contar con imprevistos como el que no se haya instalado 2007 en una base de datos de SQL Server sino a través de la versión incrustada o embedded y esto hará el proceso de extracción de la base de datos más doloroso y complicado.  Esto sucede cuando instalamos el SharePoint de forma solitaria o Stand Alone, instalación solamente diseñada para demostración y nunca recomendada para un ambiente de producción.  La sorprendente es encontrar empresas que tienen así instalado su SharePoint en modo stand-alone.

La otra configuración importante es la de SharePoint 2010 que a pesar que sea una granja “puente” ya que solo se instalará para migrar el contenido de 2007 a 2010 y de 2010 a 2013.  Debemos de asignar recursos adecuados para que el proceso de migración para que sea exitoso y eficiente.  Esta granja posiblemente no cuente con muchos recursos pero debemos prestar atención a la RAM y espacio en disco y en los servicios y contenido que estamos migrando.

A continuación la configuración mínima y recomendada por Microsoft para SharePoint 2007 Front End en sus diferentes ediciones

image

image

A continuación mi recomendación práctica para una migración para la versión SharePoint 2007

image

image

Para el servidor Puente o sea el servidor SharePoint 2010 las recomendaciones son las siguientes:

image

En la medida de disponer de mayor cantidad de RAM se garantiza un proceso más rápido de migración.  Y el espacio en disco se basa en el requerimiento de SharePoint de 5 veces el tamaño de la memoria RAM partiendo del mínimo recomendado de 80 GB + 5 Veces la RAM.  Se asume por ser un servidor puente que solo será un servidor, pero esto dependerá de la granja de SharePoint 2007 de origen cuantos servidores tienen ya que no solo se migrará contenido sino servicios también.

A continuación la recomendación mínima de una granja de SharePoint 2013 y un servidor de SQL Server 2012 en sus diferentes ediciones:

image

Comandos útiles para la migración de base de datos de contenido adjunta:

image

image

Bueno eso es todo por este artículo espero lo encuentren útil.

Hasta la próxima, SharePoint4Fun!,

Juan Manuel Herrera Ocheita

domingo, 17 de noviembre de 2013

Cómo resolver el problema de importar un sitio con diferente plantilla utilizando import-spweb

Este caso pueda ser poco usual pero pasa, a continuación explico el caso:

Se ha migrado el contenido de SharePoint 2010 a 2013 y luego se desea migrar un sitio hacia otra colección de sitios, pero el sitio que se desea migrar esta utilizando una plantilla que ya no es soportada en la versión 2013 de SharePoint, entonces cómo resolver este problema?.

Primero debes decir que para migrar un sitio de una colección de sitios a otra utilizamos la línea de comando export-SPWeb.  Para ello ejecutamos image SharePoint Management Shell  y ejecutamos una línea de comando parecida a esta:

PS c:\> export-SPWeb –Identity http://hostname/susitio –path “c:\temp\subsitio.cmp” –IncludeUserSecurity -IncludeVersions All

Luego intentamos crear un sub-sitio donde deseamos importar el contenido exportado, pero como no existe la plantilla podemos intentar crear un sitio con la plantilla de equipo por ejemplo.

Finalmente intentamos importar el contenido con una línea de comando similiar a la siguiente:

PS C:\> import-spweb –identity “http://nuevoservidor/sitios/nuevaCollecion/NuevoSubsitio" -path "c:\temp\subsitio.cmp" -IncludeUserSecurity -ActivateSolutions

Al ejecutar este comando nos muestra el siguiente mensaje de error:

import-spweb : Cannot import site. The exported site is based on the template
STS#2 but the destination site is based on the template STS#0. You can import
sites only into sites that are based on same template as the exported site.

La Solución

Eliminar el sitio creado y ahora vamos a crear un sitio desde línea de comando de la siguiente formar:

PS C:\> new-SPWeb -url http://nuevoservidor/sitios/nuevaCollecion/NuevoSubsitio -name "Nuevo Sitio" -template
STS#02 -UseParentTopNav -UniquePermissions

Al ejecutar la línea de comando nos mostrará el siguiente mensaje:

WARNING: Template is not found and is not applied.

Url
---
http://nuevoservidor/sitios/nuevaCollecion/NuevoSubsitio

No se preocupe este error nos ayudará ya que no aplicará ninguna plantilla y esto permitirá que utilice la plantilla del contenido importado.  O bien no incluir el parámetro –template y esto tendrá el mismo efecto.

Especifica la plantilla web para el nuevo sitio. La plantilla ya debe existir. Si no se especifica ninguna plantilla, no se aplica ninguna plantilla y se puede seleccionar más adelante.

Ahora ejecutamos de nuevo la línea de comando import-SPWeb.

PS C:\> import-spweb –identity “http://nuevoservidor/sitios/nuevaCollecion/NuevoSubsitio" -path r"c:\atemp\subsitio.cmp" -IncludeUserSecurity -ActivateSolutions

Log file generated:
        c:\temp\subsitio.cmp.import.log

Listo ya pudo importar el contenido de una plantilla no soportada en SharePoint 2013.

SharePoint4Fun!,

Juan Manuel Herrera Ocheita

martes, 5 de noviembre de 2013

Error Reporte RDL en SharePoint 2010 no despliega información o Type Sys.UI._Timer has already been registered

Este error no se manifiesta tan evidente ya que el navegador de IE 9, 10 no hará nada y por ende no mostrará la generación del reporte y es más funcionará para algunos usuarios y para otros no.

Si utilizamos las herramientas de desarrollador de IE presionando F12 desde IE en la pestaña de scripts podremos ver el siguiente detalle de error:

SCRIPT5022: Sys.InvalidOperationException: Type Sys.UI._Timer has already been registered. The type may be defined multiple times or the script file that defines it may have already been loaded. A possible cause is a change of settings during a partial update.
ScriptResource.axd?d=kPNVqg5Xk2xEHmG9iUkh6gb4nTjKg44qXODEnWnCK3WXpZEBMHocVoBFio19AkZm6XU5yigeZoGe2mg4Dmaq7JxvAk32sogRfD7ud5cTh5dVgp3pyap8Pqc2L3Eym8bxal5ATKCkLJDjXVUmA4sIWOvkUKp9Hs0UVf8fZ2TfizcKCAGb0&t=33137d1a

Gracias a Natalia Tsymbalenko por su solución con la pudimos resolver el problema:

http://sharing-the-experience.blogspot.com/2012/04/rsviewerpageaspx-type-sysuitimer-has.html

Lo único que quisiera agregar especialmente para usuarios no familiarizados con la estructura de SharePoint es que el web.config a modificar es de la Applicación Web donde esta el reporte instalado.  Una instalación de SharePoint puede contar con varias aplicaciones Web y no solo con una así que debe de validarse cual es la que debemos de modificar. 

Para ello puede ir al Servidor de SharePoint al IIS Manager y podrá ubicar la ruta de la aplicación Web de reportes:

image

Por ejemplo de forma predeterminada cuando creamos una aplicación web desde SharePoint esta la crea en la ubicación predeterminada del IIS que normalmente es c:\inetpub\wwwrooot\wss\VirtualDirectories y dentro de este directorio un directorio por cada aplicación Web por lo menos encontrará dos una del Central Administration y otra de la aplicación Web del portal. 

Y finalmente dentro de ese directorio encontrará el archivo de configuración web.config.  En la sección compilation batch verificar que el debug=”false” si esta activado debug=”true” cambielo a false y listo el así como vino desaparece.

<globalization fileEncoding="utf-8" />
<compilation batch="false" debug="false">
     <assemblies>
       <add assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
       <add assembly="Microsoft.Web.CommandUI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="Microsoft.SharePoint.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="Microsoft.Office.Access.Server.UI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="Microsoft.Office.Access.Services.UI, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="Microsoft.SharePoint.Publishing, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
       <add assembly="Microsoft.Office.Server.Search, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
     </assemblies>
  …

</compilation>
 
Y ahora puede ejecutar los reportes desde IE 9 o 10 si este problema.

SharePoint4Fun,

Juan Manuel Herrera Ocheita

sábado, 2 de noviembre de 2013

Error al intentar consultar historial de versiones en SharePoint 2010

Este es uno de los errores que ha acompañado a SharePoint desde 2007 y en 2010 no ha sido la excepción.   Si el problema es general en las bibliotecas puede intentar instalar la actualización de Abril del 2013 que registra el problema y su corrección.

Pero si no le funciona puede validar si esta solución que abajo describo puede resolver su problema.

Primero el error que muestra es el siguiente:

image

Si verificamos el error en los logs de SharePoint encontraremos el siguiente detalle:

Unexpected      System.NullReferenceException: Object reference not set to an instance of an object.    at ASP._layouts_versions_aspx.__Render__control14(HtmlTextWriter __w, Control parameterContainer)     at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)     at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)     at System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer)     at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children)     at System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer)     at System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output)     at System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer)     ...  1ee23f45-af8f-4521-a190-3b795d3fdda4

El error en detalle describe que el error se debe a que esta esperando un objeto en memoria al cual no esta instanciado.  Es decir hace referencia de un objeto que esta ausente en ese momento.

Para esta solución utilizaremos SharePoint Designer 2010 para resolverlo.  Abrimos el sitio donde están las bibliotecas con el error y luego en la pestaña de navegación seleccionamos la opción “Todos los archivos”

image

Luego seleccionamos en la biblioteca con el error

image

Luego seleccionamos la carpeta Forms

image

Luego seleccionamos la página DispForm.aspx, presionamos el botón derecho para que levante el menú contextual y seleccione la opción Eliminar (para que luego podamos crearla de nuevo)

image

Ahora seleccionamos la opción Listas y bibliotecas de la sección Navegación.   

image

Luego seleccionamos nuevamente la biblioteca con error

image

Luego en la sección formularios presionamos el botón Nuevo

image

En el nombre del archivo escriba DispForm y luego presiona el botón Aceptar

image

Como resultado deberíamos observar que ya esta la página dentro de la sección Formularios.

image

Ahora si consultamos el historial de versiones nos debería mostrar una ventana similar a esta.

image

Eso es todo amigos nos vemos hasta la próxima.

SharePoint4Fun!,

Juan Manuel Herrera Ocheita

domingo, 27 de octubre de 2013

Es fundamental para la planificación de la instalación de la granja de SharePoint para la búsqueda del contenido del portal antes de instalar SharePoint (2007,2010,2031)

Esto es difícil de encontrar dentro de la documentación debido al volumen del contenido y aspectos a tomar en cuenta pero es fundamental para un exitosa configuración del servicio de búsqueda.

Supongamos el siguiente escenario:

Instalamos SharePoint, creamos la granja y luego creamos la primera o principal aplicación Web normalmente con el nombre del servidor y no con el espacio de nombre definitivo. Eso será un problema más adelante, y le cuento porqué.  Cuando definimos las fuentes de contenido o content sources de SharePoint, lo debemos de hacer con el nombre de la aplicación Web predeterminado o default, es decir no el nombre del servidor, pero luego si agregamos un nuevo espacio de nombre que lo debemos de hacer extendiendo la aplicación Web. Cuando realizamos una consulta en una lista, o sitio no funcionará, sino solamente a nivel de todos los sitios.  Aunque asignemos un dirección URL en la opción Assign server results, no funcionará.  Si ya tenemos este escenario no todo esta perdido, podemos corregirlo de la siguiente forma:

1) Haga clic sobre Configuración

2) Luego sobre Configuración del Sitio

3) Configuración de la búsqueda

4) Reemplace el valor de /_layouts/OSSSearchResults.aspx. por SearchCenter/Pages/results.aspx

5) Reinicie el indice y vuelva a realizar la indagación o crawling y listo.

 

Ahora como debimos planearlo desde el principio.

Primordialmente debemos de planear que tipo de contenido vamos utilizar en el portal y organizarlo de tal forma que nos permita definir reglas que eviten el crecimiento desmedido de la indagación el espacio de nombre que utilizaremos para acceder el portal y que esta sea configurado como host header y como la zona predeterminada de la aplicación Web el cual será el mismo nombre para la indagación para evitar el problema mencionado arriba.

Las reglas de indagación son necesarias para incluir o excluir el contenido de las fuentes de contenido, pero estas reglas pueden afectar el tamaño de la base de datos.  (También el detener y reiniciar la indagación incrementa el volumen de las bases de datos, lo mejor siempre es reiniciar el índice, y realizar una indagación desde cero).

La siguiente regla es importante a considerar:

  • Crawl complex URLs (URLs that contain a question mark (?)).

Ya que si tenemos un url de un sitio público, esta intentará indagar todos las posibles opciones que tenga el sitio web.  Además también puede ser que estemos indagando un contenido de reportes que maneja por cada reporte una cantidad de posibles parámetros con lo que incrementaría el contenido de la base de datos.  Por ello es importante tomar en cuenta el contenido que estamos indagando y las reglas que especifiquemos.

Entonces el procedimiento para crear la aplicación Web de nuestro portal que evite el problema de arriba mencionado es como sigue:

1) Registrar en el servicio de DNS el espacio de nombre para el portal, por ejemplo portal.contoso.com

2) Probar en el servidor de SharePoint que este nombre se resuelva haciendo un ping a portal.contoso.com

3) Crear la aplicación Web sobre el puerto 80 y colocar como host header el nombre portal.contoso.com

4) Ir al Servicio de aplicaciones y seleccionar el servicio de búsqueda y configurar una regla de indagación o Crawl Rules, que incluya el nombre registrado en el host header.  http://portal.contoso.com/* y con la opción incluir con la única opción Crawl SharePoint content as HTTP pages habilitada, con ello será suficiente para incluir el contenido de las páginas y los documentos. 

5) Ejecutar la indagación del contenido y realizar las pruebas necesarias para validar que esta incluido.  En el caso de las listas hay que indicarle que debe de incluirse en la indagación para que lo haga, así que deberá tomar en cuenta eso.

Bueno eso es todo por ahora.  Espero que tenga éxito en la indagación del contenido de los sitios de SharePoint.

Search4Fun!,

Juan Manuel Herrera

 

Otras referencias útiles para este problema pueden consultarse en:

http://olenicksharepoint.wordpress.com/2012/03/01/the-problem-with-contextual-search-scopes/

http://sharepoint.stackexchange.com/questions/53288/how-to-remove-contextual-search-this-site-from-dropdown-box-of-target-result

http://support.microsoft.com/kb/2000365

Estrategia de migración de SharePoint 2010 a 2013 “On Prem” o local

La primera gran noticia sobre la migración de SharePoint 2010 a 2013 es que no hay otro método de migración “nativo” que el de adjuntar las bases de datos o “attach content database” así que no hay como confundirse ya que hay una sola opción para realizarlo.  También es importante mencionar que la migración nativa de Microsoft es la más veloz especialmente cuando hablamos de grandes volúmenes de contenido.  Ya que se migra las bases de datos contenido completas y no objeto por objeto como lo hace los productos de terceros.   Por ejemplo una base de datos de contenido de 1.3 GB que pequeña en realidad con el proceso nativo demora máximo una hora entre cada paso del proceso y la escritura manual de los comandos de PowerShell y unas dos horas más entre copia y respaldo de bases de datos.  Pero con una herramienta de terceros esto demora alrededor de 36 horas, podrá imaginarse una base de datos de 200 GB o 400 o de un 1tb cuanto demoraría este proceso con herramientas de terceros.

No estoy desaprobando estas herramientas yo mismo he adquirido una para otros procesos como migrar de una instalación local a la nube o migrar de 2007 a 2013 poco contenido esto es eficiente, pero para grandes volúmenes de contenido es impráctico. 

La segunda noticia sobre la migración es la conversión del método de autenticación de SharePoint obligatoria, ya que en SharePoint 2010 Claims Authentication era e opcional y en 2013 es obligatoria.  Pero ejecutar este proceso en la granja de producción puede ser algo arriesgado y no deseado.  Por lo que por ello debemos de plantear una estrategia.

La estrategia para el escenario en que ya esta funcionando el portal en SharePoint 2013 y todavía utilizan o consultan la versión 2010 es contar con un servidor de pruebas para realizar los cambios de método de autenticación es decir en SharePoint 2010 y luego migrar el contenido al servidor en Producción SharePoint 2013 a una aplicación Web creada solo para validar el éxito o fracaso de la migración para luego incorporar el contenido migrado a su ubicación definitiva dentro de la aplicación Web desea.

En este servidor de Pruebas tendremos que crear una aplicación Web para adjuntar la base de datos a migrar, hacerle el cambio del modo de autenticación y luego mover la base de datos al servidor de base de datos donde están depositadas las bases de datos de SharePoint 2013.  El procedimiento es el siguiente:

1) Realice una copia de respaldo de la base de datos de contenido a migrar.  (Ojo debe de ser la base de datos de contenido primaria, sino es así primero debe migrarse esta ya que no puede ser restaurada una base de datos de migración secundaria si no esta migrada la primaria).

1.1.) Cómo realizar una copia de respaldo en SQL Server. http://technet.microsoft.com/es-es/library/ms187510.aspx

2) Restaurar la base de datos de contenido primaria en el servidor de Pruebas. 

2.1) Cómo realizar una restauración de una copia de respaldo en SQL Server. http://technet.microsoft.com/es-es/library/ms177429(v=sql.105).aspx

3) Crear una aplicación Web en el servidor de SharePoint 2010.

3.1.) Cómo crear una aplicación Web en SharePoint 2010 de autenticación clásica. http://technet.microsoft.com/es-es/library/gg276321(v=office.14).aspx

4) Montar la base de datos de contenido en la aplicación Web del servidor de Pruebas.

4.1.) Ejecute la siguiente línea de comando en PowerShell para SharePoint.  mount-SPContentDatabase –Name WSS_Content_[el nombre de su base de datos] –WebApplication http://[nombre del servidor]:[Puerto]. Para más información:http://technet.microsoft.com/en-us/library/ff607581.aspx

5) Ejecutar el procedimiento para cambiar el modo de autenticación para la base de datos de contenido.

5.1.) Ver procedimiento completo en http://technet.microsoft.com/en-us/library/gg251985.aspx

6) Realizar la copia de respaldo de la base de datos con el nuevo modo de autenticación.

7) Restaurar la copia de respaldo en el servidor de SQL Server de la granja de SharePoint 2013.

8) Crear una aplicación Web en la granja de SharePoint 2013.

9) Desmontar la base de datos creada http://technet.microsoft.com/es-es/library/ff628582.aspx

10) Realizar la prueba de montaje de base de datos y migración antes de realizarla ejecutando la línea de comando: test-SPContentDatabase –Name WSS_content[nombre de la base de datos de contenido] –WebApplication http://[nombre del servidor]:[Puerto] .   Validar las dependencias e instalar las disponibles.

11) Realizar el montaje de la base de datos con la línea de comando: mount-SPContentDatabase –Name WSS_Content[Nombre de la base de datos de contenido] –WebApplication http://[nombre del servidor]:[puerto]

Nota: aunque le de el mensaje del modo de autenticación clásico la migración pasará por el procedimiento que se realizó con anterioridad.

12) Como paso final deberá realizar la migración de la interfaz gráfica a 2013 o conocida como la actualización de colección de sitios. http://technet.microsoft.com/en-us/library/jj219650

Listo con ello habrá realizado la migración del contenido de SharePoint 2010 a 2013.  Pero esto no es la migración completa, de hecho el proceso prevee la migración de los servicios primero y por ultimo la migración del contenido.  vea la siguiente imagen.

image

Bueno para el alcance de este artículo hemos visto suficiente.  Si quiere saber más sobre ello puede consultar:  http://technet.microsoft.com/en-us/sharepoint/fp142375.aspx

SharePoint4Fun!,

Juan Manuel Herrera Ocheita

jueves, 26 de septiembre de 2013

Comportamiento aparentemente errático de las Apps que muestran el contenido para algunos usuarios y a otros no en SharePoint 2013 On Premises o local con los mismos niveles de permisos

Este fue un error que me costo encontrar donde estaba el problema por lo que creo que es de utilidad compartir con ustedes la solución del problema.

Escenario:

SharePoint 2013 Idioma Español versión Standard con un hotfix de Marzo 2013 instalada.

Las apps fueron desarrolladas para para SharePoint online y nadie nos había reportado este problema pero luego de instalarla en un cliente en SharePoint 2013 On Premises, reportaron que algunos usuarios no veían el contenido de ninguna App.  Estas mostraban diferentes contenidos como imágenes, links, información de los empleados.

Probamos de todo, diferentes navegadores, diferentes computadoras, y siempre que el usuario ingresaba con su usuario y contraseña en diferentes computadoras y navegadores, n o les mostraba el contenido de ningún App.

Por lo que publique el problema en el foro de technet.microsoft.com relacionado con Apps en SharePoint 2013.

http://social.technet.microsoft.com/Forums/en-US/75b55f98-c4db-49e5-9001-4997ff5f5966/some-users-do-not-display-the-contents-of-app-part-and-do-not-show-any-errors-on-sharepoint-2013-on?prof=required

Allí me aconsejaron que descargará fiddler y revisará el tráfico entre el navegador y el servidor.  Y el error que reportaba fiddler al intentar autenticarse para acceder los archivos JS de no autorización.

Bueno luego de analizar la información y realizar muchas pruebas hayamos el problema.  Los usuarios que tenían acceso limitado al Internet eran los que las Apps no podían renderizar el contenido a pesar que tenían acceso a las listas e imágenes del App Web y  el problema se debía a que todas las Apps tenían una referencia a la librería microsoft.ajax.js en la nube y esto evitaba que el contenido lo pudiesen ver.  La línea de código era la siguiente:

<script type="text/javascript" src="https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js">

La Solución:

Bueno se descargó el archivo microsoftAjax.js en una carpeta de scripts dentro del App y se hizo referencia de esta.  Se publicó de nuevo cada App y el problema se resolvió.

Apps4Fun!,

Juan Manuel Herrera Ocheita

domingo, 15 de septiembre de 2013

Cómo subir masivamente fotografías a los perfiles de usuario de SharePoint 2013

Hay algunos artículos en la red sobre este tema que me ayudaron a realizar el script en PowerShell para subir de forma masiva las fotografías de los usuarios a los perfiles de usuario de SharePoint 2013.

Gracias a Toni Frankola por su artículo que me sirvicio de base para crear script personalizado para subir las fotografías de los usuarios a SharePoint 2013.  Abajo el artículo base:

http://www.sharepointusecases.com/index.php/2012/12/use-case-automatically-importing-user-profile-pictures-to-sharepoint-2013-and-2010/

El Problema:

En este escenario se cuenta con un archivo de Excel que tiene asociado un código de empleado con la ubicación de la fotografía del usuario y no con la cuenta de dominio.  Por lo que el procedimiento que se realizó para este caso en particular fue el siguiente:

1) Se actualizó el código de empleado en el Directorio Activo y para ello se utilizó un campo disponible en el Directorio como lo es la ciudad o City.

http://technet.microsoft.com/en-us/library/hh524307.aspx

3) En el servicio de aplicación perfiles de usuario en SharePoint se mapeo esta propiedad del directorio activo con una propiedad personalizada en las propiedades del perfil de usuario en SharePoint

4) Se realizó una sincronización completa de los usuarios del directorio activo en SharePoint

5) Se validó que el campo se había actualizado

6) Se creó el script que hiciera lo siguiente:

1) Lea un archivo CSV que obtuviera el código de empleado y la ruta de la imagen

2) Comparará con cada uno de los perfiles de los usuarios importados en SharePoint, el código de empleado del archivo con el código de empleado del perfil de usuario para obtener su cuenta de dominio

3) Que cargará la fotografía en memoria

4) Que la subiera a la biblioteca de imágenes de los perfiles de usuario asociada a cada perfil.

 

El Mapeo de propiedad en el UPA

En el servicio de Aplicación User Profiles o Perfiles de Usuario seleccionamos la opción “administrar propiedades del usuario” o “Manage User Profile Properties”

image

Ahora seleccionamos “Nueva Propiedad” o “New Property”

image

Llenamos el campo Nombre y nombre para desplegar, seleccionamos el tipo de dato que para este ejemplo es una cadena de caracteres o String.

image

Luego indicamos que la configuración de privacidad predeterminada es todos para que nos permita seleccionar la opción “Replicable”, luego seleccionamos la opción de configuración de edición de no permitirlo y luego las opciones de presentación que nos permita mostrar la propiedad en la sección de propiedades del perfil de usuario.

 

image

En esta área de la página de edición de la propiedad del perfil es donde se mapea con el AD, para ello seleccionamos la conexión de datos de origen hacia el AD Previamente creada y luego seleccionamos el atributo del Directorio Activo que para City es L minúscula según la tabla de abajo y seleccionamos para la dirección de actualización en Importar.

La Estructura del archivo CSV

CODIGO , FOTOGRAFIA

1009, C:\FOTOS\JUAN MARTINEZ.JPG

1010, C:\FOTOS\ROBERTO AZURDIA.JPG

1020, C:\FOTOS\ANA GONZALEZ.JPG

El Script:

#  DEFINIMOS LAS VARIABLES A UTILIZAR

$InvFile = "ListadoUsuarioYRutas.csv"

# LA DIRECCION DE MY SITES O MIS SITIOS ESTO VARIA DE INSTALACIÓN EN INSTALACIÓN DE SHAREPOINT CONSULTE AL ADMINISTRADOR O REVISE EL CENTRAL ADMINISTRACION PARA DESCUBRIR ESTA URL


$farmUrl =  http://misitio.midominio/

$site=Get-SPSite $farmUrl
$web=$site.RootWeb
$serverContext=[Microsoft.Office.Server.ServerContext]::GetContext($site)

# SE CARGA EN MEMORIA EL USER PROFILE MANAGER PARA MAS TARDE OBTENER LOS PERFILES DE LOS USUARIOS EN SHAREPOINT
$upm=New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serverContext)


# SE CARGA EN MEMORIA EL ARCHIVO CSV

$FileExists = (Test-Path $InvFile -PathType Leaf)
if ($FileExists) {
   "Loading $InvFile for processing..."
   $tblData = Import-CSV $InvFile
} else {
   "$InvFile not found - stopping import!"
   exit
}

# Leyendo Archivo de Codigos y Fotos ..."
$contador = 0
$perfiles = $upm.GetEnumerator()
foreach ($row in $tblData)
{
   $picture = $row."FOTOGRAFIA"
   if( $picture)
   {

    # LEE CADA FILA Y CADA COLUMNA DEL ARCHIVO CSV Y OBTIENE LE CODIGO Y LA RUTA DE LA IMAGEN
    $codigoLista = $row."CODIGO".ToString()
    $PicturePath = "e:\" + $row."FOTOGRAFIA".ToString()
    $perfiles = $upm.GetEnumerator()
    # SE OBTIENE LOS PERFILES DE USUARIO DEL USER PROFILE MANGER 
    foreach($up in $perfiles)
    {

        $codigoUPA = $up["CodigoEmpleado"]

#  SI ENCONTRO UN CODIGO DE EMPLEADO EN EL PERFIL
        if ($codigoUPA)
        {

          # SE COMPARA SI EL CODIGO DE EMPLEADO DEL PERFIL DE USUARIO ES IGUAL  A DEL ARCHIVO
         if ($codigoUPA -eq $codigoLista)
         {
            $FileExists = (Test-Path $PicturePath -PathType Leaf)

            # SE VALIDA SI EL ARCHIVO IMAGEN EXISTE EN LA RUTA INDICADA
            if ($FileExists) {
                $account = $up.AccountName
                $contador = $contador + 1
               write-host $contador " - " $account " - " $codigoUPA " - " $PicturePath

         # SE EJECUTA UN METODO SET-SPPROFILEPICTURES PARA SUBIR LA IMAGEN A SHAREPOINT

    # USER PHOTOS ES LA BIBLIOTECA DE MI SITES DONDE SE GUARDA LAS IMAGENES DE LOS PERFILES DE USUARIO

         set-SPProfilePictures -weburl $farmUrl -picLibraryName "User Photos"  -localFolderPath $PicturePath -accountName $account -up $up
             }
         }
        }
    }
 
    }
}
Write-Host "End of file"

# METODO PARA SUBIR LA IMAGEN DE SHAREPOINT

function set-SPProfilePictures([string]$webUrl, [string]$picLibraryName, [string]$localFolderPath, [string]$accountName, $up)
{
    # CARGA EL SITIO WEB DONDE ESTA LA BIBLIOTECA DE IMAGENES

    $web = Get-SPWeb $webUrl

    # $picLibraryName = “USER PHOTOS”
    $picFolder = $web.Folders[$picLibraryName]
    if(!$picFolder)
    {
        Write-Host "Picture Library Folder not found"
        return
     }
 
        $username = [IO.Path]::GetFileNameWithoutExtension($localFolderPath);
        $fileName = [IO.Path]::GetFileName($localFolderPath);
 
        #SE CARGA EN MEMORIA LA IMAGEN

        $fileStream = ([System.IO.FileInfo] ($localFolderPath)).OpenRead()
        $contents = new-object byte[] $fileStream.Length
        $fileStream.Read($contents, 0, [int]$fileStream.Length);
        $fileStream.Close();
 
        write-host "Copying" $username "to" $picLibraryName "in" $web.Title "..."
 
        #SE ADICIONAL LA IMAGEN EN MEMORIA EN LA BIBLIOTECA USER PHOTOS
        $spFile = $picFolder.Files.Add($picFolder.Url + "/" + $fileName, $contents, $true)
        $spItem = $spFile.Item
 
        # SE OBTIENE LA PROPIEDAD DEL USUARIO QUE GUARDA EL URL DONDE ESTA ALMACENADA LA IMAGEN O FOTOGRAFIA
        $picturePropertyName = GetProfilePropertyName -UserProfileManager $upm -PropertyName "PictureUrl";
 
        if($up -ne $null)
        {
            if (-not [System.String]::IsNullOrEmpty($picturePropertyName))
            {
                $PortraitUrl = CombineUrls -baseUrl $spFile.Web.Url -relUrl $spFile.ServerRelativeUrl;
                Write-Host $PortraitUrl

                # SE ACTUALIZA
                $up.get_Item($picturePropertyName).Value = $PortraitUrl;
                $up.Commit();
            }
        }
 
   
 
    Write-Host "Updating User Profile Photo Store..." -foregroundcolor yellow

    # FINALMENTE ACTUALIZA LA FOTO. MY IMPORTANTE EL PARAMETRO CreateThumbnailsForImportedPhotos SI NO SE INCLUYE A UN ERROR QUE NO PUEDE SER SUBIDA LA IMAGEN SIGUIENTE
    Update-SPProfilePhotoStore -CreateThumbnailsForImportedPhotos 1  –MySiteHostLocation $webUrl
    Write-Host "Done" -foregroundcolor green
}

Y eso es todo, demora la actualización, le sugiero ejecute un debug con el editor de power shell para comprender mejor lo que hace y comentarle que esto demora y esta sujeto a errores sino la imagen no esta correctamente copiada o bien tiene caracteres especiales como tíldes y eñes.  Por lo demás funciona muy bien, pero demora la actualización, al final es mejor que subirla manualmente y pueda que el script lo mejore y optimice para su conveniencia pero depende de usted.  Abajo lo dejo con el script completo que utilice para actualizar las fotografías.

Scripting4Fun!,

Juan Manuel Herrera Ocheita

#--- PRINCIPIO DEL SCRIPT -----

if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
    Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
function ToSimpleString([string]$value, [bool]$trim = $true, [bool]$removeSpaces = $true,

[bool]$toLower = $true)
{
    if ($value -eq $null) { return [System.String]::Empty; }
 
    if ($trim)
    {
        $value = $value.Trim();
    }
 
    if ($removeSpaces)
    {
        $value = $value.Replace(" ", "");
    }
 
    if ($toLower)
    {
        $value = $value.ToLower();
    }
 
    return $value;
}

function CombineUrls([string]$baseUrl, [string]$relUrl)
{
    [System.Uri]$base = New-Object System.Uri($baseUrl, [System.UriKind]::Absolute);
    [System.Uri]$rel = New-Object System.Uri($relUrl, [System.UriKind]::Relative);
 
    return (New-Object System.Uri($base, $rel)).ToString();
}

function GetProfilePropertyName($userProfileManager, $propertyName)
{
    $propertyName = (ToSimpleString -value $propertyName);
    $propertyName = $propertyName.Replace("sps-", "");
 
    foreach($prop in $userProfileManager.Properties)
    {
        [string]$n = (ToSimpleString -value $prop.DisplayName);
        $n = $n.Replace("sps-", "");
        if ($propertyName -eq $n) { return $prop.Name.ToString(); }
 
        $n = (ToSimpleString -value $prop.Name);
        $n = $n.Replace("sps-", "");
        if ($propertyName -eq $n) { return $prop.Name.ToString(); }
    }
 
    return $null;
}
 
function set-SPProfilePictures([string]$webUrl, [string]$picLibraryName, [string]$localFolderPath, [string]$accountName, $up)
{
    #Get web and picture library folder that will store the pictures
    $web = Get-SPWeb $webUrl
    $picFolder = $web.Folders[$picLibraryName]
    if(!$picFolder)
    {
        Write-Host "Picture Library Folder not found"
        return
     }
 
        $username = [IO.Path]::GetFileNameWithoutExtension($localFolderPath);
        $fileName = [IO.Path]::GetFileName($localFolderPath);
 
        #Create file stream object from file
        $fileStream = ([System.IO.FileInfo] ($localFolderPath)).OpenRead()
        $contents = new-object byte[] $fileStream.Length
        $fileStream.Read($contents, 0, [int]$fileStream.Length);
        $fileStream.Close();
 
        write-host "Copying" $username "to" $picLibraryName "in" $web.Title "..."
 
        #Add file
        $spFile = $picFolder.Files.Add($picFolder.Url + "/" + $fileName, $contents, $true)
        $spItem = $spFile.Item
 
       
        $picturePropertyName = GetProfilePropertyName -UserProfileManager $upm -PropertyName "PictureUrl";
 
        if($up -ne $null)
        {
            if (-not [System.String]::IsNullOrEmpty($picturePropertyName))
            {
                $PortraitUrl = CombineUrls -baseUrl $spFile.Web.Url -relUrl $spFile.ServerRelativeUrl;
                Write-Host $PortraitUrl
                $up.get_Item($picturePropertyName).Value = $PortraitUrl;
                $up.Commit();
            }
        }
 
   
 
    Write-Host "Updating User Profile Photo Store..." -foregroundcolor yellow
    Update-SPProfilePhotoStore –MySiteHostLocation $webUrl
    Write-Host "Done" -foregroundcolor green
}

$InvFile = "arhivoCodigosyRutas.csv"
$farmUrl =  http://misitio.sudominio/

$site=Get-SPSite $farmUrl
$web=$site.RootWeb
$serverContext=[Microsoft.Office.Server.ServerContext]::GetContext($site)
$upm=New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($serverContext)


# Get Data from Inventory CSV File
$FileExists = (Test-Path $InvFile -PathType Leaf)
if ($FileExists) {
   "Loading $InvFile for processing..."
   $tblData = Import-CSV $InvFile
} else {
   "$InvFile not found - stopping import!"
   exit
}

# Loop through file  compare an get an account

"Uploading data to SharePoint...."
$contador = 0
$perfiles = $upm.GetEnumerator()
foreach ($row in $tblData)
{
   $picture = $row."FOTOGRAFIA"
   if( $picture)
   {
    $codigoLista = $row."CODIGO".ToString()
    $PicturePath = "e:\" + $row."FOTOGRAFIA".ToString()
    $perfiles = $upm.GetEnumerator()
 
    foreach($up in $perfiles)
    {
        $codigoUPA = $up["Codigo"]
        if ($codigoUPA)
        {
         if ($codigoUPA -eq $codigoLista)
         {
            $FileExists = (Test-Path $PicturePath -PathType Leaf)
            if ($FileExists) {
                $account = $up.AccountName
                $contador = $contador + 1
                write-host $contador " - " $account " - " $codigoUPA " - " $PicturePath
                set-SPProfilePictures -weburl $farmUrl -picLibraryName "User Photos"  -localFolderPath $PicturePath -accountName $account -up $up
             }
         }
        }
    }
 
    }
}
#User%20Photos
Write-Host "End of file"
# -- FINAL DEL SCRIPT ----

 

Tabla de propiedades del Directorio Activo

Active Directory user attribute
Microsoft.AD.User property
physicaldeliveryofficename Office
displayname displayname
company Company
employeeid Employeeid
department Department
telephonenumber BusinessPhone
homePhone HomePhone
facsimileTelephoneNumber Fax
mobile Mobile
pager Pager
mail Email
givenname FirstName
initials Initials
sn LastName
distinguishedname Distinguishedname
title Title
manager manager
samaccountname UserName
l City
StreetAddress StreetAddress
st State
postalCode Zip
co Country
localeID Locale
msRTCSIP-PrimaryUserAddress SipAddress
objectSid SID
Domain Domain

Referencia oficial y completa en http://technet.microsoft.com/en-us/library/hh524307.aspx

domingo, 25 de agosto de 2013

Integración Continua - Creando un Build en Team Foundation Service para desplegar un App en SharePoint Online

 

Para pruebas es muy útil contar con una herramienta que nos permita instalar o desplegar el App de SharePoint automáticamente en un sitio de SharePoint Online en Office 365 y esto es precisamente lo que hace Team Foundation Service que es la versión Online de Team Foundation Server y que para 5 usuarios es gratuita (para más información ver http://tfs.visualstudio.com). 

Escenario:

Para este artículo vamos a crear un proyecto de Apps para SharePoint SharePoint Hosted es decir que se hospedará en SharePoint a diferencia de los otros proyectos Auto Hosted (Azure) y Provider Hosted (Terceros) este no utiliza código de servidor sino únicamente Javascript con lo cual tiene sus ventajas y sus desventajas, entre las ventajas es que es muy rápido para el usuario final, para el programador fácil de instalar el App pero entre las desventajas es el no poder escribir código de servidor y por ende la exposición del código de lado del cliente.

http://msdn.microsoft.com/en-us/library/office/apps/fp179887.aspx

Este proyecto debe de ser desplegado para propósitos de prueba en un sitio de SharePoint Online para desarrollador, por lo que el script deberá ser modificado para que cree el paquete y lo instale en el sitio de desarrollador en SharePoint Online.

El proceso:

Para poder automatizar el proceso es necesario contar con un Script que ejecute los comandos necesarios para instalar el App en SharePoint Online.  Para obtener este script debemos de visitar la siguiente dirección:

https://officesharepointci.codeplex.com/

Este sitio permitirá descargar un archivo OfficeSharePointCI.zip este contiene un archivo OfficeToolsAppTemplate.xaml como plantilla del proceso de Build especializado para construir e instalar las Apps de SharePoint.

También contiene los scripts necesarios para instalar el App para ello es necesario 4 scripts:

Parameters.ps1
Common.ps1
DeploymentFunctions.ps1

SharePointAppDeploy.ps1

De los cuales el último es el principal que llama a los otros y que debe de ser el seleccionado para asociarlo a la definición del Build.  Cómo se muestra en la imagen de abajo.

image

Como vamos a modificar los scripts para este ejemplo las buenas prácticas dictan que debemos de subirlas al control de versiones en TFS como se muestra en la imagen de abajo:

image

Vamos a revisar los scripts para ver que hace cada uno.  Empecemos con parameters.ps1

Este tiene los parametros que va utilizar el script SharePointAppDeploy.ps1 que ya modificado contiene lo sigueinte:

# SharePoint account used to deploy the app.
$SpDeployUsername = "micuenta@midominio.com"
$SpDeployPassword = "*******"
$SpDeployUserDomain = ""

Básicamente contiene la declaración de las variables a utilizar que como es SharePoint Online no se utiliza la variable que define el dominio.


common.ps1


image


Contiene los métodos que encapsulan los comandos de powershell comunes para realizar la instalación del App en SharePoint, más adelante veremos como estos son invocados en el script principal.


DeploymentFunctions.ps1


image


Entre las funciones que podemos destacar de este script esta Install-App el cual recibe como parámetros el contexto del client, el Web site de SharePoint la ruta del archivo de resumen.  Basicamente esta función toma el paquete del app y lo instala via comando de Powershell y basado en el contexto del cliente obtenido por medio del parámetro que recibió el método.


SharePointAppDeploy.ps1

# Recibe los parametros de la definición del Build en TFS como se muestra en la imagen de abajo.
Param (     [Parameter(Mandatory = $true)]     [string]$dropLocation,     [Parameter(Mandatory = $false)]     [string]$summaryFile
)
# Cambia la ruta para cargar los scripts arriba mencionados
cd "$(Split-Path $MyInvocation.MyCommand.Path)"

. .\ParametersSPDeploy.ps1
. ..\Common.ps1
. .\DeploymentFunctions.ps1
# La ruta donde se instalará el App y que es un sitio para desarrollador
$SharePointDeployServerUrl = "https://midominio.sharepoint.com/sites/developer"

try {     Write-Host "Connecting to $SharePointDeployServerUrl..."
    # invoca el método Create-SharePointClientContext del script common.ps1 y utiliza las variables declaradas en el script Parameters.ps1     
$clientContext = Create-SharePointClientContext $SharePointDeployServerUrl $SpDeployUserDomain $SpDeployUsername $SpDeployPassword               
# Declara la variable $web con el valor de la instancia del sitio web donde se va a instalar el app
$web = $clientContext.Web     
# Se le indica que debe de ser cargado en memoria
$clientContext.Load($web)     
# Se ejecuta los comandos arriba mencionados esto viaja al servidor y devuelve los valores solicitados
$clientContext.ExecuteQuery()     
# Varios comandos en una sola linea, el primero obtiene el paquete del App desde la ubicación de descarga o droplocation luego el paquete es instalado utilizando el método Install-App del Script DeploymentFunctions.ps1
Get-AppPackages $dropLocation | Install-App $clientContext $web $summaryFile     
}
catch {     Write-Error "Error occurred: " $_.Exception.ToString()
}

Y eso es todo en cuanto los scripts ahora como esto se integra con TFS y se ejecuta para ello vamos a crear un proyecto tipo SharePointHosted que lo denominaremos SharePointApp1


image


Luego que va a ser de tipo SharePoint Hosted App y que va ser instalada para depuración en un sitio de desarrollador en Office 365


image


Para ello es necesario tener una suscripción en Office 365 de prueba para desarrollador o bien alquilada.   Para más información visite el siguiente link: http://msdn.microsoft.com/es-es/library/office/apps/fp179924(v=office.15) 


image


o si ya tiene una haga clic en validate e ingrese sus credenciales, como se muestra abajo en la imagen.


image


Le mostrará una ventana de dialogo de conexión exitosa.


image


Presione el botón finish para continuar.


Esta App para efectos de concentrarnos en al automatización de la instalación solo mostrará además del usuario un titulo que indica Integración Continua


image


Si Presionamos F5 veremos lo que hace y muestra el App.  Nos solicitará que nos autentiquemos en Office 365


image


image


Bueno ahora con el proyecto abierto vamos a crear la definición del Build.  Para ello vamos a utilizar Team Explorer, en la sección Home en la opción Builds.


image


Seleccionamos la opción New Build Definition


image


Al hacer esto nos solicitará las credenciales para Team Foundation Service


image


Definimos un nombre para la definición SharePointApp1 Build.


image


Definimos el disparador o Trigger, Integración continua para cada Check-in construya o compile el App


image


Ahora seleccionaremos los predeterminados del Build, como lo són el controlador y la carpeta de descarga o drop folder de la fase de construcción.


image


En el Proceso esta la clave para poder desplegar el App en un sitio de SharePoint Online.  En Show details debemos seleccionar la plantilla xml para Office que descargamos del sitio de codeplex y subimos al control de versiones de TFS.


image


Seleccionamos el botón New y este levantará una ventana de dialogo New Build Process Template y selecionamos la opción Select an existing XAML file y luego el botón Browse


image


Seleccionamos la ubicación donde subimos la plantilla OfficeToolsAppTemplate.XAML, la seleccionamos y presionamos el botón ok dos veces para cerrar la ventana de dialogo anterior.


image


Ahora cargará la nueva plantilla y en la seccion 3.Advanced en el campo MSBuild Arguments colocamos el valor /p:IsPackaging=true


image


Ahora en la sección 4.Misc en el campo Deployment Script seleccionaremos el script que instalará el App en un sitio de desarrollador distinto que esta planificado sea donde se realizarán las pruebas finales del App. el cual en este ejemplo es https://midominio.sharepoint.com/sites/developer


image


Deberá visualizarse similar a la imagen de abajo.






image



Para finalizar vamos a guardar el build y a realizar un cambio para validar que la integración continua funcione.


Agregamos a la etiqueta h3 de la pagina default.aspx un texto Ready !, lo guardamos.


image


Y hacemos un Checkin del cambio


image


Luego desde el Team Explorer de Visual Studio 2012 seleccionamos Builds y nos desplegará el build que se esta ejecutando


image


Revisamos que esta en progreso y esperamos que termine


image


Y nos deberá mostrar que ha terminado con éxito. Y seleccionamos el enlace View Build Details


image


Y luego al revisar el detalle nos muestra la dirección url donde podemos abrir el App.




image


Nos solicitará autenticarnos en Office 365.




image


Y guala! aquí esta el App con el cambio listo para realizar pruebas de explorarción, de UI y otros en un sitio distinto al sitio donde depuramos la aplicación antes de hacer el checkin.


image


En este artículo vimos como automatizar el proceso de instalación de un App para SharePoint en Office 365.


Hasta la próxima,


Juan Manuel Herrera Ocheita