jueves, 4 de septiembre de 2014

Inventario de WorkFlows en Sharepoint 2010

Mediante este Script PowerShell podemos realizar un inventario de Workflows en Sharepoint 2010 o 2013

He incluido la opción de sacarlo por OutGrid o por CSV
También se ha extraído el AssemblyName y el ClassName del XML de configuración, de forma que permite localizar los proyectos/componentes que los contienen.
Para filtrar los workflows de aprobación (Nativos) del listado se ha usado un -NotLike, podemos usar esta linea para filtrar otros o localizar uno concreto

#List all workflows in farm
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

function ListWF()
{
    #Grab all webs
    Get-SPSite -Limit All | % {$webs += $_.Allwebs}
    if($webs.count -ge 1)
    {
        foreach($web in $webs)
        {
                #Grab all lists in the current web
                $lists = $web.Lists
                foreach($list in $lists)
                {
                   #Get all workflows that are associated with the current list
                        foreach($listassociation in $list.WorkflowAssociations)
                        {
                            if( $listassociation.name -NotLike "Aprobaci*")
                            {
                                [xml]$xmlconf=$listassociation.BaseTemplate.xml;
                                $data = @{
                                "Lista" = $List.Title; 
                                "Web" = $web.Url;
                                "NombreAsociacion" = $listassociation.name;
                                "Name" =$listassociation.BaseTemplate.Name;
                                "ID" =$listassociation.BaseTemplate.ID;
                                "CodeBesideClass" =$xmlconf.WorkflowTemplate.WorkFlowTemplateIdSet.CodeBesideClass;
                                "CodeBesideAssembly" =$xmlconf.WorkflowTemplate.WorkFlowTemplateIdSet.CodeBesideAssm;
                                }
                            New-Object PSObject -Property $data
                            }
                        }
               }         

        }
    $web.Dispose()
    }


}
ListWF | Out-GridView
#$csvFilePath = "C:\Workflows_Listado.csv"
#ListWF | Export-Csv -NoTypeInformation -Path $csvFilePath


jueves, 12 de diciembre de 2013

Suplantar Usuarios en Sharepoint 2013 y verificar la pertenencia a Grupos

Os quiero explicar una de esas cosas tan simples que uno quiere saber, como por ejemplo a que grupos pertenece un usuario.

Resulta que no es nada fácil ni mas ni menos hay que recuperar al usuario, suplantarlo, desactivar la captura de excepciones de seguridad y entonces podemos mirar y actuar sin restricciones en nombre de otro usuario.... que miedo.

Os quiero resaltar 4 cosas complejas metidas en una sola función.

1º En Rosa: Como recuperar un usuario concreto (SPUser) de la web actual
2º En rojo : Como abrir un SPSite Suplantando a un usuario, con el truco del userToken y el ID de Site/Web, sin sus contraseña... no nos hace falta.
3º En verde : Como desactivar la captura de Excepciones de Acceso denegado
4º En Azul : Como verificar la pertenencia a un grupo del usuario suplantado.

Nota: Recordad que dentro de un RunWithElevated no podemos usar directamente el SPContext.Current.Site ni el SPContext.Current.Web, tan solo podemos recuperar el ID para crear el objeto dentro del codigo de privilegios elevados.

Espero que os resulte útil este "agujero de seguridad" de sharepoint.
Nadie os impide suplantar a gente.... ni ser malos.
Funciona en todas las versiones de Sharepoint 2007,2010,2013.

 public List<string> GetAllGroupsFromUser(string sLogin)
        {
            List<string> listapertenencia = new List<string>();

            userName = sLogin;
            SPUser usuario;
            try
            {
                usuario = SPContext.Current.Web.AllUsers[userName];
            }catch(Exception ex)
            {
                usuario = null;
            }

            if (usuario != null)
            {
                SPUserToken userToken = SPContext.Current.Web.AllUsers[userName].UserToken;
                SPSecurity.RunWithElevatedPrivileges(delegate()
                            {
                                bool AccessDeniedflag = SPSecurity.CatchAccessDeniedException;
                                SPSecurity.CatchAccessDeniedException = false;
                                try
                                {

                                    using (SPSite contextSiteColl = new SPSite(SPContext.Current.Site.ID, userToken))
                                    {

                                        using (SPWeb contextSite = contextSiteColl.OpenWeb(SPContext.Current.Web.ID))
                                        {
                                            foreach (SPGroup grp in contextSite.SiteGroups)
                                            {
                                                if (contextSite.SiteGroups[grp.Name].ContainsCurrentUser)
                                                {
                                                    listapertenencia.Add(grp.Name);
                                                }
                                            }
                                        }

                                    }
                                }
                                catch (UnauthorizedAccessException ex)
                                {
                                    listapertenencia.Add("---"); //Error
                                }
                                finally 
                                {
                                    SPSecurity.CatchAccessDeniedException = AccessDeniedflag;
                                }
                                  
                            });
            }
            return listapertenencia;
        }

