Una práctica que era común en el desarrollo de software de hace unos años consistía en mezclar el código fuente de la aplicación junto con cadenas de texto y otros recursos (iconos, imágenes, etc.). El siguiente diagrama lo explica gráficamente:

Conforme el mercado comenzó a globalizarse fue surgiendo la necesidad de traducir aplicaciones a múltiples idiomas, y por ende este método acabó siendo completamente descartado por los siguientes motivos:
- Para traducir una aplicación primero hay que crear una o más copias de su código fuente, con el consecuente coste añadido que supone el mantenerlas.
- Los traductores, que por lo general no tienen conocimientos de programación, tienen que manipular el código fuente para traducir las cadenas de texto. Esto puede introducir errores en el funcionamiento de la aplicación.
Es en esta época cuando el uso de una versión en inglés (o en el idioma nativo de la empresa que desarrollara ese programa) sí podía ofrecer ciertas ventajas con respecto al resto de idiomas. La posibilidad de introducir errores en el código mientras se traducía un programa no era algo descabellado, todo ello debido a que la separación entre código fuente y cadenas de texto dependientes del idioma era insuficiente (en este caso particular, inexistente).
Las versiones de Windows anteriores a Vista introdujeron una nueva arquitectura de localización de binarios, con el objetivo de separar el código fuente (las instrucciones que acaba ejecutando el computador) de las cadenas de texto (mensajes informativos, errores, iconos, etc.).

Si bien esta arquitectura es válida y sigue siendo usada por muchísimas aplicaciones hoy en día, presenta algunas deficiencias que se magnifican en una empresa del tamaño de Microsoft: Por ejemplo, si se detecta un fallo de seguridad en un binario y se quiere desarrollar una actualización de seguridad al respecto, como el código fuente y las cadenas de texto están en el mismo fichero (pese a estar separados entre sí), sería necesario generar un par de decenas o más de actualizaciones de seguridad, una para cada idioma en el que está disponible Windows. Esto retarda innecesariamente el desarrollo de actualizaciones de seguridad en varios idiomas, pues por lo general los errores de seguridad afectan únicamente al código de la aplicación, no a las cadenas de texto y otros recursos que pudiera contener.
Con Windows Vista se rediseñó en profundidad la arquitectura MUI (Multilingual User Interface) que ya estaba presente en la versión Professional de Windows XP (entre otros) para que las cadenas de texto y el código de las aplicaciones estuviera completamente separado, esto es, en ficheros diferentes.

Esta arquitectura MUI introducida con Windows Vista no solo beneficia a Microsoft y al usuario, que ya puede instalar un paquete de idiomas en una versión de Windows que no esté en inglés, también beneficia a los desarrolladores de aplicaciones, pues por fín disponen de una arquitectura proporcionada por el sistema operativo para manejar recursos en múltiples idiomas, sin ser ya necesario que se construyan una desde cero.
¿Qué ocurre al instalar Windows Vista/7?
En un artículo de mi antiguo blog tengo un artículo que explica resumidamente en qué consisten las fases de la instalación de Windows Vista. Básicamente lo que ocurre es que en primer lugar se instalan los binarios del sistema (independientes del idioma), y seguidamente se instala uno o varios paquetes de idiomas. Como ve, el inglés no recibe ningún tipo de trato preferencial, se le trata como un idioma más. La fase correspondiente a la instalación del paquete de idiomas inicial se realiza durante la fase "Instalando características".
En Windows Vista la herramienta encargada de instalar un paquete de idiomas es la denominada Package Manager (Pkgmgr.exe). En Windows 7, se usa la herramienta Dism (Deployment Image Servicing and Imaging), que integra todas las funcionalidades de Package Manager y de otras herramientas igualmente relacionadas con la administración de imágenes de instalación.
En este primer artículo se ha explicado cómo ha ido evolucionando la localización del software a lo largo del tiempo y se ha aclarado que en Windows Vista y Windows 7 los binarios están completamente separados de las cadenas de texto, con las ventajas que esto conlleva. Esto implica también que Vista/7 sean sistemas idependientes del idioma en el que se utilicen; el inglés es un idioma como otro cualquiera.
En un siguiente artículo se explicará en detalle en qué consiste exactamente un paquete de idiomas y qué es lo que conforma la infraestructura MUI de Windows Vista/7. Se explicará también cómo el sistema obtiene los recursos en el idioma establecido por el usuario. Este aspecto puede ser importante para la gente que le interese saber cómo solucionar problemas con Windows, pues me he encontrado con algún que otro sistema cuyo síntoma es que una determinada aplicación no muestra ningún tipo de interfaz gráfica (es decir, no se abre) y cuya causa es una configuración incorrecta de los recursos MUI de ese sistema.
En un foro que frecuento un usuario tenía el siguiente problema: Al intentar ejecutar como administrador un programa en Windows 7 usando el comando Runas.exe, le aparecía el siguiente mensaje de error:
740: La operación solicitada requiere elevación.
Ciertamente el usuario estaba proporcionando el nombre de usuario y la contraseña de un usuario con privilegios administrativos así que... ¿dónde estaría el problema?
En primer lugar, vamos a analizar con calma lo que quiere decir el mensaje de error. El mensaje de error "La operación solicitada requiere elevación" está recogido en el fichero de cabecera Ntstatus.h del SDK de Windows Vista y posteriores. Concretamente está definido con el nombre de macro ERROR_ELEVATION_REQUIRED.
¿Cuándo se devuelve ese código de error durante el funcionamiento de Windows?
En Windows los procesos se crean usando la API CreateProcess. Uno de los pasos que se siguen antes de crear un proceso en Windows Vista y posteriores es comprobar si el proceso en cuestión necesita elevar sus privilegios o no. A la hora de determinar este aspecto, entran en juego, entre otros, dos parámetros: El nivel de ejecución (runlevel) impuesto por el manifiesto de la propia aplicación, y el token del usuario que está lanzando ese programa. Existen tres posibles niveles de ejecución para una aplicación:
- asInvoker: El nivel de ejecución es el mismo que el del proceso padre.
- highestAvailable: El nivel de ejecución es el de mayores privilegios posibles, considerando el tipo de cuenta desde la cual se ejecuta el proceso.
- requireAdministrator: El nivel de ejecución es administrativo, independientemente de las demás circunstancias.
Esta tabla recoge de forma básica las posibilidades:
| Nivel de ejecución de la aplicación |
Token del usuario |
Requiere elevación o no |
| AsInvoker |
Cualquiera |
No |
| highestAvailable |
Administrador "elevado" |
No |
| highestAvailable |
Administrador "estándar" |
Sí |
| highestAvailable |
Otro caso |
No |
| requireAdministrator |
Administrador "elevado" |
No |
| requireAdministrator |
Otro caso |
Sí |
Por administrador "elevado" me refiero a aquella cuenta con privilegios administrativos pero que, o bien ya ha elevado explícitamente sus privilegios (a través de un cuadro de UAC), o bien no tiene activada la característica Modo de aprobación del administrador (Admin Approval Mode). Esta característica se puede desactivar desde Directiva de grupo, pero yo personalmente lo desaconsejo. Un ejemplo de este tipo de cuentas es la cuenta "Administrador", creada durante la instalación del sistema operativo. Recuerde que el resto de cuentas con privilegios administrativos poseen dos tokens: uno limitado, con el que "actúan" por defecto, y otro "administrativo", que pueden aplicar si el usuario así lo indica a través de un cuadro de UAC.
Una vez que CreateProcess falla (devuelve un valor distinto de 1) y el último error se establece como ERROR_ELEVATION_REQUIRED (columna "Requiere elevación o no" de la tabla anterior), es asunto del proceso padre el tratar convenientemente este error. Si no lo hace, se registrará en Visor de sucesos, apartado dedicado a UAC, un evento informando de que el proceso padre no trató apropiadamente el error ERROR_ELEVATION_REQUIRED.
¿Qué ocurre cuando se lanza una aplicación desde la línea de comandos?
Imaginemos que el usuario intenta ejecutar el desfragmentador de disco de Windows 7 usando para ello una sintaxis de Runas.exe como esta:
runas /u:UsuarioAdministrador dfrgui.exe
Básicamente la línea de comandos detecta que no se trata de un comando interno, sino que se trata del programa Runas.exe, y por tanto se dispone a ejecutarlo usando CreateProcess. Como Runas.exe no es un programa que está marcado para requerir elevación de privilegios, CreateProcess retorna éxito.
Una vez que el planificador del sistema operativo cede el control al proceso Runas.exe recién creado, este se dispone a analizar su línea de comandos. Se encuentra con una petición de ejecutar Dfrgui.exe como si fuera el usuario administrador pasado como parámetro. Sin embargo, Runas.exe es poco más que un "envoltorio" de la API CreateProcessWithLogonW, que a su vez es poco más que un envoltorio de la API CreateProcess, pero pasando otro perfil de usuario distinto como parámetro.
Durante su ejecución, CreateProcess determina que Dfrgui.exe requiere privilegios administrativos (puesto que así se lo indica su manifiesto), y por ello devuelve falso y establace el último error como ERROR_ELEVATION_REQUIRED. Como Runas.exe es una herramienta que no está diseñada para tratar apropiadamente ese error, simplemente lo devuelve por pantalla de la forma "740: La operación solicitada requiere elevación".
Una vez desvelado el misterio, resta por comentar un aspecto que a estas alturas quizá ya se haya planteado:
¿Cómo es posible que ejecutando Dfrgui.exe desde la línea de comandos -sin usar Runas.exe- sí que aparezca un cuadro de UAC?
El secreto está en que la línea de comandos, antes de llamar a CreateProcess, informa al sistema de que va a tratar los posibles ERROR_ELEVATION_REQUIRED que puedan surgir. Esto lo consigue estableciendo unos atributos no documentados a la estructura STARTUPINFOEX, que se pasa como parámetro a la familia de API CreateProcess. Esto hace que no se registre el correspondiente error en el apartado UAC del Visor de sucesos. Seguidamente, la línea de comandos, sabiendo que se trata de un programa que debe elevar sus privilegios, lo intenta ejecutar mediante la API ShellExecuteEx. Esta API sí muestra el correspondiente cuadro de UAC, así que es la vía apropiada para ejecutar una aplicación que requiera privilegios administrativos.
En resumen, me gustaría resaltar estos puntos del tema del artículo:
- En Windows Vista y Windows 7 la única forma de ejecutar algo con privilegios administrativos es mediante un cuadro de UAC. No vale con poner el nombre de usuario y la contraseña de un administrador en la línea de comandos.
- Todo lo que se ejecute mediante la API CreateProcess, o alguna derivada de ella, no hará que aparezca un cuadro de UAC. Un ejemplo de ello es la utilidad Runas.exe.
- Runas.exe, en Windows Vista/7, sirve para ejecutar una aplicación como si fuera otro usuario, pero no sirve para ejecutarla con mayores privilegios.
- Si quiere que se ejecute una aplicación que requiere privilegios administrativos, use la API ShellExecuteEx, o alguna de sus derivadas. Esta API sí permite la aparición de un cuadro de UAC para que el usuario eleve sus privilegios.
Una de las dudas que más surgen entre los usuarios de Restaurar sistema es cada cuánto tiempo se creará un punto de restauración automático. Este artículo pretende dar una respuesta precisa a esta cuestión para así esclarecer aquellos casos en los que el sistema no haya creado un punto de restauración desde hace tiempo.
Windows XP
En Windows XP cada hora una tarea interna del Programador de tareas se encarga de analizar si el sistema está inactivo, es decir, si no está haciendo uso de la CPU ni del subsistema de E/S. Si se diera el caso, se realizan dos posibles comprobaciones para determinar si se debe crear un punto de restauración automático:
- Si han pasado más de 24 horas desde el último punto de restauración, se crea uno automáticamente. Este parámetro (24 horas) es editable desde el Registro del sistema operativo, concretamente en la clave HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\SystemRestore, valor RPGlobalInterval.
- Si la sesión actual de trabajo con el PC está durando más de X horas y el último punto de restauración es más antiguo, se crea un punto de restauración automático. Por defecto, esta configuración no está establecida, pero puede hacerlo desde el Registro en la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore, valor RPSessionInterval.
La comprobación de inactividad se realiza por defecto cada hora pero podría variar dependiendo de los valores de ciertas políticas de energía de su equipo. Eche un vistazo a los valores IdleTimeoutDc, IdleTimeoutAc de esta página de MSDN: http://msdn.microsoft.com/en-us/library/aa373239(VS.85).aspx. Aprovechando la inactividad, Restaurar sistema realiza otras tareas, tales como eliminar aquellos puntos de restauración cuyo tiempo de vida ya haya expirado, y de paso comprimir el almacén usando compresión NTFS. Estas tareas se realizan solo si el equipo está conectado a la corriente eléctrica, para evitar que se agote la batería en el caso de portátiles.
Si quiere profundizar en el funcionamiento de la herramienta Restaurar sistema de Windows XP, eche un vistazo a esta serie de artículos de mi antiguo blog:
http://rinconwindows.blogspot.com/2007/02/cmo-funciona-restaurar-sistema-parte-i.html
http://rinconwindows.blogspot.com/2007/03/cmo-funciona-restaurar-sistema-parte-ii.html
Windows Vista/7
En Windows Vista/7 el nuevo Programador de tareas muestra información detallada acerca de la tarea programada que crea un punto de restauración automático. Abra Programador de tareas, apartado \Microsoft\Windows\SystemRestore. La tarea SR tiene como desencadenantes:
- El inicio del sistema.
- Diariamente a las 12 AM.
En esos instantes se ejecutará el comando %windir%\system32\rundll32.exe /d srrstr.dll,ExecuteScheduledSPPCreation.
El modificador /d de Rundll32.exe ya lo traté ligeramente en mi antiguo blog: Se trata de un modificador que le dice a Rundll32.exe "ejecuta este comando y no captures las posibles excepciones que ocurran". La función ExecuteScheduledSPPCreation es la encargada de verificar si el punto de restauración más antiguo tiene más de 12 horas (la mitad que en el caso de XP) y, si así fuese, creará uno nuevo.
Hay que tener en cuenta otras condiciones adicionales que puede observar en la pestaña Condiciones: El sistema debe estar inactivo durante al menos 10 minutos y además, en el caso de portátiles, debe estar conectado a la red eléctrica.
Espero que este artículo haya aclarado sus dudas con respecto a la creación automática de puntos de restauración por parte de Windows. En resumen, si su sistema no genera periodicamente puntos de restauración puede deberse a:
- El servicio Programador de tareas no está iniciado.
- El sistema no está inactivo durante los periodos de tiempo impuestos por Windows, según lo explicado anteriormente.
Quizá ya se haya dado cuenta de que en Windows Vista/Windows 7 algunos módulos del Panel de control que anteriormente estaban implementados en la clásica forma de un fichero .cpl ahora lo están en la forma de un fichero ejecutable (.exe). El motivo de este cambio es que con la introducción de Control de cuentas de usuario (UAC), se da el caso de que algunos de estos módulos requieren privilegios administrativos para ejecutarse. Veámoslo con un ejemplo:
El ejecutable DPIScaling.exe del directorio \Windows\System32 implementa la opción del Panel de control que permite cambiar la escala DPI del sistema. Este módulo requiere privilegios administrativos para ejecutarse, como así indica su fichero de manifiesto. Para verlo prácticamente, descargue Strings desde http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx y abra una ventana de línea de comandos en el directorio donde la ha extraído. Introduzca este comando y pulse INTRO:
strings %SystemRoot%\System32\DPIScaling.exe | findstr /i requireAdministrator
La salida del comando, level="requireAdministrator", nos indica que el ejecutable en cuestión requerirá privilegios administrativos cuando lo invoquemos. Otros posibles valores para el atributo level son:
asInvoker: El ejecutable no requerirá privilegios administrativos.
highestAvailable: El ejecutable se ejecutará con los máximos privilegios que le permita la cuenta de usuario desde la que ha sido invocado.
Nombres canónicos en Windows Vista/Windows 7
Esta reestructuración de buena parte de los elementos del Panel de control trajo consigo una de las novedades que se introdujeron en Windows Vista y que se han mantenido en Windows 7: la posibilidad de abrir elementos del Panel de control usando un nombre canónico. Un nombre canónico es un nombre en inglés, no traducible, que describe de manera cercana al usuario el cometido de ese elemento del Panel de control. Esto evita que el usuario tenga que aprender el nombre de ficheros .cpl, muchas veces crípticos, y además permite separar el nombre del ítem de su implementación, ya sea en un clásico fichero .cpl o, ya sea en un fichero .dll o .exe.
Por ejemplo, para abrir el panel Agregar o quitar programas de Windows Vista/Windows 7, se puede usar esta sintaxis:
%windir%\system32\control.exe /name Microsoft.ProgramsAndFeatures
¿De dónde proviene ese nombre canónico, Microsoft.ProgramsAndFeatures?
Cuando el ejecutable Control.exe recibe el parámetro /name seguido de un nombre canónico, se invoca a la función IOpenControlPanel::Open, la cual en primer lugar busca el elemento correspondiente del Panel de control al que se está haciendo referencia. Cabe destacar que el Panel de control es un directorio virtual (no reside físicamente en el disco, sino que está implementado por el shell), situado en la clave de Registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace. El valor (Predeterminado) de cada una de las subclaves de esa rama de Registro contiene el nombre con el que se mostrará en Panel de control (no el nombre canónico). Para encontrar la implementación de, digamos, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace\{0DF44EAA-FF21-4412-828E-260A8728E7F1} (ítem de las propiedades de la barra de tareas y menú Inicio), se accede a la clave de registro HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}, en la cual existe un valor de registro de nombre System.ApplicationName y cuyo contenido es el nombre canónico: Microsoft.TaskbarAndStartMenu. Así pues, para abrir las propiedades de la barra de tareas y del menú Inicio ya sabemos que bastaría con ejecutar lo siguiente:
%windir%\system32\control.exe /name Microsoft.TaskbarAndStartMenu
Para ver qué es lo que realmente se ejecuta, eche un vistazo a la clave HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}\Shell\Open\Command.
Cada ítem del Panel de control puede implementar varias páginas
Podemos entender las páginas como subsecciones específicas del ítem del Panel de control. Para indicar una, debe usarse la sintaxis
%windir%\system32\control.exe /name Nombre_canónico /page Página
Veámoslo con un ejemplo:
Con los conocimientos que hemos adquirido, nos resulta sencillo determinar que el ítem Personalizar del Panel de control está implementado en la DLL Themecpl.dll. Es en esta DLL donde encontraremos información acerca de las posibles páginas de este ítem, en la forma, como no, de fichero XML.
Esta vez usaremos la aplicación gráfica Resource Hacker, que puede descargar gratuitamente desde http://www.angusj.com/resourcehacker/. Al abrir el fichero Themecpl.dll en esta aplicación, nos encontramos con dos ficheros XML adicionales al típico fichero de manifiesto (.manifest) que habíamos visto hasta ahora.

