lunes, 3 de septiembre de 2012

Configurando un SharePoint 2010 en Windows 2012 Server

En el artículo anterior sobre Instalar un SharePoint 2010 en un Windows 2012 Server había resuelto las incidencias para conseguir instalar correctamente la aplicación.

Pero cuando lanzo el configurador, después de haber instalado los añadido de Sharepoint del Visual Studio 2012 y de la SQL 2012 Server, me da problemas.

La solución, como siempre, son varias actuaciones.

* Entrar en el IIS y poner todos los Pool de aplicaciones relacionadas con SharePoint a la versión 2.x de .NET, ya que no funciona en 4.0.

* Visitar este blog: http://sharepoint.nauplius.net/2012/06/installing-sharepoint-2010-and-sql.html en donde nos enseña como modificar el PowerShell de SharePoint para que use la versión 2.0 y no la 3.0 que es la que viene con el WS2012 y con la que no funciona bien.

* Correr este PowerShell con privilegios de administración:

Set-WebConfigurationProperty “/system.applicationHost/applicationPools/applicationPoolDefaults” –Name managedRuntimeVersion –Value “v2.0” –PSPath IIS:\
Que lo que hace es decirle al IIS que por defecto haga el default app correr en versión 2.0 del Framework.
Y lanzando de nuevo el configurador de SharePoint, todo finalizó correctamente.
Espero que sea de utilidad

Instalar un SharePoint 2010 en un Windows 2012 Server

Como todo en IT, no hay nada fácil y sencillo. Y la instalación de un SharePoint 2010 para desarrollo en un novísimo Windows 2012 server no iba a ser diferente.

Básicamente los pasos que realice fueron (todo en inglés):

* Instalar el Windows 2012 Server

* Instalar el SQL Server 2012 con todo menos las extensiones de SharePoint y el PowerPivot.^

* Lanzar el instalador de SharePoint 2012, para que me pidiera los prerequisitos, que fui descargando e instalando.

* Modificar los Roles del Servidor, como indica en el primer blog.

* Insertar en Windows/System32 el fichero ServerManagerCmd.exe que me bajé de la segunda dirección y que no hace nada más que devolver un código.

El sitio en donde mejor se describe la forma de instalar los prerequisitos

http://bifase.blogspot.com.es/2012/03/windows-8-server-y-sharepoint-2010.html

y  aquí el fichero de Steve, que refiere en el blog anterior. OJO un fichero ServerManagerCmd que es el que me volvió loco y que , hasta que no lo puse en System32 finálmente, no funcionaba el instalador de SP2010.

http://blog.hand-net.com/sharepoint/2010-06-10-error-lors-de-linstallation-des-office-web-apps-2010-sur-windows-7.htm

Este es el sitio de Microsoft en donde se pueden descargar todos los pre requisitos uno a uno.

http://technet.microsoft.com/library/cc262485(office.14).aspx#section4

Ale, número de serie de SharePoint 2012 y empezar la instalación Stand Alone para desarrollo.

Espero que sea útil para alguien más, a mi me ha costado una mañana.

martes, 28 de agosto de 2012

Reference in the manifest does not match, o la guerra de los manifiestos

En los últimos coletazos de un EXCELENTE AddIn para Excel que hemos desarrollado en mi empresa (TeamPRO), nos hemos puesto a hacer las pruebas de la última versión del código ya con el código publicado y listo para realizar instalaciones.

Y nos ha salido esto:

image

La madre del cordero!!

Después de googlear como locos empezamos a entender lo que ha ocurrido. Para realizar el pintado de los mapas hemos utilizado un proyecto open source (y gratis) llamado CustomColorPicker, el cual hemos añadido a la solución y que compilábamos y hacíamos referencia desde el proyecto en sí del AddIn.

image

Cual es el problema, que el proyecto CustomColorPicker es un proyecto WPF de Windows, y lo que se referencia es un exe. Bueno realmente un exe.deploy. Y este ejecutable tiene un manifiesto que se pega con el manifiesto del AddIn.

¿Cual es la solución? Simple como la vida misma: quítale el manifiesto a CustomColorPicker, o en tu caso a la aplicación que es referenciada por la principal.