jueves, 23 de mayo de 2013

Comandos Powershell para Instalar Soluciones y Caracteristicas

Dejo aquí la lista de comandos powershell para instalar/actualizar soluciones y características, a modo de chuleta para no tener que buscarlo.


Add SolutionAdd-SPSolution c:\solutions\myproject.wsp

Deploy Solution
Install-SPSolution –Identity myproject.wsp –WebApplication http://myprojectsite -GACDeployment
Nota: Se pueden usar los parametros
  • –CASPolicies: Si no quieres desplegar a la GAC
  • –AllWebApplications: Si quieres desplegar la solucion a todas las aplicaciones web
  • –Force: para forzar el despliegue de la solucion
Upgrade Solution
Update-SPSolution –Identity myproject.wsp –LiteralPath c:\solutions\myproject.wsp –GACDeployment
Retract Solution
Uninstall-SPSolution –Identity myproject.wsp –WebApplication http://myprojectsite
Remove Solution
Remove-SPSolution –Identity myproject.wsp
Activate Feature
Enable-SPFeature –Identity MyFeature –url http://myprojectsite
Deactivate Feature
Disable-SPFeature –Identity MyFeature –url http://myprojectsite

martes, 14 de mayo de 2013

Depuración remota avanzada con Visual Studio y Sharepoint

Objetivo:
Realizar una depuración paso a paso usando Visual Studio 2010 de un componente (WebPart,Httpmodule,TimerJob,Feature,WebService,etc..) desplegado en un servidor remoto.

Introducción:
En ocasiones es "imposible" reproducir un entorno completamente real en una maquina local destinada para desarrollo, seguramente a muchos de nosotros nos pasa que al desplegar una solución probada hasta la saciedad, comienza a dar errores en el entorno destino, los cuales no somos capaces de reproducir.
Una solución es guardar trazas, en Ficheros de Log, EventViewer, etc..  Resulta muy buena práctica el uso de trazas, pero no es tan rápido como adjuntarnos a un proceso y depurar cualquier error que se produzca, sea cual sea ,activando  la captura de todo tipo de excepciones lanzadas (ver imágenes).
Esto último resulta extremadamente útil cuando no sabes por donde fallan las cosas.
Es harina de otro costal el poner un punto de interrupción y depurar desde nuestro visual Studio en un servidor remoto, y es precisamente lo que quiero explicar en este post, paso a paso.

Ingredientes necesarios en la máquina de desarrollo (Cliente):
1)      Visual Studio 2010 con nuestro proyecto en cuestión abierto y con los puntos de interrupción colocados.
2)      Compilar en Modo Debug y desplegar en el servidor.
3)      En la carpeta de compilación localizamos el fichero .PDB que genera Visual Studio en la carpeta /debug del proyecto, los usaremos más adelante.
4)      Abrir el firewall de Windows para todas las conexiones entrantes al PROGRAMA Remote Debugger (msvmom.exe) tanto para TCP como para UDP
http://msdn.microsoft.com/es-es/library/vstudio/bb385831(v=vs.100).aspx

Ingredientes necesarios  en el Servidor:
1)      Microsoft Visual Studio 2010 Remote Debugger (Instalado en el servidor)
http://www.microsoft.com/en-us/download/details.aspx?id=475
2)      Abrir el firewall de Windows para todas las conexiones entrantes al PROGRAMA Remote Debugger (msvmom.exe) tanto para TCP como para UDP a veces sale este mensaje.
http://msdn.microsoft.com/es-es/library/vstudio/bb385831(v=vs.100).aspx
3)      Desplegar el proyecto compilado en modo Debug en visual Studio.
4)      Si nuestro proyecto despliega a la carpeta /BIN de IIS todo es mas fácil  solo hay que copiar el fichero .PDB del punto 3 en la misma carpeta que la DLL que hemos generado en el cliente.
a.       Si el proyecto despliega a la GAC hay que abrirla en modo "Carpeta" para asi poder copiar el .PDB, esta opción se activa añadiendo la propiedad DWORD, disablecacheviewer con valor 1 en esta ruta del Registro del windows en el servidor : HKLM\Software\Microsoft\Fusion

