Trabajando con el registro de Windows desde C# y .NET

Manejar el registro de Windows es algo… en parte tedioso por lo extenso y medianamente documentado que esta lo que contiene. En mi humilde opinión, es algo a evitar siempre que sea posible en virtud de los archivos de configuración; pero en ocasiones necesitamos crear/modificar entradas que afectan al funcionamiento de otros programas ó del propio Windows desde nuestras aplicaciones, asi que hay que arremangarse y meterle mano 😀

Primero un pequeño repaso de como se estructura la información a grandes rasgos. Podemos ver el registro mediante la aplicación regedit.exe. Encontramos 5 elementos principales, que así por encima vienen a ser:

  • HKEY_CLASSES_ROOT (HKCR) : Contiene las realciones entre los identificadores de programa y clases que se usan por COM+, asociaciones de archivo e información de ejecución de aplicaciones.
  • HKEY_USERS (HKU) : Contiene un elemento por cada usuario del sistema y en cada uno se almacenan sus preferencias y configuraciones individuales.
  • HKEY_CURRENT_USER (HKCU) : Es como un enlace simbólico a la entrada en HKU correspondiente al usuario actual.
  • HKEY_LOCAL_MACHINE (HKLM) : Información del sistema y del hardware.
  • HKEY_CURRENT_CONFIG (HKCC) : Es como un enlace simbólico a la entrada en HKLM correspondiente a la configuración hardware actual.

La información esta estructurada en forma de arbol mediante claves y valores. Las claves son como carpetas que puede contener otras claves, y los valores son una pareja key-value donde podemos asignar un valor. Los valores pueden ser de tipo:

  • REG_DWORD : Número de 4 bytes, se usa para almacenar valores boleanos.
  • REG_BINARY : Almacena datos binarios.
  • REG_SZ : Cadena de texto.
  • REG_MULTI_SZ : Almacena arrays de strings.
  • REG_EXPAND_SZ : Almacena una variable en formato de string.

Ahora vamos a meterle mano, lo primero que necesitamos es el namespace Microsoft.Win32 , y nuestras clases para trabajar serán RegistryRegistryKey. Lo primero, es llegar donde vamos a trabajar:

 

// Abrimos la clave del registro con la que queremos trabajar
RegistryKey rk1 = Registry.LocalMachine;
 

Trabajando con claves:

// Nos movemos hasta la subclave donde queremos trabajar.
// El parámetro boleano indica si la abrimos en solo lectura (false)
// ó en lectura/escritura (true).
rk1 = rk1.OpenSubKey(@"SOFTWAREMicrosoftWindows NTCurrentVersionWinlogon",true);
 
// Si devuelve null es que la clave no existe
if (rk1 == null)
    Console.WriteLine("No existe esa clave");
 
// Crear una nueva clave
// El método devuelve un RegistryKey apuntando
// a la nueva entrada.
RegistryKey rk2 = rk1.CreateSubKey("Prueba");
 
// Obtener todas las subclaves contenidas en esta:
String[] subKeys = rk1.GetSubKeyNames();
 
// Borrar una clave vacia:
rk.DeleteSubKey("Prueba");
                
// Borrar una clave recursivamente:
rk.DeleteSubKeyTree("Prueba");
 

Trabajando con key-values:

// Crea un key-value indicando su nombre, valor y tipo:
rk2.SetValue("ValorPrueba", 0,RegistryValueKind.String);
 
// Obtener todos los nombres de key-values que hay en una clave:
String[] values = rk2.GetValueNames();
 
// Obtener el valor de un key-value:
Console.WriteLine(rk2.GetValueKind("ValorPrueba").ToString());
 
// Obtener el tipo de dato de registro 
// que contiene un key-value:
RegistryValueKind rvk = rk2.GetValueKind("ValorPrueba");
 
// Borrar un key-value:
// El parámetro boleano indica que salte una excepción
// si el key-value a borrar no existe.

rk2.DeleteValue("ValorPrueba", true);

 