¿Cómo se hace eso? Pues mira las pantallitas y te quedará claro.

Primero saca el menú contextual del proyecto al que le quieres quitar el manifiesto con el botón derecho.

image

Así se abrirá la configuración de la aplicación en donde encontramos la configuración que hay que cambiar y que señalo con una flecha y que es “Crear la aplicación sin manifiesto”.

image

Y con esto, compila, publica e instala. Que el mensaje de error por los manifiestos deja de producirse.

Espero que sea de utilidad.

viernes, 24 de agosto de 2012

Mover un Canvas dentro de un Canvas en WPF

Una de las cosas que más agobian es las pequeñas diferencias que hay en los lenguajes de programación de .NET. Y agobian porque las cosas más sencillas no están prácticamente en ningún sitio porque todo el mundo lo da por más que sabido.

Y es una de las razones principales de este blog. Compartir conocimientos de nivel 100 (iniciación).

Así me encuentro, en el proyecto este del Addin para Excel, que tengo la pantalla compuesta por diferentes capas en donde tengo, construidas sobre controles Canvas, los polígonos, los nombres y los diferentes valores.

Algo así, para que se entienda mejor:

   1: <Canvas x:Name="Canvas">
   2:     <Path Name="a114" Fill="#FFC2C2D8" />
   3:     <Path Name="a118" Fill="#FFC2C2D8 />
   4:     <Canvas Name="Valores">
   5:         <TextBlock Canvas.Left="683" Canvas.Top="303" Height="37" Name="t112" />
   6:     </Canvas>
   7:     <Canvas Name="Nombres">
   8:         <TextBlock Canvas.Left="683" Canvas.Top="303" Height="37" Name="t112" />
   9:     </Canvas>
  10: </Canvas>


Tengo un control “Canvas” general sobre el que pinto los polígonos del tipo Path, y añado dos capas más “Valores” y “Nombres” sobre las que pinto textos dentro de controles TextBlock. Viéndose algo tanto que así:


image


Se podría hacer dos mil preguntas de porqué se tomo la decisión técnica de hacer las cosas así, pero eso lo cubriré con un tupido velo.


El problema que quiero solucionar, es que puedo ocultar las cifras del valor que aparecen debajo del nombre y que entonces necesito que el nombre descienda unos 25 pixeles para que quede más centrado verticalmente, ocupando el sitio que ocupa el valor.


Después de darle mil vueltas, y gracias a @pablonete, encontré la forma de hacerlo y que es la mar de sencillo con un método del control del tipo Canvas.



   1: Canvas.SetTop(canvasNombres, 0);

Es decir, Al tipo Canvas le invoco el método SetTop que lo que hace es mover el control tipo Canvas “canvasNombres”  25 pixeles hacia abajo desde su Canvas contenedor. Que ya se encarga el solito de buscarlo.


El quid del asunto aquí es cómo recuperar el Canvas “canvasNombre”. Y que, para darte una pista, es un Child del Canvas principal “Canvas”.


Espero que sea de utilidad.

miércoles, 22 de agosto de 2012

Pintando un gráfico de tartas en un ImageBitMap

 

La verdad que esto del desarrollo sigue siendo muy interesante, aún en mi actual faceta de responsable de departamento y, por ende, con labores más de gestión que de picar código.

Le estoy echando una mano a un equipo que está desarrollando un Addin para Excel, y así pruebo qué tal va el VS2012 RTM, que ha mejorado bastante al ya de por sí bueno VS2012 RC.

Me encuentro que el programador anterior (que el demonio lo tenga en la más miserable celda posible en el infierno) debía tener conocimientos más bien cortitos y, para pintar un indicador que mostrara el porcentaje de un valor, no se le ocurrió otra cosa que hacer un bitmap por cada 10 grados de una imagen de una gráfica de tarta y, con cientos de líneas de código, montar un “chocho” impresionante para saber cual utilizar según el porcentaje.