La GAC vista como carpetas:
5)      Arrancar el Remote Debugger en el servidor
Nota:  tiene que coincidir la version y la arquitectura de procesador del cliente y servidor Cliente_x86==Servidor_x86  Cliente_x64==Servidor_x64
estan ubicados en la ruta C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Remote Debugger\  en la carpeta x64   o x86
6)      Dar permisos al usuario del cliente que quiere depurar, en la opción de permisos (esto no se guarda hay que hacerlo siempre que se reinicie el remote debugger) hay que darle a Aceptar cuando nos pregunta si queremos realmente depurar.


7)      En el Remote debugger Abrimos las Opciones y copiamos el nombre del servidor (lo necesitaremos),  es del tipo "mi_dominio\mi_usuario@nombre_servidor" también podemos Activar la opción de "Sin autenticación (solo nativo)" marcando "permitir que cualquier usuario depure", esto a veces es mas sencillo (e inseguro).

8)      Abrir IIS , y el apartado de WorkerProcesses para obtener el numero de PID del proceso a depurar, lo necesitaremos en el ultimo paso.


Si ya hemos realizado los pasos preparatorios, ahora podemos hacer …

DEPURACIÓN REMOTA
1º Desde el cliente, en el Visual Studio seleccionamos: Debug>AttachToProcess

2º En la ventana de Attach to process en el recuadro de Qualifier, escribimos el Servidor en cuestión que copiamos de las opciones del remote debugger en el servidor.
3º Se cargan todos los procesos, seleccionamos el w3wp.exe que tiene el PID que apuntamos en el Punto 8 de workerprocess.
4º Pulsamos  ATTACH y …. Voila, ya estamos depurando, ahora solo lanzar la parte que queréis depurar vía navegación y saltara el punto de interrupción.

Notas: No olvidéis copiar el .PDB en cada nueva compilación  el PID del workerprocess cambia con cada Reciclado de application Pool y con cada IIS Reset.

Truco:
Si creáis una Aplicación web Extendida de Sharepoint, en otro puerto con otro AplicationPool, no paráis todo el entorno, esto es muy útil para un equipo de desarrollo que anda depurando continuamente.

Espero que os resulte de utilidad,  y muchas gracias a Luis Lázaro por instruirme en estas difíciles artes.


lunes, 13 de mayo de 2013

Errores 403 Forbidden en SharePoint

Problema:
De manera intermitente y especialmente a reciclar en ApplicationPool o hacer IIS Reset, al acceder a Sharepoint aparecen Errores 403 Forbidden.

Pistas de resolución:
Aunque el usuario tenga los permisos adecuados en la colección de sitios, en ocasiones vuelve a aparecer.
En cambio al identificarse como un administrador con permisos de administración en los frontales, la pagina carga correctamente, incluso para todos los siguientes usuarios, por lo que suponemos que hay un problema de permisos tras la impersonación.

Utilizando la utilidad  "Filemon" o "Process Monitor" de SysInternals, localizamos un acceso denegado en el proceso w3wp.exe al acceder al directorio virtual "/bin" que solo es visible únicamente desde la consola de administración de IIS.

9


Diagnóstico:
El problema es de ASP.NET no de Sharepoint, el proceso usa las credenciales del usuario remoto para acceder, es especialmente en la primera carga (de DLL), cuando intenta acceder a este directorio virtual y es ahí donde se produce el acceso denegado. Posteriormente no intenta acceder es por ello que cuando un administrador se identifica, posteriormente ya no se produce el error.
Un usuario normal no tiene permisos de lectura y ejecución en este directorio virtual.
Nota:El error aparece especialmente si hay paginas con webparts de terceros o custom que usen ensamblados  ya que en primer lugar se buscan en /bin (donde se produce el error) y posteriormente en la GAC.