Aunque los Setup Project que creamos con Visual Studio tiene capacidad para añadir claves y key-values al registro, su funcionalidad esta muy limitada, por ejemplo… no podriamos crear un key-value que contuviese el path de la aplicación que estemos instalando a no ser que lo pusieramos harcodeado.

 

Trabajando con el registro de Windows desde C# y .NET | vtortola.NET

Evento: Windows Communication Foundation al Descubierto en SNUG

El próximo 1 de Abril podréis asistir a un nuevo Webcast en el que podréis sacar el máximo provecho de sistemas, tanto nuevos como ya existentes, a través de Windows Communication Foundation. Para esta nueva charla, contaremos con la presencia de Hadi Hariri como ponente de excepción, que nos deleitará con todo lo que esta nueva herramienta nos puede ofrecer.

El evento será a las 19:30 – 21:30 (GMT+1), y como en las anteriores ocasiones, se retransmitirá vía Web a través de Live Meeting.

  • Si no tienes Live Meeting, puedes descargarlo en el siguiente enlace.
  • Podéis registraros en el evento en el siguiente enlace.

Yo para variar, me lo perderé en directo porque será mi segundo día en Dublin y tengo clase hasta las 19:00, pero lo bueno de estos eventos es poderlos ver a posteriori en diferido 😀 y este en concreto me interesa muchísimo.

Menealó

Evento: Windows Communication Foundation al Descubierto en SNUG | vtortola.NET

Chatarra a precio de oro III, Microsoft es asi

Y no se confundan, Microsoft nada pinta aquí… al menos para mi, pero si para el SAT 😀  Sigo con mi lucha con la chatarra (parte I, parte II), alcanzado ahora nuevas cotas de asombro con el SAT. Una de mis reglas cuando hablo con el SAT, es ser tan humilde como pueda, prestar atención a lo que dice y evitar dar a entender que soy un usuario avanzado, en este caso… mucho menos decir que soy programador.

Una vez instalada la aplicación en red, la primera cosa que se me ocurre (yo y mis ocurrencias…), es lanzar el cliente como usuario Invitado … a lo que recibo un error de que no puede escribir a un archivo que el programa de instalación ha dejado caer en C: … nada más y nada menos, no se me ocurre otra cosa que llamar al SAT (más ocurrencias bobas…) para preguntar como ejecutar la aplicación con una cuenta desprivilegiada para que nadie pueda cargarse la máquina… la respuesta… increible:

«… es así y la aplicación necesita que se ejecute como administrador, es un requerimiento de Microsoft… es lo que hay…»  [ … ] «… vamos… deberia ser un usuario malintencionado…»

Aún estoy recuperandome del sock. Bien, pues siguiendo los consejos de Josue en Geeks.ms y mi colega Joe_Dalton de BandaAncha.st me lanzo a crear una Windows shell para contener al usuario en una interfaz de la que no puedan ejecutar nada, además deshabilito el Task Manager, ahora parece que todo irá bien y no hay posibilidad de catástrofe ya que los ordenadores no tienen teclado tampoco.

Comienzan los problemas de verdad, sin saber porque … se cuelga «algo» en el servidor. Los clientes siguen funcionando, es decir… siguen accediendo a la bd en forma de archivos que hay en el recurso compartido y trabajando normalmente, pero en el servidor es imposible abrir el módulo de gestión ni abrir la aplicación cliente, obtengo errores de timeout y procesos colgados indefinidadmente, tampoco funciona el BDE Administrator del panel de control, nos vemos obligados a reiniciar la máquina… y vuelve a funcionar. Llamo al SAT (iluso yo) … simplemente para preguntar como solventar el problema sin reiniciar la máquina, ya que eso supone que los clientes pierdan el trabajo no guardado ó hacerles que terminen, paren, reiniciar y volver a abrir de nuevo… con la mala imagen que da eso, es decir… que me diga algún servicio de Borland que reniciar … no sé… algo xD, la respuesta tan asombrosa ó más como la anterior:

«… Microsoft no proveé de ninguna herramienta para hacer eso, es lo mismo que si se te cuelga alguna aplicación y tienes que reiniciar, no se puede hacer nada, Microsoft es así…»

