viernes, 30 de marzo de 2012

Outlook y el misterio de la carpeta perdida

Hoy toca un off-topic, ya que esta semana he tenido un problema con el correo electrónico, que al ser tan, por denominarlo de alguna manera, ‘curioso’ no he podido evitar dejarlo reflejado por si me vuelve a pasar.

Situación inicial

Normalmente tengo siempre el cliente de correo (en mi caso Outlook 2010) abierto, y siempre en la Bandeja de Entrada.
En un momento dado, al volver del calendario a los correos, no pude hacerlo con los accesos directos de la parte inferior (operación que realizo habitualmente) en lugar de abrir la Bandeja de Entrada, me aparecía debajo del calendario las carpetas del buzón:
image
Primer pensamiento: “He hecho algo raro” así que le doy al botón de “volver atrás” del ratón, y vuelvo a la Bandeja de Entrada.
En otro momento dado, voy a una de las carpetas de RSS que tengo configuradas, y al ir a volver a la Bandeja de Entrada, de repente no está (se puede ver en la captura anterior, donde ya tampoco no aparecía, aunque en ese primer momento no me fijé)
Como podéis imaginar, tras unos ‘pocos’ juramentos y expresiones ofensivas, me tranquilicé un poco al ver que los correos seguían entrando y que lo ‘único’ que había pasado (que no es poco) es que no tenía un enlace a la propia carpeta de la Bandeja de Entrada.

En busca de la solución

A la hora de buscar una solución el tema era complicado, ya que ‘conscientemente’ no había realizado ninguna operación con Outlook distinta de las que puedo realizar cualquier día, e incluso no estaba seguro de cuándo había desaparecido la dichosa carpetita.
Lo primero, copia de seguridad de todo el buzón, y, sobre todo de los contactos y el calendario.
Lo segundo, San Google.
Gracias a este santo, llego a una descarga en Codeplex que permite acceder a las ‘tripas’ de almacenes MAPI, así que a descargar y a ver si internamente está todo en orden.
La herramienta es “MFCMAPI” y este es el acceso.
Ojo porque la versión a ejecutar (32 o 64 bits) depende de la versión de Outlook (bueno, o del sistema, no estoy seguro, porque yo tengo ambos en 64 bits)

Al turrón

Ejecutamos la aplicación (no voy a hacer comentarios acerca de la apariencia…)
image
0.- Cerramos el Outlook.
1.- Hacemos clic en el menú “Session” y a continuación en “Logon…”
2.- Elegimos el perfil de correo que queremos revisar.
image
En la ventana de la aplicación se cargarán todos los almacenes que tengamos configurados.
3.- Elegimos el correspondiente al buzón que está dando problemas (ante la duda, posiblemente sea el que está marcado como almacén por defecto)
image
4.- Con el botón derecho del ratón, hacemos clic sobre el y elegimos “Open Store”. Se abrirá una nueva ventana con un estructura de árbol que contiene todo nuestro buzón:
image
5.- La carpeta que nos interesa el la “IPM_SUBTREE” así que la desplegamos. Esta carpeta muestra todo el contenido de nuestra estructura en el Outlook:
image
En mi caso al menos, suspiro de alivio: La carpeta “Bandeja de Entrada” aparece ahí, la primera, no ha huido de mí.
6.- Seleccionamos la carpeta Y revisamos las propiedades (y sus valores) que se cargan en la parte derecha de la ventana. A pesar de que la mayoría de elementos no me suenan de nada, hay uno que llama la atención, tanto por el nombre en sí como por el valor que tiene asignado:
image
Entiendo que no hace falta, pero por si acaso, la propiedad que me llama la atención es la que aparece resaltada “PR_ATTR_HIDDEN” con un valor de “True”.
¿Será casualidad que una propiedad de mi carpeta desaparecida que se llama “HIDDEN” esté a True? Vamos a probar (recuerdo que tengo por si acaso una copia de seguridad de todo… o de casi todo)
7.- Hacemos doble clic en la propiedad, y en la ventana que aparece, establecemos el valor de la misma a “False”:
image
8.- Confirmamos con “OK” y al volver a la pantalla anterior, vemos que el valor ha cambiado (en este punto, sólo por asegurarme, reinicié el programa y volví a navegar hasta esa pantalla sólo para ver si el valor se había reseteado, pero seguía correcto, a False)
9.- Cerramos la aplicación, cruzamos los dedos y lanzamos el Outlook y…
¡¡SOLUCIONADO!! Ya tengo de nuevo la carpeta de la Bandeja de Entrada y todo vuelve a la normalidad.

¿Alguna explicación?

Yo desde luego no la tengo, pero por lo menos he conseguido ‘apañarlo’ sin perder nada.

viernes, 23 de marzo de 2012

TFS Builds, error con “Tracker.exe”

Una rápida para terminar la semana…

Situación inicial

Tras instalar un nuevo servidor de compilación, la primera Build configurada para un proyecto de tipo Windows Forms, falla con el siguiente mensaje:

image

 

Posibles soluciones