Solución:
1º Desde la consola de administración de IIS seleccionamos la carpeta /bin del sitio en cuestión que nos esté dando problemas.
2º Con el botón derecho desplegamos el menú contextual y seleccionamos "Edit permissions"
3º En la pestaña de Security y añadimos el grupo de usuarios nombre_servidor\users
4º Verificamos que puede (Listar Carpetas,Leer y Ejecutar)

Después de esto el problema desaparece.
Estos permisos pueden tener implicaciones de seguridad, especialmente si se expone el servidor a internet.

Espero que os resulte de utilidad.



miércoles, 8 de mayo de 2013

Sharepoint List Generator Web Part (ListGenWP)

He creado un web part que permite la creación masiva de listas sharepoint.

Solo hay que insertar el webpart en una pagina de sharepoint, por ejemplo en un directorio destinado a la administración del sitio
Es sencillo editar el XML ya sea introduciéndolo por el editor visual, generarlo o copiándolo de otro sitio

Lo he publicado en codeplex http://listgenwp.codeplex.com/

para que quien lo desee colabore en las funcionalidades que he planificado y bueno que así os ahorre trabajo en la pesada tarea de crear las listas.

De momento solo crea , me gustaría convertirlo en un editor de listas para hacerlo mas cómodo.

Sharepoint List Generator Web Part (ListGenWP)Generador de Listas Sharepoint, con un interfaz mas comodo y un fichero XML de Soporte que puede ser editado cargado Masivamente.
Facilita la creación de Listas con Lookups de forma Rápida.
Utiliza los nombres de Listas en lugar de los GUID por lo que funciona Siempre.
Utiliza un fichero XML que se puede generar y editar manualmente.
Permite Lookups enlazados entre listas.
NO utiliza GUID, utiliza el NOMBRE DE LISTA, para evitar problemas de portabilidad

Instrucciones
*1º Insertar las listas a crear
*2º Activar el Check "Crear" y Guardar
*3º Pulsar el Boton de Crear Listas
(bug:cuando se creen las listas hay que entrar en los campos lookup uno a uno y pulsar guardar para que funcione correctamente.)
Nota:Puede editar el XML de definición de listas ListasDef.xml de forma manual, reemplazarlo, salvarlo incluso automatizarlo.
Tipos de campo Permitidos
text : Campo de tipo texto, hay que especificar el tamaño
number : Campo de tipo Numero
currency: Campo de tipo moneda
lookup: Campo de tipo Lookup, hay que especificar la lista de origen y el campo de texto a mostrar (Hay un bug solventable)
date: Campo de tipo Fecha
datetime: Campo de tipo Fecha y Hora
calculated: Campo calculado Por ejemplo: CODIGO & ") " & DESCRIPCION , para por ejemplo rellenar Combobox
boolean: Campo tipo Si/No
percent: Numero en Porcentaje (%)


Autor: Roberto Marcos Asensio http://www.robertomarcos.com
Blog de Soporte: http://sharepointworks.blogspot.com

wpListSincMapper - Sincronizador de listas sharepoint por ODBC

Hola a todos,

Finalmente he conseguido una versión estable y completamente funcional del sincronizador de listas sharepoint que había prometido.
Lo he hecho con vs.net 2008 , también he configurado un instalador grafico para realizar el deploy mas cómodo.

Este es el sitio del proyecto: http://wplistsincmapper.codeplex.com/

También he creado un manual de instrucciones paso a paso muy cortito pero con capturas de pantalla para hacerlo mas fácil. Esta en ingles

Quería agradecer la ayuda aportada por Guillermo Martin (Goyo) sin el que una buena parte del proyecto se habría demorado mucho y gracias tambien por sus correcciones de mi ingles.

A modo de experimento he creado una cuenta paypal para donaciones por si alguien quiere aportar algo, y así poder irme de tapas con Goyo y mi hermano o tal vez de cena. Bueno no deja de ser un experimento :)


Dejo unas capturas de pantalla para abrir el apetito.




Mi intención es crear un migrador de sitios mucho mas grande en el que este proyecto solo es una pieza, para sincronizar y copiar listas sharepoint de entorno SQL
Muchas gracias por las ideas aportadas, estoy trabajando en algunas de ellas.
Espero que os sea de MUCHA UTILIDAD
Saludos, RobertoMarcos.com