Intentando recuperar la respiración, me reincorporo, me sacudo el polvo de la ropa después de haber rodado varias veces por el suelo y vuelvo a sentarme en la silla de nuevo, minutos después me llaman de la sala diciendo que hay un equipo que «no va». Me acerco y un mensaje alerta algo como «Cannot set focus on a unexistent window», doy a aceptar y la pantalla se queda sin datos… y sin que funcione ningún botón, toca matarla y reiniciarla. Llamo al SAT de nuevo … «hola, soy el de antes», la respuesta… ya para llorar:

«… eso es porque el usuario va muy rápido, cuando se inicia el test sale una ventana de bienvenida y hay que darle a aceptar, si se pulsa sobre la ventana de fondo sin darle a aceptar… pasa eso…, la ventana esa se puso para ese fin, que terminase de cargar la otra… si le das antes … pues normal que se quede asi…»

En fin… Ahora mismo, mientras escribo esto estaba esperando a que el SAT me coja de nuevo el teléfono porque hay otro cliente que se ha quedado … literalmente congelado, ni el cronómetro que hay en una de las esquinas corre… pero justo ahora mismo, después de 5min congelado ha saltado el error : «Lock time out, table xxx.db» …

¿Alguien tiene idea de que se puede hacer? Han transcurrido los 15 días de prueba ya… con lo que no creo que se pueda devolver… pero una cosa es que no te guste, otra cosa es … ESTO.  Este post se va a hacer interminable xD, ahora mismo estoy sacando un captura de pantalla de un volcado de datos (ó eso parece) sobre el formulario después de otro error de «Lock time out». No sé si reir ó llorar…

Locktimeoutyvolcado

Aquí queda el testimonio de mi indignación e impotencia 🙁

 

Chatarra a precio de oro III, Microsoft es asi | vtortola.NET

Forzando la captura de excepciones no manejadas en WPF

En .NET 2.0 y WinForms había una forma que ahora ya no es del todo válida en WPF ya que han desaparecido el método Application.SetUnhandledExceptionMode y el evento Application.ThreadException, en su lugar tenemos Application.DispatcherUnhandledException:

<Application x:Class="KiosimWPF.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml" 
    DispatcherUnhandledException="App_DispatcherUnhandledException">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Luego en el handler del evento podemos evitar que la excepción tumbe la aplicación:

void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
    // Proceso la excepción:
    Trace.Write(String.Format("({0}):{1}nn{2}",e.Exception.GetType().Name,
                                            e.Exception.Message,
                                            e.Exception.StackTrace));
 
    // Evito que la excepción siga subiendo y tumbe
    // la aplicación marcándola como manejada:
    e.Handled = true;
}

Más info: Información general sobre la administración de aplicaciones (WPF).

Forzando la captura de excepciones no manejadas en WPF| vtortola.NET

Cursos gratis en Microsoft Learning

Gracias a la lista de SNUG y a Toni Recio, me entero que hasta el 30 de Junio del 2008 Microsoft Learning ofrece un curso gratis, a parte de los que ya ofrecia «for FREE». Al registrarnos, se nos da un código con el que el precio del curso que elijamos se rebajará hasta $0 🙂 El código tiene validez por 30 días.

Remarcar que los siguientes cursos para desarrolladores son gratis ya de por sí, podriamos registrarnos en uno de pago mediante el descuento y realizar cualquiera de estos también:

Happy learning 🙂

Cursos gratis en Microsoft Learning | vtortola.NET

Parsear los argumentos de la línea de comando

Para determinadas situaciones, es más útil parametrizar nuestras aplicaciones desde los argumentos que pasamos al ejecutable que desde un archivo de configuración, sobre todo si es una aplicación de consola. El problema suele ser que lo que nos llega a nuestra aplicación es un array de cadenas y nosotros debemos relacionarlas entre ellas, pudiendo haber distintos tipos de elemetos como modificadores, parámetros, parámetros de los modificadores y distintas cantidades de ambos tipos de parámetros.

