lunes, 28 de febrero de 2011

Deshabilitar vista explorador con Excel Services

Excel Services consiste en un servicio de SharePoint 2010 que permite manejar ficheros Excel desde un entorno Web. Su principal objetivo es el de proveer de la potencia de cálculo de Excel mediante SharePoint.

Otra de sus cualidades es que se puede compartir gráficos, tablas dinámicas, … pero sin llegar a compartir las fórmulas y los datos de los que se obtienen.

image

Desde el post MOSS: Guías paso a paso de Excel Services y otros recursos! encontraréis una serie de artículos adicionales sobre cómo habilitar y configurar este servicio.

Uno de los problemas que encontraremos al habilitar Excel services es que todos los documentos con extensión .XLSX de la colección de sitios se abrirán por defecto en modo explorador aunque tengamos marcado que se muestre en modo cliente desde la biblioteca de documentos.

image

Para forzar que se abran los ficheros Office en modo cliente habilitaremos la feature “OpenInClient”, para éllo abriremos una consola de PowerShell:

$defaultOpenBehaviorFeatureId = $(Get-SPFeature -limit all | where {$_.displayname -eq "OpenInClient"}).Id

Con el Cmdlet Get-SPFeature devuelve un listado de las features disponibles, y mediante “where” aplicamos un filtro para obtener la feature cuya propiedad DisplayName sea igual a “OpenInClient”. Una vez obtenido el id de la feature y activaremos la feature.

Get-SPSite http://c8191497276/sitios/excelservices/ -limit ALL |foreach{ Ensable-SPFeature $defaultOpenBehaviorFeatureId -url $_.URL }

iisreset

image

image

 

Desde el post Configure the default open behavior for browser-enabled documents (Office Web Apps) encontrareis más información sobre como activar desactivar la funcionalidad browser-enabled.

lunes, 14 de febrero de 2011

Envío de alertas con Task Scheduler

I Love PowerShell, como hoy es el día de los enamorados quería tener un pequeño detalle con una herramienta a la que cada vez estoy cogiendo más aprecio, aunque muchos piensan que es solo para los administradores de sistemas, están muy equivocados, también es una herramienta para los desarrolladores. En esta ocasión he podido implementar una funcionalidad de monitorización con PowerShell y el TaskScheduler de Winwdows.

Mediante el programador de tareas de Windows 2008 podemos planificar tareas en base a un evento de sistema e incluso podemos añadirle ciertas condiciones. Para mí una de las funcionalidades más interesantes es la de poder notificar vía mail al producirse un error crítico en nuestro aplicativo. En concreto lo estoy utilizando para notificar errores de mis componentes de SharePoint, mediante el servicio SPDiagnosticsService podemos realizar una entrada en el log de sucesos windows con nuestro propio código con un código similar al siguiente:

SPDiagnosticsService diagSvc = SPDiagnosticsService.Local; 
WriteEvent(MiCodigoDeError, new SPDiagnosticsCategory(CATEGORIA, TraceSeverity.VerboseEx, EventSeverity.Error), Microsoft.SharePoint.Administration.EventSeverity.ErrorCritical, "Exception: {0} {1}”, new object[] { ex.Message, ex.StackTrace});



Una vez dispongamos de una entrada en el log de windows podemos asociarle una tarea seleccionando el evento y pulsando en “Attach task to this Event…”, se iniciará entonces un asistente para definir la tarea asociada al evento pudiendo seleccionar entre tres tipos de acciones: lanzar un programa, enviar un mail y mostrar un mensaje. Aunque lo ideal sería seleccionar la acción de “Enviar un mail” lo cierto es que esta acción solo envía un mail estático por lo que no podremos utilizarla si deseamos que nos indique en el mail el mensaje del evento que lanzó la acción.



Aquí es donde llega nuestro amigo PowerShell, con el que obtendremos el mensaje del último evento producido y enviáremos un mail con el formato que deseemos Sonrisa



imageimage



 



Lo primero será obtener el mensaje del evento que lanzó la tarea programada, para ello dispondremos del cmdlet Get-WinEvent. Con el siguiente script podremos por ejemplo obtener un listado con todas las entradas en el log de windows con el código 4664: 



Get-WinEvent -LogName "Application" | where {$_.Id -eq 4664} 



image



Para obtener el último mensaje limitaremos los resultados a 1 elemento y poder manejar una instancia de la clase :



$event = Get-WinEvent -LogName "Application" -MaxEvents 1 | where {$_.Id -eq 4664} 

$event.Message



image



Ahora solo quedaría componer el mail de la siguiente forma:







$emailFrom = "mailorigen" 
$emailTo = "maildestino"
$subject = "Error portal"
$body = $event.MachineName + " " + $event.Message

$smtpServer = "DirecciónSMTP"
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($emailFrom, $emailTo, $subject, $body)



Una vez tengamos el script completo lo guardaremos en un fichero con extensión “.ps1” e indicaremos en la acción que ejecute nuestro ps1 con una expresión similar a la siguiente:



%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe –Noninteractive C:\Windows\System32\TaskSendMail.ps1


image

jueves, 3 de febrero de 2011

[Tips SharePoint 2010] Qué bases de datos estoy utilizando?

En SharePoint 2010 las bases de datos se reproducen como champiñones, el problema lo podemos tener cuando tenemos varias aplicaciones web utilizando el asistente o queremos realizar un plan de mantenimiento desde SqlServer. Para saber las bases de datos que estamos utilizando podemos verlo desde la Administración central > Upgrade and migration > Review database status

Si preferimos utiliza PowerShell para obtener el listado de bases de datos:

Get-SPDatabase | Format-Table DisplayName, Name, Server –auto

o también:

Get-SPDatabase | foreach {$_.DisplayName, $_.Name, $_.Server}

 

image image

jueves, 27 de enero de 2011

Mis experiencias con Amazon EC2

Por mis necesidades freak me he visto necesitado de disponer de más recursos para poder montar mis entornos adecuadamente hasta que he llegado a la gran pregunta “On-premise o cloud”, pues la respuesta no ha sido sencilla ya que partía de la premisa que necesitaba un entorno que me permitiera disponer de distintas máquinas y que dispusiera de bastantes recursos como >12GB de RAM, un buen procesador y placa y varios discos rápidos. He estado varios días comparando distintos presupuestos de servidores físicos con la opción de utilizar las VM en modo Cloud.

Al final me he decantado por utilizar un proveedor Cloud ya que la inversión inicial es muy baja, rápida de adquirir y muy personalizable en cuanto a características.

Una vez decidido que me iba al cloud, tocaba decidir el proveedor. Lo primero que me vino a la cabeza fué utilizar el Rol de VM de Azure, pero tuve que descartarlo (muy a mi pesar) porque de momento solo puedes utilizar el servicio subiendo tus propias imágines y no puedes utilizar plantillas de VM prediseñadas, pensar que estar subiendo 25 GB cada cierto tiempo no me era factible. Después estuve barajando distintos proveedores que ofrecían templates hasta que al final me decidí por Amazon EC2 Elastic Compute Cloud. Los motivos fueron:

  • el coste por hora de los recursos era bastante competitivo.
  • distintas opciones de pago por consumo: en demanda, slots de precios, VM reservadas.
  • permite bastante flexibilidad en cuanto a la configuración de recursos.
  • dispone de templates de VM, entre ellos Windows 2008.
  • consola de configuración.
  • podemos crear nuestros propios snapshots (AIMS).
  • disponemos de un api de configuración y despliegue.
  • integración con una gran variedad de servicios adicionales: bbdd, balanceo, VPN, monitorización,…

image image

Lo primero que debes hacer es registrarte en Amazon Web Services (AWS) para conseguir un usuario, a continuación tendrás que logarte en la consola de AWS para subscribirte en los servicios que desees. La primera vez tendrás que crear un cliente que se asociará al usuario. Durante este registro habrá que introducir los datos de contacto, envío facturación y datos de pago. Esto es lo que más me ha impactado ya que para identificar a la persona te realizan una llamada al teléfono de contacto para que introduzcas un pin.

Como en mi caso he utilizado EC2, desde la consola AWS seleccioné la opción “Launch instance” para iniciar el asistente de creación de una nueva VM. Amazon te empieza a cobrar en el momento que inicias la instancia y la mantienes. La VM as por los siguientes estados:

  • stopped: apagada solo nos cobrarán por el espacio
  • running: está encendida, ya empieza contar el consumo de proceso por hora, las I/O a disco y red y consumo de resto de servicios. Aquí hay que tener en cuenta que nos van a cobrar una hora entera cada vez que arranquemos independientemente de si si es completa o no. Por lo que no os aconsejo encender y apagar. Ojo los reboot no cuentan.
  • terminatted: Indica que queremos que se borre la instancia, tarda bastante pero al final se elimina sola. Una vez terminada no se puede volver a encender así que cuidado…

Pero no todo es jauja’ al crear la primera instancia me encontré con el primer problemilla (de unas cuantas horas), una vez había creado la VM con éxito descubrí que tenía un límite de 30GB de disco y que encima no podía configurarlo desde la consola AWS :(  Al parecer aunque varias herramientas free tuve que recurrir a ejecutar una serie de scripts para crear de nuevo la VM pero esta vez con 200GB.

Primero te tienes que bajar las Amazon EC2 API tools que consisten en un conjunto de comandos hechos en java para configurar tus instancias, volúmenes y servicios. Una vez descargado y descargado y descomprimido tenemos que configurar las variables de entorno para que funcionen desde cmd:

 

SET EC2_HOME =c:\ec2-api-tools-1.3-62308

SET PATH =PATH; c:\ec2-api-tools-1.3-62308\bin

 

Para crear una instancia del tipo “Large” 7GB de RAM, con Windows 2008 y con 200GB de RAM ejecutamos:

ec2-run-instances --region eu-west-1 -K pk-xxxxxxxxxxxxxxxx.pem -C cert-xxxxxxxxxx.pem -b "/dev/sda1=:100:false" ami-c9517bbd --key key3 -g quick-start-1 -t m1.large --disable-api-termination stop -z eu-west-1a

 

donde ami-c9517bbd corresponde con el id de la AIM (imagen de la VM), key3 corresponde con un key pair, pk-xxxxxxxxxxxxxxxx.pem y cert-xxxxxxxxxxxxxxxx.pem corresponden con la private key y el certificado. Para obtenerlos teneis que acceder al menú superior Account > Credenciales de seguridad  > credenciales de acceso.

 

image image image

 

image image

Por último me gustaría concluir comentando las pegas que le veo al servicio:

  • no es nada intuitivo
  • no hay suficiente documentación o está dispersa
  • no tiene una consola con la que realizar todas las operaciones, al final te tienes que meter a ejecutar scripts
  • EC2 está basado en VMWare por lo que será muy difícil poder reaprovechar las VM para exportalas/importarlas algún día on-premise si vienes del mundo Microsoft.

 

Para conocer más sobre mis experiencias en cloud y SharePoint podéis seguirme en twitter @mariocortesf

Encontrar las páginas que hacen Crash!!

Aunque las buenas prácticas dicen que deberíamos de tener pruebas unitarias para validar que nuestro código tiene un comportamiento correcto durante todo el ciclo de vida del desarrollo, en el caso de SharePoint nos podemos encontrar con que puede que nuestros componentes estén correctamente pero haya otros elementos que impidan la ejecución provocando errores fatales. Si disponemos de Visual Studio 2010 Ultimate dispondremos de los WebTest con los que realizar una prueba sobre las páginas en un entorno de integración.

El problema nos puede venir porque no dispongamos de esta versión o porque no hayamos creado pruebas unitarias durante todo el proyecto. Para poder identificar al menos las páginas que están dando problemas al desplegar nuestras soluciones, podemos realizar peticiones GET a todas las páginas de nuestras colecciones de sitio y comprobar que no nos devuelva una excepción o la cabecera HTTP “SharePointError”. Esta cabecera se añade automáticamente en las repuestas a páginas que han generado un error no controlado.

 

Os dejo un pequeño ejemplo de código de como hacer este proceso, muy útil en migraciones ;)

 

static bool BuscarErrorAlCargarPagina(SPSite Site, List<string> ErroresEncontrados)
        {
            Console.WriteLine("BuscarErrorAlCargarPagina...");

            bool res = false;
            try
            {
                foreach (SPWeb web in Site.AllWebs)
                {
                    try
                    {
                            PublishingWeb pubWeb = PublishingWeb.GetPublishingWeb(web);
                            foreach (PublishingPage page in pubWeb.GetPublishingPages())
                            {
                                string url = string.Format("{0}/{1}", pubWeb.Url, page.Url);
                                try
                                {
                                    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
                                    req.PreAuthenticate = true;
                                    req.Credentials = CredentialCache.DefaultNetworkCredentials;

                                    byte[] result = null;
                                    byte[] buffer = new byte[4096];

                                    using (WebResponse resp = req.GetResponse())
                                    using (Stream responseStream = resp.GetResponseStream())
                                    using (MemoryStream memoryStream = new MemoryStream())
                                    {
                                        int count = 0;
                                        do
                                        {
                                            count = responseStream.Read(buffer, 0, buffer.Length);
                                            memoryStream.Write(buffer, 0, count);

                                        } while (count != 0);

                                        result = memoryStream.ToArray();

                                        if (result.Length < 1)
                                            ErroresEncontrados.Add(string.Format("Error al recibir datos de página {0}", page.Url));
                                        else if (resp.Headers["SharePointError"] != null)
                                        {
                                            ErroresEncontrados.Add(string.Format("Error al procesar página {0} correlation {1}", url, resp.Headers["SPRequestGuid"]));

                                        }
                                    }
                                }
                                catch (Exception ex)
                                {
                                    ErroresEncontrados.Add(string.Format("Error al cargar página {0}", url));
                                }
                            }
                    }
                    finally
                    {
                        web.Dispose();
                    }
                }
            }
            catch (Exception ex)
            {
                ErroresEncontrados.Add(string.Format("Error BuscarErrorAlCargarPagina: {0}", ex.Message));
            }
            return res;
        }

miércoles, 26 de enero de 2011

Material evento ALM en SharePoint 2010 con TFS 2010

El 12 de enero pude realizar junto con Roberto González el evento ALM con TFS 2010 y SharePoint 2010 donde pudimos ver aspectos de ALM aplicados al desarrollo de soluciones para SharePoint 2010 apoyándonos de Team Foundation Server 2010.
En el post de Roberto Pruebas Unitarias SharePoint 2010 y Moles podréis encontrar parte del material de este evento junto con más información sobre ALM y una serie de ejemplos de moles para SharePoint.

También os dejo la otra parte del material del evento más orientada al diseño de soluciones y trabajo diario con SharePoint 2010 y TFS 2010.

 

Presentación ALM para SharePoint 2010

Material de trabajo ALM

Pruebas Unitarias SharePoint 2010 y Moles (Roberto González)

viernes, 21 de enero de 2011

Página para encontrar empresas de hosting

A raíz de una pregunta de Alberto Díaz me he encontrado con el sitio web de Microsoft “Find Web Hosting” desde el que podemos encontrar una lista de proveedores de hosting sobre la que podemos realizar distintos tipos de filtro como encontrar por paises, computación, almacenamiento, tecnología,…

Incluso he podido encontrar distintos proveedores de SharePoint que no conocía quitando el filtro por país e insertando la palabra clave “Sharepoint”  ;)

 

imageimage