Como indica el propio mensaje, hay varias soluciones posibles:

  1. Instalar el Windows SDK v7.0A o superior.
  2. Instalar Visual Studio 2010.
  3. Establecer ‘a mano’ una propiedad en el registro de Windows.
  4. Desactivar la operación que desencadena el error en la compilación.

La primera opción entiendo que es la mejor y la que aplicaré en el servidor de compilación, pero no quería tener que hacerlo hoy.

Las segunda y tercera opciones, pues cómo decirlo, no me convencen. No quiero tener que instalar Visual Studio 2010 en un servidor de CI, y por supuesto que NO quiero tampoco andar jugueteando con el registro (si no es estrictamente necesario)

La cuarta opción es la que he aplicado de manera temporal y la verdad es que funciona perfectamente.

Desactivar la generación de recursos incremental

En el mensaje lo pone muy fácil:

You can turn off incremental resource generation by setting the "TrackFileAccess" property to "false"

Investigando por Internet, he visto que es un parámetro que se le puede indicar al “MSBUILD”, e incluso que se puede añadir en la definición XML de la compilación.

Lo que no tenía tan claro era cómo aplicar ese parámetro a la definición de la compilación desde el propio Visual Studio, y al final ha sido sencillo, basta con introducir el parámetro en la definición de la compilación, como aparece en la siguiente captura:

image

Ojo porque hay que añadir la marca de parámetro, quedando así:

/p:TrackFileAccess=false

Una nota curiosa, otras compilaciones configuradas en el servidor funcionaban correctamente, pero ninguna utilizaba archivos de recursos…

Y ya está solucionado, ahora que no se me olvide instalar el dichoso SDK.

martes, 20 de marzo de 2012

Impedir Cortar / Pegar en un ComboBox

Los controles ComboBox no disponen de una propiedad ReadOnly, únicamente podemos ‘jugar’ con la propiedad Enabled.

Sin embargo, en ocasiones no es suficiente con la propiedad Enabled, sino que necesitamos, por ejemplo, que se pueda seleccionar el texto del control. Para conseguir esto es relativamente sencillo generar una propiedad ReadOnly que lo que haga sea modificar el estilo del ComboBox a “ComboBoxStyle.Simple”. Peeero, no es esa parte la que nos interesa, sino que lo que vamos a explicar es cómo impedir que se pueda utilizar el ratón para ‘Cortar’ y/o ‘Pegar’ el contenido del control.

Al turrón

Lo primero que hacemos es generar una clase que herede de “NativeWindow”, en la que sobrescribiremos el método “WndProc” que se invoca cada vez que se lanza un mensaje al handle de la ventana.

El código de la clase aparece a continuación.

 

    /// <summary>
    /// Esta clase se utiliza para evitar las operaciones de Cortar / Pegar en los combos deshabilitados.
    /// </summary>
    public class DisallowCutPaste : NativeWindow
    {
        #region
Constantes
        private const int WM_CUT = 0x0300;
       
private const int WM_PASTE
= 0x0302;

        #endregion
Constantes

        #region
Overrides
        
/// <summary>
        /// Sobrecarga del método <see cref="WndProc"/> para evitar operaciones de cortar / pegar.
        /// </summary>
        /// <param name="m">
        /// El <see cref="Message"/> recibido por el objeto.
        /// </param>
        protected override void WndProc(ref Message m
)
        {
           
if (m.Msg == WM_CUT || m.Msg == WM_PASTE
)
            {
               
return
;
            }

           
base.WndProc(ref m
);
        }

        #endregion

    }

Una vez generada la clase, la aplicamos al control que queremos manipular (en este caso un ComboBox personalizado)


Para esto, en el código del control referenciamos la siguiente función del API:


 

        [DllImport("user32.dll", SetLastError = true)]
       
private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter
,
           
string lpszClass, string lpszWindow
);

Ya sólo queda aplicar todos los elementos para que todo funcione, como podemos ver en este fragmento de código:


 

    IntPtr handle = FindWindowEx(this.Handle, IntPtr.Zero, "EDIT", null);
   
DisallowCutPaste p = new DisallowCutPaste
();
   
p.AssignHandle(handle
);

Una vez hecho esto, ya podremos comprobar que aunque en el combo tengamos disponible las opciones de ‘Cortar’ y ‘Pegar’ con el botón derecho del ratón, cuando el código anterior se ejecuta, al utilizar esas opciones, no sucede… NADA.


Nota


Hay que decir que estas instrucciones es recomendable ejecutarlas solamente cuándo sea necesario, por ejemplo en el “Set” de una propiedad, de forma que para desactivarlo sólo hace falta no ejecutar el código en el mismo “Set” de la propiedad (por ejemplo en un bloque ‘If’) el siguiente fragmento de código explica un poco mejor esta observación:

        public bool ReadOnly
        {
           
get
            {
               
return this._readOnly
;
            }
           
set
            {
               
if (value
)
                {
                   
IntPtr handle = FindWindowEx(this.Handle, IntPtr.Zero, "EDIT", null
);
                   
DisallowCutPaste p = new DisallowCutPaste
();
                   
p.AssignHandle(handle
);
                }
               
this._readOnly = value
;
            }
        }

Y esto es todo.