Este primer fichero XML especifica una serie de tareas que puede realizar el elemento del Panel de control "Personalizar". Estas tareas (cambiar los colores, el fondo de pantalla, etc.) se muestran como enlaces de texto justo debajo del elemento del Panel de control (suponiendo que esté configurado en la vista por categorías). Y lo que es más importante, estas tareas son indizables por el sistema de búsqueda de Windows Vista. Puede obtener más información en este artículo de MSDN: http://msdn.microsoft.com/en-us/library/bb776840(VS.85).aspx.

Esta segunda imagen hace referencia al segundo fichero XML, que es el que contiene la información acerca de cada una de las páginas que implementa este ítem del Panel de control. Entre las etiquetas <pagedefinition></pagedefinition> nos encontramos con una etiqueta <properties>, que hace referencia a cada una de las páginas. El atributo canonicalName nos ofrece su nombre canónico.
Como vemos, el ítem "Personalizar" del Panel de control admite como sintaxis:
%windir%\system32\control.exe /name Microsoft.Personalization /page pageColorization (para cambiar la configuración de color)
%windir%\system32\control.exe /name Microsoft.Personalization /page pageWallpaper (para cambiar el fondo de escritorio)
Ejercicio
Ahora que ya sabe cómo escudriñar en los ítems del Panel de control con el fin de construir accesos directos lo más directos posibles (valga la redundancia), le propongo como ejercicio que en un sistema Windows 7 averigüe la sintaxis para un acceso directo al Monitor de confiabilidad, que como sabe en Windows 7 está algo escondido dentro del Centro de actividades (Action Center).
Si se rinde, puede ver la solución seleccionando texto a partir de aquí: control.exe Microsoft.ActionCenter /page pageReliabilityView
A mucha gente le gusta personalizar su sistema de escritorio al máximo posible. Por ello, Microsoft acostumbra a incorporar en sus sistemas operativos bastantes menús y cuadros de diálogo capaces de personalizar muchos de los detalles de funcionamiento de Windows. Sin embargo, hay ciertos detalles que no son modificables desde la interfaz gráfica, solamente desde el Registro; siempre siguiendo los pasos de algún artículo de la documentación oficial de Microsoft (KB, MSDN LIbrary, Technet Library, etc.). También hay detalles que no están documentados pero que pueden "descubrirse" utilizando herramientas de monitoreo del Registro, como Process Monitor, tal y como se explica en este artículo.
En el caso que nos ocupa, el usuario quería modificar el tiempo de aparición de la vista en miniatura de una aplicación en la barra de tareas de Windows Vista. En Windows Vista, la funcionalidad Windows Aero permite ver, a golpe de ratón, el contenido de todas y cada una de las ventanas minimizadas en la barra de tareas. El usuario intentaba buscar una forma de acortar ese tiempo de aparición de la vista en miniatura, pues le parecía excesivo. En Internet la alternativa que es más popular es la de modificar el valor de Registro MouseHoverTime de la clave de Registro HKEY_CURRENT_USER\Control Panel\Mouse. Sin embargo, este valor influye en el tiempo que tarda en reconocerse un posicionamiento del cursor del ratón, en cualquier parte de la interfaz gráfica de Windows. Era necesario buscar algún valor de Registro más específico, y para ello iba a recurrir a Process Monitor.
Antes de nada hay que comentar que no tenía la garantía de que existiera un valor de Registro que controlara ese aspecto tan específico de la interfaz gráfica de Windows. De existir, suelen ser parámetros que solo se tienen en cuenta en las versiones de depuración (checked) del sistema operativo. De todas formas, abrí Process Monitor y establecí un filtro de aquellos eventos de Registro que contuvieran en su ruta la palabra "Thumbnail". Inicié Explorer.exe y rápidamente me encontré con tres eventos bastante interesantes:

El primer evento indica el momento en que Explorer.exe examina una directiva, TaskbarNoThumbnail, configurable desde Directiva de grupo, encargada de desactivar las vistas en miniatura de la barra de tareas. La lectura de este valor me hizo pensar que los dos valores siguientes podrían estar relacionados con lo que buscaba.
Esos dos eventos siguientes hacen referencia a una búsqueda de cierta rama en el Registro (ExplorerThumbnails), tanto en la rama HKEY_CURRENT_USER como en la rama HKEY_LOCAL_MACHINE. El primer evento hace referencia al SID de mi usuario dentro de la rama HKEY_USERS (HKU) simplemente porque ejecuté Process Monitor desde una cuenta limitada, proporcionando obviamente el nombre de usuario y contraseña del administrador.
¿Qué sería esa rama ExplorerThumbnails? La verdad es que no encontré nada documentado en Internet, pero su nombre era lo suficientemente atractivo como para seguir indagando. Una de las cosas que suelo hacer en casos como este es crear la clave que busca en este caso Explorer.exe y ver qué valores o subclaves de Registro busca a continuación. Eso hice: Abrí Editor del Registro y creé la clave de Registro ExplorerThumbnails. Volví a capturar una traza con Process Monitor y el resultado ofreció otros tres valores tan interesantes como desconocidos:

Los valores InitialThumbnail, InitialTooltip y AutoPopTooltip me hacían pensar que efectivamente estaban relacionados con lo que realmente buscaba: Modificar el tiempo de aparición de la vista en miniatura. En este caso podría haber experimentado introduciendo algunos valores aleatorios para esos valores de Registro y observar los resultados, aunque en este caso recurrí a una lectura del código fuente de Explorer.
Al parecer, el valor InitialThumbnail tiene que ver con el tiempo en milisegundos que tarda en aparecer la vista en miniatura desde que se sitúa el cursor del ratón en la aplicación minimizada en la barra de tareas; InitialTooltip influye en el tiempo de aparición del texto emergente que siempre aparece encima de la vista en miniatura, un tiempo después. Por último, AutoPopTooltip influye en el tiempo que tarda en desaparecer el texto emergente. Por defecto, si no se encuentran esos valores en el Registro, el sistema supone, respectivamente, 500, 1000 y 5000 milisegundos.
Para concluir, codifiqué una aplicación gráfica que facilitara la modificación de estos valores en el Registro: http://winvista.mvps.org/Ficheros/TweakThumbnails.zip
Ya conoce otro posible uso de Process Monitor: Intentar descubrir valores de Registro (o ficheros) no documentados pero que pueden permitirnos configurar aspectos más o menos interesantes del sistema operativo.
Nota: Como indico en el margen izquierdo de este blog, toda la información que no está documentada por Microsoft es muy susceptible de cambiar e incluso de desaparecer en versiones posteriores de Windows. Este es el caso particular de esta rama del Registro, pues no es tenida en cuenta en Windows 7. Adicionalmente, deberá tomar las medidas oportunas si aplica este tip en un entorno de producción, pues de seguro se trata de un parámetro que no está tan probado como el resto de personalizaciones conocidas en el sistema operativo.
En el anterior artículo vimos cómo abrir nuestra aplicación en modo usuario dentro de Windbg y comprendimos mejor qué es lo que ocurre cuando este se hace cargo de nuestra aplicación. Ahora tenemos a nuestra disposición una ventana con salida de texto y una caja de entrada de comandos pero, ¿qué podemos hacer?
Es importante saber que podemos manejar la ventana de Windbg e introducir comandos en su caja de texto porque nuestra aplicación está detenida debido a la excepción STATUS_BREAKPOINT que se recibe por defecto nada más abrir la aplicación en Windbg. Así pues, lo primero que buscamos es una forma de permitir que nuestra aplicación continúe con su ejecución. El comando g (o presionar F5) consigue esto mismo. Este comando hace que la aplicación siga ejecutándose hasta que se encuentre con alguna condición de parada (posteriormente aprenderemos a configurar esto), o bien ocurra algún tipo de excepción (por ejemplo, la aplicación quiere acceder a una posición de memoria incorrecta).
El comando g admite alguna que otra variante. Si, por ejemplo, queremos que nuestra aplicación siga ejecutándose hasta que se alcance una determinada posición de memoria, podemos usar la sintaxis g <Dirección>. Por otra parte, si solo nos interesa que continúe la ejecución hasta que finalice la función en curso, podemos usar el comando gu.
¿Cómo detener la ejecución de la aplicación en los momentos que nos interese?
Uno de los aspectos más importantes en la depuración de aplicaciones es la creación de breakpoints. Windbg nos proporciona los medios necesarios para crear todo tipo de breakpoints, desde los más sencillos hasta los más imaginativos. Saber qué tipo de breakpoint se debe usar en cada caso nos permitirá ahorrar horas de trabajo infructuoso.
Establecer breakpoints en código
El primer tipo de breakpoints que voy a tratar son los clásicos breakpoints en código. Como su nombre indica, son breakpoints que se alcanzan en una determinada dirección de código (típicamente el inicio de una función, pero podría ser cualquier otra cosa). El comando de Windbg para crear este tipo de breakpoints es bp. Este comando recibe como parámetro la dirección en la que queremos detener la ejecución del programa y, opcionalmente, algunas restricciones y comandos que se ejecuten automáticamente cuando se llegue al breakpoint. El abanico de restricciones que se pueden establecer conforma un amplio tipo de breakpoints que se conocen como breakpoints condicionales, que se tratarán más adelante en este artículo. Por ejemplo, si introducimos el comando bp MiAplicacion!MiFuncion "kb" y pulsamos INTRO, lo que va a ocurrir es que cuando reanudemos la ejecución de nuestra aplicación (con el comando g, como ya sabe) y se llegue a la función cuyo símbolo es MiAplicacion!MiFuncion, el depurador informará sobre esto y automáticamente ejecutará el comando kb, que como verá posteriormente, sirve para ver el estado de una estructura de datos muy importante para un proceso/hilo, la pila de ejecución.
Una cosa que quizá se pregunte es, ¿cómo averiguar qué símbolo de función me interesa? Una opción de fuerza bruta consiste en mostrar en pantalla todos los símbolos que cumplan con un determinado patrón y buscar aquella función que puede interesarnos. El comando x consigue esto mismo. Por ejemplo, si quisiera mostrar los símbolos de MiAplicacion que contuvieran la palabra "Window", podríamos usar la sintaxis x MiAplicacion!*Window*. Al pulsar INTRO, WIndbg buscará entre los símbolos disponibles aquellos que coincidan con el patrón establecido y los mostrará en pantalla junto con sus correspondientes direcciones. Si bien esta aproximación de fuerza bruta es útil en algunos casos, lo más probable es que el símbolo en el que quiera detener la ejecución del programa lo obtenga de los resultados que le proporcione Windbg al ejecutar otros comandos.
Por supuesto, también podemos crear múltiples breakpoints sin necesidad de tener que establecerlos uno a uno. Supongamos que nuestra aplicación tiene algún problema a la hora de escribir ciertos archivos en el disco. Podríamos suponer que los símbolos que más nos interesa son los de aquellas funciones que contengan la palabra "Write". Para agregar breakpoints para todos y cada uno de los símbolos que cumplan con este patrón, podemos usar el comando bm, de la siguiente manera: bm MiAplicacion!*Write*
Si la aplicación que se está depurando tiene un cierto grado de complejidad, es bastante probable que haga uso de librerías dinámicas (DLL) cuya carga no se conoce de antemano y se produce en tiempo de ejecución. Por este motivo, si necesitara parar la ejecución en alguna función dentro de esas librerías dinámicas no le sería posible, pues Windbg no conoce la dirección de la función donde debe detenerse. A fin de cuentas, Windbg solo entiende de direcciones de memoria. Para dar solución a este problema, existe el comando bu. Por ejemplo, si nuestra aplicación hiciera uso de una DLL para calcular los primeros dígitos decimales del número pi, podemos detener la ejecución en dicha función ejecutando el comando bu MiDLL!CalcularPI. Una vez introducido el comando lo que ocurre es que Windbg sabe que justo en el momento en que el módulo correspondiente a esa DLL (MiDLL) se cargue en memoria (eche un vistazo al artículo anterior para obtener más información sobre la carga de módulos), debe crear el correspondiente breakpoint, ahora que sabe cuál es su dirección de memoria.
Establecer breakpoints por acceso a un dato
En muchos casos vamos a necesitar parar la ejecución de nuestro programa no cuando se llegue a una porción de código, sino cuando se acceda a un dato. El escenario típico de esto es una aplicación que en apariencia sufre un bug del tipo buffer overrun. Básicamente este tipo de problemas implica que se sobreescriban posiciones de memoria contiguas a las de una porción de datos del programa, por ejemplo un vector. En esta situación, quizá necesitemos indagar sobre todos y cada uno de los accesos que se produzcan hacia este vector. Podemos lograr esto ejecutando el comando ba w4 miVector, suponiendo que el símbolo miVector sea el correspondiente al vector que queremos examinar. Por supuesto, podemos sustituir el símbolo por una dirección de memoria. ¿Qué significa el w4 que aparece como primer parámetro del comando ba? "W" indica que estamos buscando accesos de tipo escritura. Otras posibilidades son "E" (ejecución) y "R" (lectura). El "4" indica el número de bytes que queremos monitorizar. En las arquitecturas de 32 bits este valor puede ser 1, 2 ó 4. En las de 64 bits existe la posibilidad de establecer también 8 bytes como tamaño.
Como habrá podido observar, la creación de breakpoints es un aspecto complejo de Windbg. La capacidad más interesante a mi juicio es la posibilidad de crear breakpoints condicionales. Como vimos, para crear un breakpoint se usa el comando bp. Uno de los parámetros de este comando va entrecomillado y representa una condición adicional a la condición estándar (la llegada a la correspondiente función). Incluso se puede omitir la función y dejar solamente la condición. Supongamos que nuestro programa tiene una variable Contador que va incrementándose cada vez que se itera en un bucle, por ejemplo. Quizá estemos interesados en parar la ejecución de nuestra aplicación cuando la variable Contador adquiera el valor 10, que sabemos que es el valor de finalización del bucle. Para ello podríamos usar esta sintaxis:
bp ".if (poi(Contador)==10) {.echo Fin de cuenta }"
Este comando establece un breakpoint (bp) cuya condición (.if) es que la variable Contador sea igual al número 10. En tal caso, sacamos por pantalla (.echo) la cadena "Fin de cuenta". El comando poi se usa porque de no hacerlo, la variable Contador sería interpretada como una dirección de memoria, y esto no es lo que queremos. Como queremos tener acceso al contenido de esa dirección de memoria, los programadores de C que estén leyendo esto contestarán rápidamente que necesitamos desreferenciar ese acceso. En C esto se hace con el operador * y en Windbg con poi.
Cómo mostrar un listado de los breakpoints que hemos añadido
Una vez que hayamos establecido los breakpoints que necesitemos, es posible que queramos ver un listado de los mismos. Puede usar para ello el comando bl o bien usar la interfaz gráfica de Windbg: Si pulsa F9, se abrirá el cuadro de diálogo Breakpoints, desde el que podrá ver un listado de los breakpoints asociados a la sesión de depuración actual y crear de manera más o menos intuitiva otros nuevos. Mi consejo es usar siempre que sea posible la propia consola de comandos de Windbg, pues suele ofrecer más flexibilidad que la interfaz gráfica, pero comento esta posibilidad por si alguien se siente más cómodo/a usando cuadros de diálogo.
En este artículo hemos aprendido a crear breakpoints básicos y sencillos y otros no tan sencillos. Hemos visto también que la potencia de los breakpoints reside en los breakpoints condicionales, pues el único límite prácticamente es el de nuestra imaginación. La documentación de Windbg (F1) ofrece información más detallada sobre cada uno de los comandos que he tratado aquí, pero espero esto que sirva como punto de partida para sacarle el mayor provecho posible a esta funcionalidad que nos proporciona el sistema operativo en conjunción con Windbg. En los próximos artículos veremos comandos que nos permiten examinar el estado de la máquina. Para comprender mejor la salida de estos comandos, se explicarán también algunos conceptos importantes de la estructura de un computador y del sistema operativo, como son el repertorio de registros, la pila de ejecución o el bloque de control de un proceso/hilo.
Hace unos días en un grupo de noticias que frecuento un usuario que estaba utilizando este script del MVP Enrique Cortés se preguntaba por qué en el fichero de resultados las horas de cada punto de restauración no coincidían con las mostradas en el calendario de Restaurar sistema.
Esto se debe a que en la información que se guarda en el almacén de puntos de restauración (y que es accedida por WMI en el script) las fechas y horas tienen como huso horario +000 (GMT). Así pues, modifiqué el script para que las fechas se conviertan a la zona horaria del sistema en cuestión y aproveché para mostrarlas en un formato más legible. En principio el script es compatible con cualquier versión a partir de XP, pero en Vista y 7 deberá ejecutarlo con privilegios administrativos.
Puede descargar el script modificado desde esta página.
¡Que lo disfuten!
A principios de este mes Technet ha publicado una nueva utilidad que no debería faltar en la «caja de herramientas» de toda persona que se enfrente a un problema con Windows. ProcDump es una herramienta que se adhiere a un proceso de la máquina y genera un volcado de memoria en el momento que se cumplan ciertas condiciones, como por ejemplo un alto consumo de CPU, una ventana que no responde, una excepción no manejada, etc. En este sentido se trata de una herramienta similar al script ADPlus.vbs, aunque considero que ProcDump resulta más intuitiva y algo más sencilla de utilizar.
Puede descargar la versión 1.0 de ProcDump en http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx
En algún artículo posterior espero poder mostrar el uso de esta versátil herramienta para resolver un problema real.
Como quizá sepa, el comando Runas.exe de Windows XP y Windows Server 2003 sirve para ejecutar procesos en el contexto de otra cuenta de usuario. Los usuarios domésticos normalmente lo usan para ejecutar un proceso como administrador desde una cuenta limitada. Echando un vistazo al listado de parámetros de Runas.exe nos encontramos con uno que suele llamar la atención de bastante gente. Sirve para almacenar temporalmente en el administrador de credenciales (Credential Manager) el usuario y contraseña que va a ejecutar el programa. El atractivo de este parámetro es que no tendremos que introducir el nombre de usuario y contraseña para ese programa durante la sesión en curso. Sin embargo, no hay unanimidad con respecto al nombre del parámetro (incluso la propia documentación del sistema operativo creo que presenta alguna inconsistencia al respecto): Unos lo llaman /savecred, otros /savedcred, otros /savedcreds... Incluso en algunos sitios se indica que tienen semántica diferente.
Nada más lejos de la realidad. Runas.exe solo entiende el parámetro /sa (que contiene el mínimo número de letras que diferencian /savecred de los parámetros /smartcard y /showtrustlevels); lo que venga después le es indiferente. Del mismo modo, en cuanto se encuentra con /p supone el parámetro /profile; si se encuentra con /e supone /env, y así sucesivamente.
Nota: Por limitaciones del administrador de credenciales de XP Home Edition, el parámetro /savecred no es tenido en cuenta en esta versión de Windows. Este artículo no es aplicable tampoco a Windows Vista, pues el comando Runas.exe en Windows Vista es bastante diferente del de XP y será tema de un próximo artículo.
Desde que salió a la luz Windows Vista, y ahora con las versiones preliminares de Windows 7, me he dado cuenta de que el número de problemas cuya solución implica el registro de una DLL (mediante el comando regsvr32 nombreDLL) ha descendido notablemente en estos dos últimos sistemas operativos. Una de las causas de esto, para mí, es la inclusión de Windows Resource Protection (WRP), mecanismo que garantiza la integridad de los componentes vitales del sistema operativo y que supone una tremenda mejora con respecto a Windows File Protection (WFP), sistema de protección de archivos de sistema presente en Windows 2000 y XP.
Windows File Protection (WFP)
Windows 2000 y XP incorporaron una característica denominada WFP (Windows File Protection), encargada de proteger los archivos más importantes del sistema operativo para evitar que sean modificados o eliminados.
Su funcionamiento se basa en uno o varios hilos de tipo centinela residentes en el proceso Winlogon e implementados en la DLL Sfc_os.dll. Es decir, estos hilos están al tanto de cualquier tipo de modificación que se realice sobre directorios del sistema (típicamente \System32 y \System32\drivers). Si hubiera cambiado alguna DLL de estos directorios, se registra dicho suceso en una cola destinada a tal efecto. En ese momento se señaliza un evento que despierta a otro hilo encargado de realizar la verificación del correspondiente archivo y su recuperación desde la cache (carpeta oculta \WINDOWS\System32\dllcache). Si no estuviera en cache, se mostrará una interfaz al usuario informándole de tal situación e invitándole a introducir el CD de Windows 2000/XP para intentar recuperar la versión original del archivo.
Windows Resource Protection (WRP)
La llegada de Windows Vista supuso que la estructura interna del sistema operativo cambiara radicalmente. Ahora el sistema operativo está formado por componentes, claves de Registro, manifiestos XML y ficheros binarios, entre otras cosas, por lo que la aproximación empleada en versiones anteriores de Windows ya no podía seguir siendo válida. Este aspecto puede ser interpretado como una ventaja, pues si se desarrolla un sistema de protección para cada uno de los componentes del sistema operativo, ya no solo estaremos protegiendo ejecutables y DLL, como en Windows 2000/XP, sino que estaremos protegiendo también claves de Registro y otro tipo de recursos que son igualmente vitales para el correcto funcionamiento del equipo. Este sistema de protección recibió el nombre de Windows Resource Protection (WRP).
Cada uno de los componentes que conforman el sistema operativo Windows Vista/Windows 7 contiene un fichero denominado manifiesto. Un manifiesto es un fichero de tipo XML que contiene información específica sobre el componente, es decir, archivos que lo componen, archivos de los que depende, claves de Registro, privilegios con los que se ejecutará por defecto, idioma, etc. Uno de estos posibles parámetros (etiquetas XML) es la protección del recurso en cuestión, etiqueta <systemProtection></systemProtection>. Existen distintos valores posibles para el parámetro behavior (comportamiento) de esa etiqueta:
- readOnlyIgnoreWrites: El recurso solo puede ser modificado por el sistema operativo, durante una instalación (servicio TrustedInstaller). Cualquier intento de escritura por parte de una aplicación será descartado; es decir, se le informará de que la escritura se realizó con éxito pero el fichero no se verá modificado.
- readOnlyFailWrites: El recurso solo puede ser modificado por el sistema operativo, durante una instalación (servicio TrustedInstaller). Cualquier intento de escritura por parte de una aplicación tendrá como consecuencia que reciba un error.
- OSOnlyIgnoreWrites: Similar a readOnlyIgnoreWrites, pero las modificaciones las puede hacer cualquier componente del sistema operativo.
- OSOnlyFailWrites: Similar a readOnlyFailWrites, pero las modificaciones las puede hacer cualquier componente del sistema operativo.
- applicationVirtualized: Cualquier cambio que se haga sobre el recurso supondrá que el sistema operativo cree una copia privada a la aplicación que lo ha modificado. El recurso global no se ve modificado.
- userVirtualized: Similar a applicationVirtualized pero la copia privada es por usuario, no por aplicación.
En el mismo fichero de manifiesto se indica también qué descriptor de seguridad usar para dicho componente. Por ejemplo, la carpeta Winsxs de Windows Vista tiene este descriptor de seguridad:
O:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464
G:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464
D:PAI
- (A;OICI;FA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)
- (A;OICI;0x1200a9;;;BA)
- (A;OICI;0x1200a9;;;SY)
- (A;OICI;0x1200a9;;;BU)"
Donde S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 es el SID de TrustedInstaller, un servicio encargado de instalar actualizaciones y componentes en Windows Vista y Windows 7.
Vamos a explicar un poco el descriptor de seguridad: Las dos primeras líneas indican que el propietario (O, de owner) como el grupo (G, de group) es TrustedInstaller. La línea D:PAI quiere decir que el DACL es protegido (es decir, que no hereda listas de control de acceso o ACL) y además se hereda automáticamente. A continuación se indica que TrustedInstaller tiene acceso total al recurso (FA, de full access); el grupo de administradores, sistema y usuario (BA, SY y BU, respectivamente) tienen acceso genérico de lectura/escritura. Así pues, ni siquiera un administrador podrá modificar el contenido del directorio Winsxs. Tan solo TrustedInstaller, con motivo de la instalación/desinstalación de actualizaciones, Service Packs o componentes opcionales de Windows podrá modificar ese directorio.
Si quiere saber más sobre ACL y DACL le recomiendo el libro Windows Internals, escrito por Mark Russinovich y David Solomon, ya sea en su cuarta o su quinta edición.
Veámoslo con un ejemplo
Abriendo el fichero de manifiesto del componente Bloc de notas de Windows Vista podemos observar entre otras cosas lo siguiente:
<dependentAssembly>
<assemblyIdentity name="Microsoft-Windows-Kernel32" version="6.0.6001.18000" processorArchitecture="x86" language="neutral" buildType="release" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS" />
</dependentAssembly>
Aquí se hace referencia a que Bloc de notas depende del componente Microsoft-Windows-Kernel32 (que contiene entre otras cosas la DLL Kernel32.dll) para funcionar correctamente.
<systemProtection xmlns="urn:schemas-microsoft-com:asm.v3" behavior="readOnlyFailWrites" perUserVirtualization="Disabled" />
Aquí se hace referencia a que cualquier intento de escritura sobre el componente Bloc de notas dará como resultado un error y no se llevará a cabo la modificación. La virtualización está desactivada, por tratarse de un componente de Windows.
<shortCut arguments="" destinationPath="$(runtime.documentsSettings)\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories" destinationName="Notepad.lnk" targetPath="$(runtime.system32)\notepad.exe" iconPath="$(runtime.system32)\notepad.exe,0" windowStyle="normal" workingDirectory="%HOMEDRIVE%%HOMEPATH%" description="@%SystemRoot%\system32\Shell32.dll,-22563" displayResource="$(runtime.system32)\shell32.dll,22051" />
Aquí se hace referencia a la configuración del acceso directo al bloc de notas que hay en el menú Inicio.
<registryKey keyName="HKEY_CLASSES_ROOT\Applications\notepad.exe\shell\open\command" owner="false">
<registryValue name="" valueType="REG_EXPAND_SZ" value="%SystemRoot%\system32\NOTEPAD.EXE %1" operationHint="replace" owner="true" />
Aquí se hace referencia a una de las claves de Registro gobernadas por Bloc de notas, la correspondiente a las asociaciones de ficheros.
Como puede observar, la integridad del sistema operativo fue uno de los objetivos principales para Microsoft mientras diseñaba Windows Vista. La protección de todos y cada uno de los recursos vitales del sistema operativo mediante Windows Resource Protection (WRP) hacen que Windows Vista y Windows 7 sean sistemas mucho más estables y robustos que sus predecesores.
Si se hiciera un listado con las consultas más frecuentes en los foros de Windows, seguro que esta ocuparía una posición bastante destacada: ¿Por qué no puedo cambiar el atributo de solo lectura a una carpeta de mi sistema?
Pese a que Microsoft dispone de un artículo al respecto (KB326549), considero que mucha gente aún tiene dudas sobre este tema y por eso me he decidido a escribir este artículo.
Si un usuario hace clic con el botón derecho sobre una carpeta de su sistema y selecciona Propiedades, le aparecerá un cuadro de diálogo similar al siguiente (en un sistema XP):