Este es un ejemplo de como ordenarlos obteniendo una estructura en la que todo esta ordenado en forma jerárquica para poder consultar fácilmente parámetros, modificadores y parámetros de los modificadores, la función devuelve una clase de este tipo:

public class CommandLineArguments
{
    public List<String> Parameters { get; private set; }
    public Dictionary<String, List<String>> Modifiers { get; private set; }
 
    public CommandLineArguments()
    {
        this.Parameters = new List<String>();
        this.Modifiers = new Dictionary<String, List<String>>();
    }
}

La función recorre el array de argumentos (args[]) identificando cada uno por su relación y posición y colocandolo en la clase anterior:

delegate void ModParFinder_(String key, Int32 current);
static CommandLineArguments ParseParameters(String[] args, Char modIndicator)
{
    CommandLineArguments cmdArgs = new CommandLineArguments();
 
    // Busca los parametros de un modificador y los 
    // añade a la clave dada
    ModParFinder_ ModParFinder =
        new ModParFinder_(delegate(String key, Int32 current)
        {
            current++;
 
            if (!cmdArgs.Modifiers.ContainsKey(key))
                cmdArgs.Modifiers.Add(key, new List<String>());
 
            while (current < args.Length && !args[current].StartsWith(modIndicator.ToString()))
            {
                cmdArgs.Modifiers[key].Add(args[current]);
                current++;
            }
        });
 
    Boolean modsFound = false;
    if (args != null)
        for (Int32 i = 0; i < args.Length; i++)
        {
            if (args[i].StartsWith(modIndicator.ToString()))
            {
                ModParFinder.Invoke(args[i], i);
                modsFound = true;
            }
            else if (!modsFound)
                cmdArgs.Parameters.Add(args[i]);
        }
 
    return cmdArgs;
}

Para usar y consultar esta funcionalidad, un sencillo ejemplo:

static Int32 Main(String[] args)
{
    Console.WriteLine(Environment.CommandLine);
 
    CommandLineArguments cmdL = ParseParameters(args, '-');
 
    // Mostrar la información recabada
 
    Console.WriteLine("Parameters: ");
    foreach (String s in cmdL.Parameters)
    {
        Console.WriteLine("  " + s);
    }
 
    Console.WriteLine("Modifiers: ");
    foreach (String k in cmdL.Modifiers.Keys)
    {
        Console.WriteLine(k+": ");
        foreach (String s in cmdL.Modifiers[k])
            Console.WriteLine("  " + s);
    }
 
    Console.ReadKey(true);
    return 0;
}

Por ejemplo, si ejecutamos la aplicación y le pasamos los siguientes argumentos:

MiApp.exe "C:Archivos de programapath largo" -s smod -l "lmod largo" 123 -w wmod1 wmod2 -h -j

El resultado será el siguiente :

Parameters:
C:Archivos de programapath largo
Modifiers:
-s:
smod
-l:
lmod largo
123
-w:
wmod1
wmod2
-h:
-j:

Luego el validar la cantidad y corrección de los parámetros y modificadores… a gusto de cada uno 😀

Parsear los argumentos de la linea de comando | vtortola.NET

Dar el foco a una aplicación externa

Para dar el foco a una aplicación externa a la nuestra, se usa el método SetForegroundWindow de user32.dll mediante PInvoke:

        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

Simplemente hay que encontrar el proceso y pasar a este método el puntero Process.MainWindowHandle, que apunta a la ventana principal de la aplicación, por ejemplo asi:

        Process runningProc = Process.GetProcessesByName("notepad").First();
        SetForegroundWindow(runningProc.MainWindowHandle);

Ojo que no es el mismo que Process.Handle🙂

Existe un pequeño… inconveniente… cuando el proceso que queremos controlar acaba de iniciarse. Es posible que algunas veces no funcione, ya que el MainWindowHandle  podría no estar configurado ó la aplicación no ha terminado de arrancar… y no se ha enganchado todavia al bucle de mensajes de la GUI (por lo que enviarle el mensaje de foco seria inútil). Para solventar este problema, podemos hacer uso del método Process.WaitForInputIdle que espera a que la aplicación este en estado Idle y por tanto… esperando mensajes de la cola:

        Process newProc = Process.Start("notepad");
        newProc.WaitForInputIdle(1000);
        SetForegroundWindow(newProc.MainWindowHandle);