En cuanto lo vi, me di cuenta que con un poquito de GDI+ lo tenia solucionado. Y así fue, casi mil líneas de código convertidas en los siguientes métodos:

   1: Using System.Drawing;
   2:  
   3: private Image PintarEnImageBitmap(Image imageIndicador, double valorPorcentual)
   4: {
   5:     // Aquí indico que voy a crear un nuevo Bitmap de 50x50px y con un formato ARGB de 32bpp
   6:     Bitmap dibujoDelValor = new Bitmap(50,50,System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
   7:     
   8:     // A continuación creo un nuevo objeto Graphics (sobre el que voy a pintar) a partir del Bitmap anterior
   9:     Graphics graficoDelValor = Graphics.FromImage(dibujoDelValor);
  10:     
  11:     // Declaro el pincel con el que voy a pintar la circunferencia que va a rodear la gráfica de tartaa
  12:     // incluyendo el color y el ancho del pincel        
  13:     System.Drawing.Pen pluma = new System.Drawing.Pen(System.Drawing.Color.White,2);
  14:     
  15:     // Declaro la brocha con la que voy a rellenar la gráfica de tarta
  16:     System.Drawing.SolidBrush brocha = new System.Drawing.SolidBrush(System.Drawing.Color.White);
  17:             
  18:     // Limpio el gráfico con el color negro. Ojo, en Excel el transparente no vá bien.
  19:     graficoDelValor.Clear(System.Drawing.Color.Black);
  20:  
  21:     // Le indico el grado de aliasing que quiero utilizar al dibujar
  22:     graficoDelValor.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
  23:     
  24:     // Pinto la circunferencia que rodea a la gráfica de tarta
  25:     graficoDelValor.DrawEllipse(pluma, 0, 0, 47, 47);
  26:  
  27:     // Pinto la gráfica de tarta. Invoco a un método que me transforma el valorPorcentual a grados.
  28:     // 270 es para que empiece a pintar desde una linea vertical. Ya que 0 es la horizontal derecha.
  29:     graficoDelValor.FillPie(brocha, 0, 0, 47, 47, 270, PorcentajeAGrados(valorPorcentual));
  30:  
  31:     // Cargo el Bitmap resultante en un objeto Image
  32:     imageIndicador.Source = BitmapToSourceImage(dibujoDelValor);
  33:  
  34:     Return imageIndicador;
  35: }

El método PorcentajeAGrados, no puede ser más sencillo:



   1: private int PorcentajeAGrados(double valorPorcentual)
   2: {
   3:     return (int)(valorPorcentual * 3.6);
   4: }

Y el “truco del almendruco” es pasar el Bitmap GDI+ a un tipo ImageSource, que es el que puede leer los ImageBitmap de DirectX (y que por alguna extraña causa, el programador anterior prefirió utilizar en vez de los Bitmap GDI+).


Para ello, copio y pego el código que me he encontrando googleando, y que como no me lo he apuntado no lo puedo referenciar como debería hacer.



   1: /// <summary>
   2: /// Dado un objeto Bitmap lo convierte en un objeto ImageSource
   3: /// </summary>
   4: /// <param name="dibujoDelValor"></param>
   5: /// <returns></returns>
   6: private System.Windows.Media.ImageSource BitmapToSourceImage(System.Drawing.Bitmap dibujoDelValor)
   7: {
   8:     System.IO.MemoryStream ms = new System.IO.MemoryStream();
   9:     dibujoDelValor.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
  10:     System.Windows.Media.Imaging.BitmapImage bImg = new System.Windows.Media.Imaging.BitmapImage();
  11:     bImg.BeginInit();
  12:     bImg.StreamSource = new System.IO.MemoryStream(ms.ToArray());
  13:     bImg.EndInit();
  14:  
  15:     return bImg;
  16: }

Por lo cual, y resumiendo. Una llamada de ejemplo sería:



   1: Image imagenIndicador = new Image();
   2: imagenIndicador = PintarEnImageBitmap(imagenIndicador, 73);

Y el resultado, en el caso de la aplicación que estamos realizando es algo así:


image


Según me ha comentado Rodrigo, debería de investigar el no tener que hacer lo que estoy haciendo que es pintar en GDI+ y después utilizar objetos de DirectX, si no que debería pintar directamente con la propia API de Excel… pero eso es para nota.






Espero que sea de utilidad.

viernes, 27 de julio de 2012

Workbook.Worksheets.Delete y la madre que parió a la alerta de borrado

Estoy trabajando en un AddIn para Excel, utilizando las famosas VSTO (Interop) de Offcie desde Visual Studio 2012.

Pulsando en un botón del Ribbon, que hemos definido, debía localizar una hoja del libro específica y borrarla. el problema es que por defecto esta acción Delete(), lanza un ventana de dialogo que te pide una confirmación  de si quieres borrar esa hoja.

El problema viene de que cuando pulso cancelar, no he encontrado la forma de capturar cual de los botones ha pulsado antes de que realice el borrado… y tres métodos más allá rompía la aplicación por no encontrar una hoja que se suponía que aún existía.

Googleando me he encontrado con una solución bruta y basta, pero que me ha valido. Y no es más que deshabilitar las ventanas de alerta y que borre de forma directa.

   1: /// <summary>
   2:         /// Dado el nombre de la hoja Excel, la busca y la borra
   3:         /// </summary>
   4:         /// <param name="name"></param>
   5:         /// <returns></returns>
   6:         private bool borraHoja(string name)
   7:         {
   8:  
   9:             Boolean seHaBorradoLaHojaExcel = false;
  10:  
  11:             var addInExcel = Globals.ThisAddIn.Application;
  12:             addInExcel.DisplayAlerts = false;
  13:             Worksheet HojaASerBorrada = (from Worksheet hojaExcel in addInExcel.ActiveWorkbook.Worksheets
  14:                                          where hojaExcel.Name == name
  15:                                          select hojaExcel).FirstOrDefault();
  16:  
  17:             if (HojaASerBorrada != null)
  18:             {
  19:                 HojaASerBorrada.Delete();
  20:                 seHaBorradoLaHojaExcel = true;
  21:             }
  22:  
  23:             addInExcel.DisplayAlerts = true;
  24:             return seHaBorradoLaHojaExcel;
  25:         }

 



En mi caso me ha valido porque es el comportamiento esperado, pero creo que merece un estudio en más profundidad para ver como capturar el botón que ha pulsado el usuario.


Que os sea de utilidad

jueves, 28 de junio de 2012

Detectar MouseEnter en la capa inferior de un gráfico

Buenas,

Hoy estaba un compañero bloqueado con un problema un tanto peliagudo.

Estamos desarrollando una Addin para Excel, en donde construimos un mapa de España dividido por provincias, y encima de cada uno de los polígonos se añaden TextBox con el nombre, un valor y dos imágenes que son unos indicadores de otros valores.


El problema venía que cuando te pones encima del objeto o los valores, debe salir un Tooltip con datos. Y el programador anterior (Dios lo tenga en el infierno) no se le ocurrió otro modo de conseguir verlo cuando nos situamos encima del texto o el número o los indicadores que añadiendo tooltip a cada uno con la misma información. Es decir, por cada polígono llenaba de información el tooltip de cuatro controles más.

Entonces, necesitaba eliminar los tooltip de más y decir de alguna forma, a la aplicación, que no controlara si el ratón se ponía encima de cualquier cosa que no fuera el polígono base.

¿Y cómo hago eso?

Lo intenté preguntandole al sender del evento OnMouseEnter a ver si me traía una colección de los objetos sobre el que estaba situado el ratón. También se lo pregunté al MouseButtonEventArgs. Y por este camino yo llegue a ningún lado.

Asi que, en un momento de inspiración me puse a mirar los métodos y propiedades de los controles y me encontré con la solución:

Control.IsHitTestVisible = false

Esto hace que el objeto sea transparente para los eventos lanzados por el ratón. Lo cual produce que para el ratón solamente exista el polígono de fondo. En el ejemplo que he traído esto lo conseguí con:


imageIndicador1.IsHitTestVisible = false;
imageIndicador2.IsHitTestVisible = false;
valor1.IsHitTestVisible = false;
nombre.IsHitTestVisible = false;
path.IsHitTestVisible = true;


Espero que os sea útil.