Como puede observar en la imagen, la casilla Sólo lectura tiene un aspecto particular: No está marcada, pues no aparece la típica marca de verificación en el cuadrado blanco, ni tampoco está desmarcada, pues el color del cuadrado no es blanco sino verdoso. ¿Qué significa esto? Esa casilla es una casilla de tipo triestado; es decir, hay tres posibles estados para esa casilla: Marcada, desmarcada e indeterminada, que es el caso que nos ocupa. Si hace clic varias veces sobre la casilla Sólo lectura podrá ver que va cambiando el estado de la misma. Sin embargo, pese a dejar la casilla en estado marcado y pulsar Aceptar, al volver a abrir las propiedades de la carpeta la casilla vuelve al estado indeterminado.
¿Cuál es la causa de esto?
La causa de este comportamiento es que el atributo de sólo lectura no se puede cambiar, para carpetas, desde la interfaz de Windows. Microsoft tomó esta decisión porque el atributo de sólo lectura aplicado a carpetas tiene una semántica que nada tiene que ver con la del atributo de sólo lectura aplicado a ficheros. El atributo de sólo lectura aplicado a carpetas únicamente quiere decir que la carpeta es una carpeta personalizada (con un icono distintivo, con un fondo, etc.).
Debe quedar claro que el atributo de sólo lectura aplicado a una carpeta no quiere decir que la carpeta no se pueda eliminar o cosas por el estilo.
¿Para qué está la casilla Sólo lectura en las propiedades de una carpeta?
Está presente porque puede aplicarse a los ficheros que contenga esa carpeta. Si desmarca la casilla Sólo lectura en las propiedades de una carpeta y pulsa Aceptar, lo que ocurre es que se quita el atributo de sólo lectura a todos los ficheros que contenga esa carpeta, si es que contiene alguno. De igual forma, si establece el estado de la casilla como marcado (con una marca de verificación en el cuadrado blanco) y pulsa Aceptar, todos los ficheros de esa carpeta pasarán a tomar el atributo de sólo lectura.
Entonces, ¿cómo cambiar el atributo de sólo lectura a una carpeta?
Como ha podido ver, Explorador de Windows no permite que el usuario cambie el atributo de sólo lectura a una carpeta. Esto se debe a que Microsoft no quiere que los usuarios "jueguen" con este atributo, lo que podría suponer que se perdieran las personalizaciones de algunas carpetas del equipo, incluidas algunas carpetas de sistema importantes para Windows. Así pues, si un usuario quiere "jugar" con el atributo de sólo lectura aplicado a una carpeta, debe hacerlo desde la línea de comandos usando el comando Attrib.exe de un modo similar al siguiente:
attrib +r <Ruta_carpeta>
Esto aplicaría el atributo de sólo lectura a la carpeta indicada por <Ruta_carpeta>
Similarmente, el comando
attrib -r <Ruta_carpeta>
desactivaría este atributo.
Espero que este artículo sirva para aclarar de manera definitiva en qué consiste exactamente el atributo de sólo lectura cuando se aplica a una carpeta, por qué Explorador de Windows siempre muestra la casilla correspondiente como indeterminada, y qué ocurre cuando el usuario deja esa casilla en estado marcado o en estado desmarcado y pulsa sobre Aceptar.
En la primera parte de esta serie de artículos aprendió a instalar Windbg y a configurar un aspecto básico, los símbolos de depuración. En este artículo veremos cómo configurar otros aspectos menores de Windbg, pero que le pueden resultar necesarios, y depuraremos la primera aplicación en modo usuario.
Configurar la ruta de código fuente
Si está depurando una aplicación que no haya desarrollado, es probable que no disponga del código fuente de la misma; sin embargo, si estuviera depurando una aplicación de la que dispone el código fuente, es muy buena idea configurar Windbg para que sea capaz de usar toda esa información y mostrar la ejecución paso a paso en formato de instrucciones de código fuente, no instrucciones máquina. Para configurar este aspecto, despliegue el menú File, Source File Path (o pulse Ctrl+P). También puede usar el comando .srcpath <Ruta_código_fuente>
Para que el depurador muestre instrucciones de código fuente y no instrucciones máquina es necesario además que los símbolos de depuración contengan información acerca del fichero fuente y número de línea que se corresponde con un determinado símbolo. Estos símbolos, denominados normalmente símbolos privados, no suelen estar a disposición de los usuarios ajenos a la empresa creadora del software en cuestión.
Configurar la ruta de los módulos
En la mayoría de ocasiones, Windbg es capaz por sí solo de encontrar las imágenes de los ejecutables implicados en una sesión de depuración. En determinados casos, como por ejemplo cuando se está depurando un volcado de memoria pequeño o minidump (la depuración de volcados de memoria se tratará en un posterior artículo), es necesario indicarle al depurador dónde debe buscar los módulos (.exe, .dll, .sys, etc.). Para ello, abra File, Image File Path (o pulse Ctrl+I). Como siempre, si desea lograr esto mediante un comando de Windbg, ejecute .exepath <Ruta_ejecutables>
Ejecutar una aplicación dentro del depurador
Ya está en condiciones de depurar su primera aplicación en Windbg y para ello vamos a ejecutar la calculadora de Windows dentro de Windbg.
Abra File, Open Executable (o pulse Ctrl+E) y busque el ejecutable Calc.exe dentro del directorio \Windows\system32\. En este caso deje desmarcada la casilla Debug child processes also, que sirve para depurar no solo el proceso principal que cree ese ejecutable sino sus procesos hijos también. Haga clic sobre Abrir.
La pantalla de Windbg se rellenará con un texto similar al siguiente:
Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: C:\WINDOWS\system32\calc.exe
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 01000000 0101f000 calc.exe
ModLoad: 7c910000 7c9c5000 ntdll.dll
ModLoad: 7c800000 7c903000 C:\WINDOWS\system32\kernel32.dll
ModLoad: 7e6a0000 7eec1000 C:\WINDOWS\system32\SHELL32.dll
ModLoad: 77da0000 77e4c000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e50000 77ee2000 C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fc0000 77fd1000 C:\WINDOWS\system32\Secur32.dll
ModLoad: 77ef0000 77f39000 C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e390000 7e421000 C:\WINDOWS\system32\USER32.dll
ModLoad: 77be0000 77c38000 C:\WINDOWS\system32\msvcrt.dll
ModLoad: 77f40000 77fb6000 C:\WINDOWS\system32\SHLWAPI.dll
(23c.24c): Break instruction exception - code 80000003 (first chance)
eax=001a1eb4 ebx=7ffdb000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c91120e esp=0007fb20 ebp=0007fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c91120e cc int 3
Analicemos detalladamente toda esta información:
La línea CommandLine nos está indicando el archivo que vamos a ejecutar dentro de Windbg, en este caso la calculadora de Windows. A continuación se muestra la ruta establecida para los símbolos y la ruta de búsqueda de módulos ejecutables, que en este caso está vacía porque no la hemos establecido desde la opción File, Image File Path. Seguidamente el depurador ha registrado información sobre la carga de una serie de módulos de los que depende la calculadora de Windows. Para ver las dependencias de un módulo yo recomiendo usar la herramienta Dependency Walker (http://www.dependencywalker.com/).
La siguiente línea, (23c.24c): Break instruction exception - code 80000003 (first chance), da pie a comentar bastantes cosas:
La sintaxis (23c.24c) la va a encontrar no pocas veces en Windbg. Hace referencia a un hilo dentro de un proceso. 23c es el identificador de proceso (PID), en formato hexadecimal. En este caso es el PID del proceso Calc.exe. 24c hace referencia al identificador de hilo (TID), en formato hexadecimal también. La excepción recibida en este caso es "Break instruction" (STATUS_BREAKPOINT), identificada por el código hexadecimal 0x80000003. Vamos a ver qué ocurre "por lo bajo" para explicar por qué ha ocurrido esto:
Cuando hemos seleccionado el ejecutable Calc.exe y hemos hecho clic sobre Abrir, Windbg ha llamado a la API CreateProcess con el sexto parámetro establecido a DEBUG_PROCESS. Esto permite crear un proceso e indicarle a Windows que deseamos depurarlo. Pero depurar un proceso requiere de algo más. Requiere que el programa depurador reciba una serie de eventos procedentes de la ejecución de la aplicación y los muestre al usuario o los trate de manera conveniente. Lo que ocurre durante una sesión de depuración se puede entender como un bucle en el cual el depurador espera eventos de depuración mediante la API WaitForDebugEvent, los trata de manera conveniente, y continua la ejecución del programa mediante la API ContinueDebugEvent. Este bucle se repite indefinidamente hasta que o bien la aplicación que está siendo depurada desaparece de la memoria, o bien finaliza correctamente su ejecución, o bien desacoplamos el depurador mediante el comando Debug, Detach Debugee.
La frase (first chance) hace referencia al comportamiento de las excepciones. Cuando una aplicación genera una excepción y está siendo depurada, el depurador recibe una excepción de primera oportunidad (first chance) y le da la opción de tratarla. En este caso, el depurador trata la excepción STATUS_BREAKPOINT deteniendo la ejecución de la aplicación permitiendo que el usuario introduzca comandos o examine el estado de la imagen de memoria del proceso y el estado del procesador. Si el depurador no capturase la excepción, se comprueba si el código de la aplicación la capturara. Este procedimiento implica verificar en la pila de ejecución si hay algún código manejador de excepciones, desde el marco de activación más reciente hasta al más antiguo. Este procedimiento recibe técnicamente el nombre de stack unwinding. No se preocupe, en posteriores artículos se va a tratar la estructura de datos conocida como pila, pues es de capital importancia a la hora de entender buena parte de la información que nos proporcione Windbg. En caso de que el código no capturase la excepción, se lanza al depurador una excepción de segunda oportunidad (second chance) y se vuelve a comprobar si el código captura la excepción.
Lo que aparece a continuación en la pantalla de Windbg es el estado de los registros del procesador. Para entender esta parte de la salida es necesario disponer de ciertos conocimientos específicos de la máquina que está siendo depurada. En este caso se trata de la arquitectura x86, por lo que la referencia obligada es este documento: http://download.intel.com/design/PentiumII/manuals/24319102.PDF. Cuando veamos algunos casos de estudio verá cómo aplicar la información sobre los registros de la máquina a un caso real.
Para finalizar nos aparece la última instrucción ejecutada en el procesador antes de que se pasara el control al depurador. En este caso se trata de una instrucción dentro de la función DbgBreakPoint dentro del módulo Ntdll.dll. La instrucción en cuestión es la instrucción int 3, identificada mediante el código hexadecimal CC. Esta instrucción lanza una interrupción software. El parámetro 3 indica que ejecutaremos la posición 3 del vector de interrupciones y básicamente se enviará la excepción STATUS_BREAKPOINT al depurador, para que haga con ella lo que considere oportuno. La dirección de memoria que contiene esa instrucción es la 7c91120e (en este ejemplo particular).
Para concluir, puede configurar Windbg para que no informe de ciertos eventos (tales como la finalización de un proceso, la carga de una DLL, etc.). Para ello puede ir al menú Debug, Event Filters.

Si desea hacer uso de la línea de comandos de Windbg, el comando en cuestión es sx y sus derivados sxe, sxd, sxi, sxn. En la documentación de Windbg (Help, About) puede obtener información adicional sobre el uso de estos comandos.
En este artículo hemos aprendido a configurar Windbg para comenzar una sesión de depuración y hemos ejecutado nuestra primera aplicación dentro del depurador. También hemos aprendido qué quiere decir la información que aparece en pantalla y en qué consiste "por lo bajo" la depuración de aplicaciones y el manejo de excepciones. En la siguiente parte veremos algunos comandos para examinar el estado de la máquina y del proceso que está siendo depurado. Se detallarán también algunos aspectos de la arquitectura interna de Windows que son importantes para saber realmente lo que está pasando.
Un problema que le ocurre a no poca gente que usa Windows XP consiste en que al intentar abrir un fichero con extensión MSC (Services.msc, Diskmgmt.msc, etc.) el sistema muestra el siguiente mensaje de error:
MMC no puede abrir el archivo C:\WINDOWS\system32\services.msc.
Puede ser que el archivo no exista, no sea una consola de MMC o fue creado por una versión más reciente de MMC. También puede ser que no tiene suficientes derechos de acceso para abrir el archivo.
El propio mensaje nos explica las posibles causas del problema, pero ciertamente la información que ofrece es algo vaga e inespecífica. El principal problema con el que se encuentra el usuario al recibir este mensaje de error es que, al tratarse de un mensaje de error genérico, es posible que la causa del problema que está experimentando no quede recogida en el texto del mensaje de error.
¿Cómo actuar en casos como este?
Hay muchas formas de actuar ante un mensaje de error de este estilo. Una manera consiste en observar si hay algún tipo de LOG que registre información detallada sobre el error (lo primero que debemos buscar es el código de error exacto). Es bastante probable que, de existir la posibilidad de registrar en un fichero LOG la información correspondiente a un mensaje de error, esta opción deba activarse explícitamente a través del registro del sistema operativo, o mediante algún otro método avanzado similar. En ocasiones, como último recurso para obtener información detallada sobre un mensaje de error tendremos que instalar una versión de depuración del sistema operativo o aplicación (versión checked). Las versiones checked son versiones que incorporan información detallada de depuración (trazas, aserciones, etc.) que son de mucha utilidad a los programadores de aplicaciones. De hecho, para adquirir la versión checked de un sistema operativo de Microsoft debe ser suscriptor de MSDN. Las versiones de depuración de los Service Packs sí están disponibles públicamente desde el Centro de descargas de Microsoft. Por ejemplo, este es el enlace para descargar la versión de depuración del SP3 de Windows XP.
En este artículo se va a describir un método menos complicado que puede sacarnos del atolladero en bastantes casos. De hecho, nos va a sacar del atolladero en el problema concreto que se describe más arriba.
En primer lugar, instale la última versión de Debugging Tools for Windows y configure el depurador Windbg apropiadamente. Para saber cómo hacer esto, siga los pasos de este tutorial.
A continuación, vamos a ejecutar la aplicación desde dentro del depurador. Para ello, haga clic sobre File, Open Executable. En la caja de texto Nombre, escriba lo siguiente: %SystemRoot%\system32\mmc.exe En la caja de texto Arguments, escriba lo siguiente: Services.msc (o el nombre del fichero MSC que no es capaz de abrir). Pulse Abrir.
Asegúrese de que Windbg le informe de que la información sobre los símbolos es correcta y pulse F5 (Go).
Cuando se muestre el mensaje de error en pantalla, active la ventana de Windbg y pulse Ctrl+Pausa o haga clic sobre Debug, Break.
Ahora tendrá que examinar la pila de ejecución de todos y cada uno de los hilos activos de la aplicación para ver si encuentra el código de error como parámetro de alguna de las funciones que allí aparezcan. Para cambiar de hilo, puede hacerlo gráficamente desde el menú View, Processes and Threads. Seleccione con un simple clic el hilo que quiera examinar (quedará marcado en negrita) e introduzca en la caja de texto de Windbg el comando kb para mostrar la pila de ejecución. En mi caso, esta es la pila de ejecución del hilo responsable de abrir el fichero MSC:
0:000> kb
ChildEBP RetAddr Args to Child
0007f030 7c91df4a 7c809590 00000002 0007f05c ntdll!KiFastSystemCallRet
0007f034 7c809590 00000002 0007f05c 00000001 ntdll!ZwWaitForMultipleObjects+0xc
0007f0d0 7e3995f9 00000002 0007f0f8 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
0007f12c 6c6d4b52 00000001 0007f160 ffffffff USER32!RealMsgWaitForMultipleObjectsEx+0x13e
0007f14c 6c6d4cbd 000024ff ffffffff 00000000 DUSER!CoreSC::Wait+0x3a
0007f170 6c6d4eb9 000024ff 00000000 0007f19c DUSER!CoreSC::WaitMessage+0x40
0007f180 7e3d8e33 000024ff 00000000 00000064 DUSER!MphWaitMessageEx+0x22
0007f19c 7c91e473 0007f1ac 00000008 000024ff USER32!__ClientWaitMessageExMPH+0x1e
0007f1b0 7e399418 7e3a770a 00000000 00000000 ntdll!KiUserCallbackDispatcher+0x13
0007f1e8 7e3a49c4 000301b4 00000000 00000001 USER32!NtUserWaitMessage+0xc
0007f210 7e3ba956 7e390000 000c44f8 00000000 USER32!InternalDialogBox+0xd0
0007f4d0 7e3ba2bc 0007f62c 00000001 00000000 USER32!SoftModalMessageBox+0x938
0007f620 7e3e63fd 0007f62c 00000028 00000000 USER32!MessageBoxWorker+0x2ba
0007f678 7e3d0853 00000000 00e76008 00bafeb0 USER32!MessageBoxTimeoutW+0x7a
0007f698 7e3e6579 00000000 00e76008 00bafeb0 USER32!MessageBoxExW+0x1b
0007f6b4 4754f5fe 00000000 00e76008 00bafeb0 USER32!MessageBoxW+0x45
0007f6f0 0107a216 00e76008 00002010 00e86458 mmcbase!MMCErrorBox+0x7f
0007f740 01058ce9 00000003 80040154 00000000 mmc!DisplayFileOpenError+0x191
0007f794 0104093c 0007f748 00000004 00e6e018 mmc!CAMCDoc::OnOpenDocument+0x90
0007f7e0 5f81424a 0007fc14 00000001 00038988 mmc!CAMCMultiDocTemplate::OpenDocumentFile+0x21f
Marcada en negrita está la parte importante de la traza, el error en cuestión (0x80040154). ¿Qué quiere decir ese código de error? El propio Windbg nos lo puede decir:
0:001> !error 80040154
Error code: (HRESULT) 0x80040154 (2147746132) - Clase no registrada
Un error de clase no registrada. Para sabér qué clase es la afectada, puede usar Process Monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx), monitorizar el sistema mientras intenta volver a abrir el archivo MSC y analizar con calma los resultados NOT FOUND que hagan referencia al Registro del sistema, o bien puede seguir las pautas de este artículo referido a Explorer.exe.
Para no hacerle perder el tiempo, le diré que en este caso la clase afectada está en la librería Msxml3.dll y se puede volver a registrar con el comando regsvr32 msxml3.dll.
Otro código de error que se puede encontrar es el código 0x2 (archivo no encontrado). En este caso lo ideal es hacer uso de Process Monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx), monitorizar el sistema mientras intenta volver a abrir el archivo MSC y analizar con calma los resultados NOT FOUND que hagan referencia, en esta ocasión, al sistema de archivos. Un caso que he analizado tenía como culpable al virus Vundo, aunque en general podría tratarse de cualquier otro tipo de malware.
Una duda que quizá tenga es, ¿cómo distinguir en la salida del comando kb lo que es un código de error de lo que no? En general yo suelo descartar en primer lugar lo que seguro sé que no es un código de error. Por ejemplo, en la traza de pila del ejemplo puede ver que 7e3a770a es un valor que está cerca de las direcciones de retorno de cada una de las funciones, por lo que probablemente no sea un código de error. Los valores 00bafeb0 y similares, es decir, un número hexadecimal no muy alto, suelen ser punteros a estructuras de datos, por lo que tampoco suelen ser códigos de error. Los valores muy bajos (00000002), o que comiencen por 8 (80040154), sí suelen ser códigos de error. Por supuesto, en este caso el nombre de la función mmc!DisplayFileOpenError+0x191, nos da la pista fundamental.
Espero que este artículo les ayude a investigar a fondo los mensajes de error en Windows en los que no aparece de manera explícita el código de error. En futuros artículos verá cómo atacar un problema similar pero esta vez causado por una excepción de aplicación, o bien por una versión incompatible de una DLL en el sistema, usando para ello la aplicación Dependency Walker.
He añadido a mi página web un artículo que explica lo que ocurre cuando se ejecuta el comando Explorer.exe tanto sin parámetros como con parámetros, en sistemas XP y Vista. Se incluye toda la casuística, lista completa de parámetros soportados, cómo forzar la creación de un nuevo proceso, etc. El artículo lo puede leer en la dirección http://winvista.mvps.org/Tema.aspx?ID=233
Cualquier duda o sugerencia la puede hacer llegar a través de la sección de comentarios de esta entrada o mediante el enlace Contact de la parte izquierda del blog.
A petición de un buen número de personas que me han escrito a través del blog, he decidido comenzar un tutorial sobre depuración de aplicaciones y el sistema operativo Windows usando Windbg. A través de este tutorial espero cubrir conceptos introductorios (tales como aprender a configurar Windbg, saber qué comandos son los más destacados y para qué sirven, etc.), hasta llegar a conceptos más avanzados que impliquen la aplicación de la teoría al análisis y solución de problemas reales. Se van a tratar tanto la depuración de volcados de memoria (algo que se conoce como postmortem debugging), como la depuración de sistemas en vivo (live debugging). Al final del tutorial espero que tenga la información apropiada para abordar un problema en su máquina ejecutando algo más que el clásico comando de Windbg "analyze -v".
¿Qué es un depurador y qué tipos de depuradores hay?
El concepto de depuración en el ámbito de la computación podría describirse como un procedimiento metódico consistente en el análisis y corrección de los defectos de un sistema software o hardware. Esta sencilla descripción representa una tarea ardua y dificultosa en sí misma dada la alta complejidad de cualquier sistema computacional de hoy en día. Para poder llevarla a cabo, los ingenieros se sirven de unos programas denominados depuradores (en inglés, debuggers) que permiten, entre otras cosas, analizar un volcado de memoria, adjuntarse a un proceso (más adelante veremos en qué consiste esto exactamente), ejecutar un programa y examinar el estado de la máquina (registros, memoria, procesos en ejecución, etc.), ejecutar paso a paso una aplicación, parar la ejecución según una cierta condición, etc.
Los depuradores pueden clasificarse en dos grupos bien diferenciados:
- Depuradores en modo usuario: Este tipo de depuradores son capaces de mostrar el estado de un proceso en un determinado momento (hilos en ejecución, registros de la máquina, contenido de la memoria, etc.), es decir, el depurador tiene exactamente la misma visión de la máquina que tendría cada uno de los procesos que se estén ejecutando.
- Depuradores en modo núcleo: Este tipo de depuradores disponen de una visión completa de la máquina sobre la que se están ejecutando. Suelen utilizarse para detectar errores en controladores de sistema, pero en ciertos casos es necesario recurrir a un depurador en modo núcleo para depurar una aplicación que funcione en modo usuario.
¿Qué es Windbg?
Windbg es un completo depurador de Microsoft, tanto en modo usuario como en modo núcleo, con una intuitiva interfaz gráfica y descargable de forma gratuita desde la página http://www.microsoft.com/whdc/devtools/debugging/default.mspx. El paquete Debugging Tools for Windows incorpora un buen número de depuradores y utilidades relacionadas, y aunque este tutorial solo se vaya a centrar en el depurador gráfico Windbg mi recomendación personal es que se instale el paquete completo de Debugging Tools for Windows.
Una vez finalizada la instalación, podemos ejecutar Windbg desde Inicio, Todos los programas, Debugging Tools for Windows (x86)/(x64), Windbg. La pantalla principal tendrá un aspecto similar al de la siguiente imagen:

Lo primero que se debe hacer es configurar el depurador. El aspecto de configuración más importante de Windbg es quizá la información referente a los símbolos del código del programa que vayamos a depurar. Antes de proseguir, vamos a describir lo que es un símbolo:
Durante la fase de construcción de un fichero ejecutable a partir de su código fuente, se genera información referente a las funciones, variables, estructuras de datos, etc. usadas en dicho código. Dependiendo de los intereses del programador, esta información puede acabar embebida en el propio ejecutable o bien proporcionarse de manera separada en la forma de ficheros con extensión .pbd (si se ha usado algún compilador de Microsoft). Embeber dicha información en el ejecutable tiene como consecuencia que su tamaño se vea incrementado de manera considerable, además por información que solo es de utilidad para programadores o profesionales de soporte. Por lo tanto, la gran mayoría de compañías de software proporcionan los símbolos para la depuración de manera separada. Sin embargo, es muy probable que existan multitud de versiones de una determinada DLL o ejecutable, en cuyo caso, ¿cómo sabe el depurador qué símbolos escoger? La primera alternativa supondría indicar individualmente la ruta que apunte a los símbolos de cada una de estas versiones, algo inviable. Para dar solución a este y otros problemas, se ideó el concepto de servidor de símbolos, una máquina cuyo cometido es proporcionar los símbolos de depuración conforme el depurador los vaya necesitando. Y lo que es más importante, el servidor de símbolos mantiene una lista de símbolos indizada por nombre, tamaño, versión o cualquier otro parámetro, por lo que es capaz de ofrecer la versión apropiada de un símbolo de manera cómoda y rápida.
¿Cómo configurar la información referente a los símbolos de depuración en Windbg?
Hay que precisar que si se configura Windbg para que consiga los símbolos de depuración desde un servidor de símbolos, es necesario que el sistema tenga conexión a Internet durante todo el periodo que dure la depuración. Si esto no fuera posible, existe la alternativa de descargarse un paquete de símbolos acorde con la versión del sistema operativo que está siendo depurado desde una web de Microsoft, http://www.microsoft.com/whdc/devtools/debugging/symbolpkg.mspx#d. Sin embargo, esta opción tiene el inconveniente de que los símbolos suelen estar actualizados solo hasta el Service Pack más reciente que haya salido. Si Windows Update hubiera actualizado algún ejecutable o DLL con motivo de una actualización de seguridad, por ejemplo, es posible que el depurador no disponga de la información simbólica pertinente. En particular, si faltan los símbolos de Ntoskrnl.exe (depuración en modo núcleo) o bien Ntdll.dll, Shell32.dll o alguna otra DLL muy usada del sistema operativo (depuración en modo usuario), el análisis que hagamos no servirá para nada. Es, por tanto, muy importante que configuremos correctamente la información simbólica en Windbg.
Para configurar Windbg para que acceda al servidor de símbolos de Microsoft se pueden seguir estos pasos:
- Abrir el menú File, Symbol File Path (o pulsar Ctrl+S).
- Introducir en la caja de texto Symbol path lo siguiente:
SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
- Pulsar OK.