Espero que sea de utilidad.

Dar el foco a una aplicación externa | vtortola.NET

Chatarra a precio de oro II (a ver si alguien de IT me echa una mano :P )

Estoy empezando a pensar que esto es una broma de camara oculta ó similar. Sigo en mi lucha con el maravilloso programa para hacer test. Realmente no sé que pensar ya, supongo que los test que incluye son buenos … porque lo que es el programa… tela…

 Ya están hechos los agujeros en la pared para pasar los cables… y llegan las pruebas de funcionamiento en red, desinstalo la aplicación ya que no hay forma de pasar de monopuesto a multipuesto y vuelvo a reinstalar:

  • La desinstalación del programa no funciona completamente, si lo instalas en un modo (local) y luego lo quieres reinstalar en otro (en red)… has de ir borrando archivos del hdd porque no desinstala bien y quedan archivos residuales de configuración en «Archivos de Programa».
  • Cuando eliges una instalación en red, te instala la base de datos en local… aunque ese PC luego se vaya a conectar a un servidor.
  • La carpeta del servidor donde esta la BD… tiene que estar compartida y con todos los permisos para los usuarios de las máquinas clientes … es decir… CUALQUIER USUARIO PODRÍA BORRAR LA BD!! El servicio técnico me ha contestado a esto… «tendría que ser un usuario malintencionado»… en fin, del riego va a ser.

En fin, y las máquinas clientes con XP Home Edition 🙁  Al final ó encuentro la forma buena de reponer gpedit.msc en  este sistema operativo ó me tocará pagar el upgrade a XP Professional Edition, ó instalar un programa para cibercafes ó yo que sé, pero si no como a alguien se le ocurra acceder al servidor por red… que risa 😐

El problema:

La red quedará dividida en dos, una donde están todos los equipos para realizar test y conectados a eth1 del servidor; otra donde esta el router ADSL al que el servidor esta conectado mediante eth0 . El servidor NO comparte la conexión.  Todos los equipos tienen XP HE y por lo tanto es una red en grupo de trabajo con las limitaciones propias de estos sistemas operativos, necesito que los usuarios Invitados NO puedan acceder a la red mediante el explorador de Windows… aunque la carpeta este compartida y con permisos para todo dios.

Cualquier idea sera bienvenida y agradecida 🙂

 

Chatarra a precio de oro II | vtortola.NET

Chatarra a precio de oro

Mi padre, que tiene una autoescuela, acaba de adquirir un software para que los alumnos realizen test de una de las principales (si no la más famosa) editoriales españolas especializadas que seguro todos conoceis, aunque no diré el nombre. El caso es que se ha decidido adquirir un nuevo software por cambiar de aires, ya que siempre lo mismo … no da muy buena imagen, asi que esto se ha planteado como una inversión… no precisamente barata.

Actualmente, estaba trabajando con un programa que adquirió en 1995, corria sobre Windows 3.11, esta hecho en la versión de Visual Basic de la época y que cumplia correctamente su función. Además presenta una interfaz intuitiva que hacia que gente profana en la informática, como mis padres… pudieran trabajar con el fácilmente, es altamente configurable y la información, test, ayuda e imágenes estan bien estructuradas facilitando la creación de nuevos tests. La única posible pega… era que los usuarios tienen sus datos en un disquete con su nombre que deben utilizar para iniciar sesión … y bueno, el feo aspecto grisáceo pseudo-3D que tiene una aplicación Windows 😀

 

Este tipo de programas no evoluciona mucho, ya que funcionalmente siempre son lo mismo:

  • Una pantalla de inicio de sesión.
  • Una pantalla donde el alumno puede revisar su evolución con los test realizados, las preguntas falladas, ..etc…
  • Una pantalla de selección de test.
  • Una pantalla que muestra preguntas con 3 respuestas donde solo una es la correcta, puede haber una imagen y una ayuda opcional que explica la pregunta en si.

Adicionalmente hay un módulo específico para el profesor, protegido con contraseña, donde:

  • Puede confeccionar test.
  • Puede confeccionar nuevas preguntas, con sus 3 respuestas, la respuesta que es correcta y la imagen si procede.
  • Imprimir test.
  • Gestionar alumnos.

Realmente un programa asi es bastante sencillo de hacer con por ejemplo .NET y SQL Server 2005 Ex, el problema son los test… normalmente un recurso bajo copyright, que no puedes copiar.

Este nuevo programa, tiene la misma funcionalidad, ó al menos eso dice, más vistoso… y la posibilidad de centralizar los usuarios en una BD de Borland en lugar de que los alumnos tengan que ir con disquetes. Es comenzar a usar el nuevo programa y decir… NO ME LO PUEDO CREER!! , este es el resultado de unas dos horas de uso:

  • Borras un usuario, lo vuelves a crear y todos los datos sobre tests realizados y demás … persisten!
  • Al crear un nuevo alumno, ningún dato es obligatorio, lo que provoca que si omites algún dato que debería serlo, al intentar iniciar sesión aparecen excepciones… en inglés y hablando de problemas de conversión de datos.
  • Para crear un nuevo alumno, se pulsa un botón de «nuevo», se escribe en unos TextBox y se le da a un boton «guardar»… pero puedes escribir directamente sobre los TextBox y darle a «guardar» sin que aparezca ningún error, aunque evidentemente no crea el usuario. 
  • No hay forma de cambiar el password del profesor, al menos desde la misma aplicación sin meterse a la BD a pelo.
  • Esta hecho el Delphi, lo sé porque dos aplicaciones mantienen el icono que el IDE les da por defecto 😀
  • Insertar una imagen en una pregunta puede llevar horas ya que no hay ningún tipo de estructura, clasificación ó nomenclatura documentada que las organice, si hay 500 te tienes que mirar las 500 para ver si encuentras la que buscas.
  • Al entrar, el usuario introduce su clave en un teclado numérico en pantalla, donde cada botón es un cuadrado que tiene un tamaño como el puntero del ratón a lo alto, sin embargo el label de «Introduzca su clave» … en nuestras pantallas de 17″ debera tener 10x20cm.
  • Los ListBox coloreados, que son parte principal de la interfaz para el alumno, no sombrean al seleccionar, mi padre me hizo bajar explícitamente porque decia «le doy y no selecciona». La diferencia entre estar seleccionado ó no, es la débil línea de puntitos que pone Windows. Veremos que fina tienen la agudeza visual los alumnos.
  • Todos los botones son imagenes (como PictureBox) y parece que se desarrolló a 800×600 sobre una pantalla de 14″… al ponerlo sobre nuestros monitores de 17 algunas etiquetas son ilegibles debido al stretch.
  • En algunos de estos botones, hay partes de la imágen donde haces click y no sucede nada.
  • El cuadro donde se muestra la ayuda de la pregunta, tiene como unas 50 líneas en blanco, lo que provoca que a poco que muevas el scroll … te vayas a la zona en blanco.
  • Algunas ayudas son imágenes en vez de texto y cuando la muestras ya no la puedes ocultar.
  • Cuando abandonas un test aparece un mensaje diciendo que «el tiempo para realizar el test ha acabado», aunque hayas abandonado explícitamente a los dos segundos.

Además de muchas cosas que hacen que la mecánica de la aplicación sea obtusa en lugar de intuitiva para el profesor. Eso si, viene con su llave Hasp y además cada vez que lo instalas hay que llamar por telefono para que lo activen.

Entiendo que el verdadero valor de estas aplicaciones sean los test que contienen pero… no sé… «un poquito de por favor» … no? 🙂 Resumiento, en mis manos un programa del 2007, supuestamente uno de los mejores, que no supera a otro de 1995 ni en funcionalidad ni en facilidad de uso, lo único nuevo que aporta es … mucho colorido y una BD central para trabajar en red.

Así esta el patio, yo desde luego no doy crédito y estoy intentando convencerle para que lo devuelva.

Chatarra a precio de oro | vtortola.NET