Téngase en cuenta que se ha configurado como carpeta de descarga de los símbolos la carpeta C:\websymbols, pero se podría indicar cualquier otra. A continuación podemos salvaguardar la configuración que hemos realizado para que no se pierda en sucesivas depuraciones haciendo clic sobre el menú File, Save Workspace (o Save Workspace As).
Si estamos en una sesión de depuración (algo que se describirá en un posterior artículo), podemos usar comandos para configurar los símbolos adecuadamente:
.sympath
Este comando muestra la ruta que esté configurada para el servidor de símbolos.
.sympath <Ruta>
Este comando establece la ruta <Ruta> como ruta del servidor de símbolos.
.sympath+ <Ruta>
Este comando es similar al anterior pero respeta cualquier otra ruta de servidor de símbolos que pueda haber configurada con anterioridad.
.symfix <Carpeta>
Este comando nos evita tener que aprender de memoria la dirección del servidor de símbolos de Microsoft. Tan solo tenemos que indicarle la carpeta en la que queremos que se descarguen los símbolos.
.symfix+ <Carpeta>
Este comando es similar al anterior pero respeta cualquier otra ruta de servidor de símbolos que pueda haber configurada con anterioridad.
Ya hemos configurado uno de los aspectos más importantes de Windbg, la información simbólica de depuración. En el siguiente artículo veremos otros aspectos menores de configuración del depurador y aprenderemos a depurar una aplicación o proceso en modo usuario.
Cuando lea estas líneas es probable que ya pueda descargar la versión final de Internet Explorer 8 desde su web oficial: http://www.microsoft.com/windows/internet-explorer/download-ie.aspx.
Una de las dudas que creo que mucha gente tendrá es sobre cómo integrar Internet Explorer en el DVD de Windows Vista/Windows Server 2008. Al integrarlo, cuando instale Windows Vista/Windows Server 2008 automáticamente ya tendrá instalada la versión 8 del navegador de Microsoft, con la comodidad que esto supone. Los pasos a seguir están disponibles en el blog oficial de IE (http://blogs.msdn.com/ie/archive/2008/06/20/slipstreaming-ie8.aspx), lo que sigue es una mera traducción de dicho contenido, con ligeras modificaciones para adaptarlo al idioma español.
Preparación
- Instalar el kit de instalación automática de Windows (WAIK)
El kit de instalación automática de Windows (WAIK) es una herramienta disponible para Vista y Windows Server 2008 que administra y personaliza las imágenes del sistema operativo. Esta es la herramienta que va a usar para integrar IE8. Descargue una versión de WAIK que concuerde con la configuración de su máquina local (no la imagen en la que va a integrar IE8).
Nota: No es posible usar una versión de 64 bits de WAIK para integrar IE sobre una imagen de Vista de 32 bits. Para más información, lea el fichero Readme.txt del WAIK.
- Crear el directorio de Windows Vista
Cree en el sitio que quiera una carpeta de nombre Slipstream y, dentro de ella, un directorio VistaSP1x86es. Copie el contenido del DVD de Windows Vista en el directorio VistaSP1x86es.
- Crear tres carpetas temporales: Mount, Pkg, Sandbox
Cree en la raíz del directorio Slipstream tres carpetas: Mount, Pkg y Sandbox.
- Descargar Internet Explorer 8
Cree en el directorio Slipstream la carpeta IE8x86es y descargue en ese directorio Internet Explorer 8.
- Extraer y expandir el archivo MSU
Abra una ventana de línea de comandos (Cmd.exe) y teclee este comando: <ruta del instalador de IE8> /x: <carpeta donde quiera alojar el fichero MSU>. Por ejemplo: C:\Slipstreaming\IE8x86es\IE8-WindowsVista-x86-esn.exe /x: C:\Slipstreaming\IE8x86es
Para extraer el fichero MSU, desde la ventana de línea de comandos teclee lo siguiente: expand.exe <ruta del fichero MSU de IE8> -F:* <carpeta Pkg>. Por ejemplo: expand.exe C:\Slipstreaming\IE8x86es\IE8.MSU -F:* C:\Slipstreaming\Pkg
Integración
- Montar la imagen de instalación de Vista en el directorio temporal
En la ventana de línea de comandos, ejecute lo siguiente: imagex.exe /mountrw install.wim <número_de_imagen> <carpeta Mount>
Para este ejemplo estoy integrando IE8 en un Windows Vista Ultimate que tiene como número_de_imagen = 4. El comando que ejecuté fue "C:\Archivos de programa\Windows AIK\Tools\x86\imagex.exe" /mountrw C:\Slipstreaming\VistaSP1x86es\sources\install.wim 4 C:\Slipstreaming\Mount
Si no sabe cuál es el número de imagen de su sistema operativo, puede usar un número grande al azar en lugar del 4 del comando anterior, tal que así: imagex.exe /dir C:\VistaRTM\sources\install.wim 20. Esto hace que se muestre la información de ayuda. Busque la versión de Vista/Server 2008 que esté usando y el valor IMAGE INDEX será el valor del parámetro número_de_imagen que está buscando.
- Integrar IE8 en la imagen de Vista
Si está usando la versión Gold de Windows Vista (es decir, sin ningún Service Pack instalado), es necesario que cambie el atributo de solo lectura de un fichero antes de ejecutar el comando de integración: attrib -R "<Carpeta Mount>\Windows\Offline Web Pages"
Por ejemplo: attrib -R "C:\Slipstreaming\Mount\Windows\Offline Web Pages"
Ahora ya está listo para integrar IE8. Ejecute lo siguiente en la ventana de línea de comandos: pkgmgr.exe /n:<Carpeta Pkg>\WindowsVista-KB#-NEUTRAL.xml /o:"<Carpeta Mount>;<Carpeta Mount>\windows" /s:<Sandbox> /l:<Sitio donde quiera que se genere el fichero de LOG>. Asegúrese de que el ejecutable Pkgmgr.exe que utilice sea el incluido en el WAIK.
Por ejemplo: "C:\Archivos de programa\Windows AIK\Tools\x86\Servicing\pkgmgr.exe" /n:"C:\Slipstreaming\Pkg\Windows6.0-KB944036-x86.xml" /o:""C:\Slipstreaming\Mount";"C:\Slipstreaming\Mount\windows"" /s:"C:\Slipstreaming\Sandbox" /l:"C:\Slipstreaming\Slp.log"
Una vez que el comando de integración finalice correctamente, el fichero Slp.log contendrá la línea "exit code 0x00".
Recuerde establecer de nuevo el atributo de solo lectura una vez que haya finalizado la integración (solo si usa Windows Vista Gold, es decir, sin ningún Service Pack instalado): attrib +R "<Carpeta Mount>\Windows\Offline Web Pages"
Por ejemplo: attrib +R "C:\Slipstreaming\Mount\Windows\Offline Web Pages"
- Guardar los cambios
Use Imagex.exe para guardar los cambios: imagex /commit /unmount <Carpeta Mount>
Para este ejemplo: "C:\Archivos de programa\Windows AIK\Tools\x86\imagex.exe" /commit /unmount c:\Slipstreaming\Mount
Y con esto ya habrá integrado IE8 en su imagen de Windows Vista. Ya solo tiene que crear un DVD con dicho contenido. Como IE8 es parte de la imagen de Vista, puede personalizarlo creando un fichero Answer.xml y ejecutando el programa de instalación de Vista con la opción desatendida, tal como: <Carpeta Vista>\setup.exe /unattend:<Carpeta del fichero Answer.xml>
Enlaces relacionados:
http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=728ab2c8-8000-4888-8f62-340223d01fe0
En este artículo se va a describir el arranque de los sistemas operativos Windows Vista y Windows 7. Antes de comenzar, es necesario que veamos unas pinceladas del arranque de sistemas operativos anteriores, para poner el nuevo sistema de arranque en contexto.
El proceso de arranque en Windows XP y anteriores
El proceso de arranque comienza cuando la BIOS de la máquina lee el primer sector del disco duro. Este sector (el sector de arranque), típicamente contiene una porción de código denominada MBR (Master Boot Record), pero podría contener cualquier otro código ejecutable. En sistemas Windows XP y anteriores sistemas NT, dicho código apunta al fichero Ntldr mediante una cadena de tipo Unicode situada en una posición fija de dicho primer sector del disco duro. El archivo Ntldr es el encargado de leer el fichero Boot.ini, que contiene información importante sobre los sistemas que están instalados y cómo se debe arrancar cada uno de ellos. Si procede, Ntldr muestra al usuario una lista de sistemas operativos para que elija alguno mediante las flechas de dirección.
La nueva arquitectura de arranque
El problema principal de este esquema primitivo de arranque es que se trata de un esquema enormemente dependiente del hardware. Este problema se hizo patente cuando Intel desarrolló, a mediados de los años 90, una nueva especificación para sus máquinas Itanium, con el objetivo de evitar las limitaciones impuestas por el ya vetusto sistema PC BIOS. Esta especificación se denominó EFI (Extended Firmware Interface) y básicamente consiste en una interfaz entre el sistema operativo y el firmware de la máquina. EFI soporta tanto el esquema clásico de particiones basado en MBR como el nuevo esquema GPT (Guid Partition Table). La principal ventaja de este nuevo esquema es que no se ve afectado por las limitaciones de MBR, tales como el límite de 4 particiones primarias por disco y los 2TB como máximo por partición.
Con la salida al mercado de Windows Vista, Microsoft introdujo un nuevo almacén de configuración de arranque denominado almacén BCD (Boot Configuration Data). Podríamos decir que este almacén realiza las mismas funciones que el fichero Boot.ini realiza en sistemas Windows XP o anteriores. La diferencia fundamental reside en que el almacén BCD es independiente del hardware y es capaz de arrancar tanto sistemas PC BIOS tradicionales como sistemas basados en EFI. En el futuro podría darse soporte a nuevos esquemas de arranque.
La arquitectura del BCD está formada por tres componentes bien diferenciados: almacén BCD, objeto BCD y elemento BCD.
Almacén BCD
El almacén BCD es un contenedor de objetos BCD, entidad que a su vez contiene elementos BCD. Físicamente es un fichero binario con una estructura similar a los ficheros binarios que representan ramas del Registro del sistema. Su nombre es BCD y está situado en el directorio \Boot (en un sistema PC BIOS) o \EFI\Microsoft\Boot (en un sistema EFI) de la partición activa del disco.
Objetos BCD
Por defecto, el almacén BCD contiene los siguientes objetos BCD:
- Administrador de arranque de Windows: Este objeto contiene entradas correspondientes a cada uno de los sistemas operativos instalados en la máquina. También existen parámetros adicionales, tales como el tiempo de espera hasta que se seleccione la entrada por defecto de dicho menú o la ordenación de la lista de sistemas operativos. Podríamos decir que este objeto BCD reemplaza la funcionalidad de la porción [boot loader] del fichero Boot.ini.
- Cargador de arranque de Windows: Existe un objeto BCD de este tipo por cada sistema Windows Vista/Windows 7 que esté instalado en el equipo. Se podría decir que este objeto reemplaza la funcionalidad de la sección [operating systems] del fichero Boot.ini.
- Ntldr: Este objeto BCD es opcional y contiene la información necesaria para arrancar sistemas Windows XP o anteriores. Nótese que el fichero Ntldr no sirve para nada en Windows Vista/Windows 7, excepto para arrancar sistemas anteriores.
Además de estos objetos BCD, las aplicaciones pueden crear sus propios objetos utilizando la interfaz de programación del almacén BCD. Por ejemplo, la utilidad de comprobación de memoria RAM incluida en el entorno de recuperación de Windows Vista/Windows 7 programa un análisis de RAM mediante el ejecutable Mdsched.exe, que crea un nuevo objeto BCD que apunta al ejecutable \Boot\Memtest.exe (en sistemas PC BIOS) o \EFI\Microsoft\Boot\Memtest.efi (en sistemas EFI). Otras aplicaciones de terceros podrían crear sus propios objetos en el BCD.
Elementos BCD
Los elementos BCD guardan los parámetros de configuración de cada uno de los objetos BCD. Estos parámetros, como ya se ha comentado, pueden ser la existencia de un depurador de kernel, el sistema operativo que iniciará por defecto, si se han activado las PAE (Physical Address Extensions), etc.
Este diagrama proporciona una visión global de la arquitectura del BCD:

Cada uno de los objetos BCD anteriores enlaza con un ejecutable diferente. Como ya se comentó, el objeto BCD correspondiente al análisis de memoria RAM enlaza con el ejecutable Memtest.exe o Memtest.efi. La entrada correspondiente al arranque de un sistema Windows Vista/Windows 7 enlaza con el ejecutable Winload.exe o Winload.efi, encargado de inicializar el núcleo del sistema operativo mediante Ntoskrnl.exe y cargar algunos controladores de arranque. Si el sistema hibernó por última vez, un objeto BCD apuntará al ejecutable Winresume.exe o Winresume.efi, que es el encargado de reanudar el sistema operativo para dejarlo tal cual estaba antes de ser hibernado.
¿Qué hace la herramienta Reparación de inicio si se encuentra con algún problema?
Si alguna de las estructuras comentadas anteriormente se ha dañado, el sistema no podrá arrancar. La herramienta Reparación del inicio habrá obtenido toda la información mediante su conjunto inicial de pruebas. Si la tabla de particiones, sector de arranque o almacén BCD estuviera dañado, el ejecutable BCDMD (Boot Critical Disk Meta-data Repair) se encarga de regenerar toda esta información. Esta herramienta básicamente realiza un análisis en busca de sistemas operativos, a la vez que compara esta información con la residente en el almacén BCD. Si la información del BCD no fuera coherente, esta herramienta es capaz de modificarla para que lo sea. Si los ficheros Winload.exe o Bootmgr no estuvieran o estuvieran dañados, Reparación de inicio puede recuperarlos en ciertas circunstancias, como ya vimos, mediante el comando Bfsvc.exe /nosetupcheck.
Otro de los problemas que puede afectar al arranque del sistema, como ya vimos, es una corrupción de los ficheros de sistema o bien un problema de permisos sobre ciertos ficheros importantes. Para el primer caso, Reparación del inicio ejecuta el comando Sfc.exe, cuyo funcionamiento se describió en un anterior artículo. Para el segundo caso, la herramienta reconstruye los permisos correctos, teniendo en cuenta que los ficheros del sistema operativo tienen una serie de permisos por defecto, para evitar su accidental eliminación o sobreescritura.
Si el Registro resultara estar corrupto, se puede recuperar a partir de la copia de seguridad del directorio %windir%\system32\config\RegBack. Si dicha copia tampoco estuviera en buen estado, se recurre a la copia con extensión .old que hay en el mismo directorio. Sin embargo, ante una corrupción del Registro la restauración del sistema se intenta aplicar siempre en primer lugar. El motivo es claro, las ramas de Registro del punto de restauración probablemente serán más recientes que las que hay en la carpeta RegBack. Solo se recurre a esta carpeta si no hubiera puntos de restauración disponible o estos no hubieran solucionado el problema.
Haciendo referencia a los puntos de restauración, la herramienta elige el más reciente que sea anterior a la causa que ha producido el fallo. Por ejemplo, si el usuario instaló un controlador y el sistema dejó de iniciar, Reparación del inicio intentará usar el punto de restauración más reciente anterior a la instalación del controlador. Para el caso de un Registro corrupto, la herramienta prueba con el punto de restauración más reciente que haya disponible.
Espero que toda esta información sobre el arranque de Windows Vista/Windows 7 y la herramienta Reparación del inicio les sirva para comprender un poco mejor cómo arranca el sistema operativo, qué estructuras están asociadas al arranque, qué problemas pueden surgir y cómo los aborda la herramienta de Reparación del inicio.
(Esta entrada ha sido programada. Daniel está en estos momentos en Redmond, Washington).
Aunque Internet Explorer no sea algo que conozca en profundidad, últimamente mucha gente me ha estado enviando mensajes indicando que su navegador se bloquea a menudo. He estado analizando por encima el volcado de memoria de un sistema afectado y al parecer el complemento Adobe Flash es el presunto culpable. De hecho, desactivando dicho complemento en IE, desde Herramientas, Administrar complementos, se ha solucionado el 100% de los casos que he tratado. Otra sugerencia que ha resultado útil consiste en desinstalar la versión 10 de Adobe Flash y a continuación instalar la versión 9. Así que si ha llegado a esta página buscando información sobre un cuelgue de Internet Explorer, espero que esta información le resulte útil.
Buscando en la web de Adobe, he visto que se trata de un posible bug que ya está siendo analizado, pero aún no hay solución: http://bugs.adobe.com/jira/browse/FP-1145.
Si conoce alguna web con contenido Flash que haga que el navegador se cuelgue con frecuencia, o si ha logrado obtener unos pasos que reproduzcan el problema de manera consistente, le agradecería que contactara conmigo ya sea a través de la sección de comentarios de esta entrada o a través de la página Contact de la parte izquierda de este blog. Gracias de antemano.
Actualización 25/02/2009: Gracias a todos por la información. El problema ya está solucionado en la nueva versión de Adobe Flash Player que se puede descargar desde http://get.adobe.com/flashplayer.
Ayer a las 12 del mediodía (hora de Redmond), Microsoft anunció cuáles serán las ediciones de su nuevo sistema operativo, Windows 7. En resumen, las dos ediciones más apropiadas para el segmento de consumo serán Windows 7 Home Premium y Windows 7 Professional. Esta última estará orientada a profesionales y pequeñas empresas que utilicen Windows Vista Business y quieran migrar a Windows 7.
El resto de ediciones serán Windows 7 Home Basic, que solo estará disponible en mercados emergentes (Asia, África y Latinoamérica); Windows 7 Starter, disponible en todo el mundo pero limitada su distribución a los OEM; Windows 7 Enterprise, para empresas, y Windows 7 Ultimate, que, como en el caso de Windows Vista, contendrá todas las funcionalidades del sistema operativo. Aún no se sabe nada de los precios de cada una de ellas.
Puede obtener más información en esta entrevista realizada a Mike Ybarra, general manager de Microsoft: http://www.microsoft.com/presspass/features/2009/feb09/02-03Win7SKU-QA.mspx
En la parte primera de esta serie de artículos sobre la herramienta Reparación de inicio de Windows Vista se trató con detalle el conjunto de pruebas iniciales que realiza esta aplicación, así como las conclusiones que extrae en función de los signos experimentados en el sistema. Estas pruebas iniciales se centran principalmente en la primera fase del arranque del sistema operativo, pues lo más normal es que si hay un problema que impida que un equipo se inicie, tenga que ver con el disco en sí, con el MBR, con la tabla de particiones, con el sector de arranque, etc.
A continuación se comentará sobre el resto de comprobaciones que siguen a las pruebas iniciales si estas no han dado con una posible causa.
Pruebas adicionales
Como ya vimos, si el sistema no ha sido capaz de iniciarse y tanto el administrador de arranque como el cargador de arranque de Windows Vista no han reportado ningún error, es de suponer que el problema probablemente esté encuadrado en alguna fase posterior del arranque del sistema operativo. Si se detecta que ha sucedido una pantalla azul (bugcheck), la herramienta trata de realizar un análisis rudimentario del volcado de memoria resultante. Si no es capaz de extraer ninguna conclusión, supone sencillamente que es un controlador mal diseñado el culpable del problema.
En el caso de que no haya sucedido ninguna pantalla azul durante el último intento de arranque, el siguiente conjunto de pruebas tiene como objetivo detectar un posible fallo que anterior a la inicialización del sistema de ficheros. Un fallo de este tipo por lo general tiene que ver con permisos incorrectos sobre ficheros importantes del sistema operativo, o bien con un sistema de archivos corrupto. En el primer caso, lo que se hace es comparar los permisos de los ficheros de los directorios %windir%\system32 y %windir%\system32\drivers con los permisos originales tras una instalación limpia de Windows Vista. Los permisos originales sobre ficheros de sistema en Windows Vista son un tanto peculiares; esto tiene que ver con la característica WRP (Windows Resource Protection), que se tratará en un posterior artículo. La corrupción en el disco se analiza con la conocida herramienta Chkdsk.
Si las pruebas anteriores no sacan nada en claro, Reparación de inicio investiga si el usuario ha instalado alguna actualización o algún controlador tras el último inicio correcto del sistema. Para ello repasa los eventos del Visor de sucesos, físicamente disponible en la ruta %windir%\System32\winevt\Logs. Si se ha instalado un controlador y/o actualización, la herramienta supone automáticamente que es la causa del problema, sin realizar más pruebas.
Y con esto finalizan las pruebas que realiza la herramienta Reparación de inicio en Windows Vista y Windows Server 2008. Si tras todas las comprobaciones no se hubiera dado aún con el culpable, el sistema registra este hecho e intentará una restauración del sistema como último recurso.
En el siguiente artículo de la serie se tratarán los arreglos que realiza la herramienta Reparación de inicio, según el problema que haya detectado. Será un artículo en el que también se explique detalladamente el arranque de Windows Vista, que ha cambiado bastante con respecto a sistemas NT anteriores (XP, 2000, NT).
More Posts
Next page »