Ejecutar un programa antes de que se inicie Windows

Publicado 16/5/2007 17:06 por Rafael Ontivero

Seguro que cualquier usuario de Windows ha visto cómo justo en medio del arranque de su PC, se modifica la pantalla de inicio de forma un tanto extraña y se inicia un chequeo del disco duro. O si utiliza herramientas como el Acronis Disk Director, tras el pertinente reinicio se lanzan en dicho lugar las herramientas, o también con los desfragmentadores comerciales como el Perfect Disk o el Diskeeper.

¿Cómo puede hacer uno eso mediante código para, por ejemplo, forzar un chequeo del disco de sistema sin intervención del usuario? Es decir, si uno intenta lanzar un chkdsk con la opción /f desde una ventana sobre el disco de sistema (aunque sea por programa), chkdsk le dirá que no puede verificar ahora, que si quiere hacerlo en el siguiente reinicio, requiriendo la intervención del usuario.

O quizás estemos haciendo una aplicación de sistemas que requiera acceso a disco antes de que el propio Windows lo bloquee…

La teoría
Justo es que si Windows puede hacerlo, nosotros también. Todo el meollo del asunto está en una clave del registro, situada en

"HKLM\SYSTEM\CurrentControlSet\Control\Session Manager"

llamada

"BootExecute"

y que suele contener un array de cadenas con el texto (en mi caso, que tengo instalado el Perfect Disk)

"PDBoot.exe","autocheck autochk *"

Una inspección a dicha clave tras haber lanzado un chequeo de disco y haber aceptado la opción de reinicio devuelve

"autocheck autochk /p \\??\\C:","PDBoot.exe","autocheck autochk *"

Podemos observar que a lo existente se le ha añadido una nueva línea, justo al principio de todo. Con esto ya tenemos claro cómo funciona todo el asunto: una línea por comando, con la observación de que los programas de aplicación pueden, también, trastear con la clave sin peligro, ya que el software del Perfect Disk así lo hace.

El algoritmo
Para evitar eliminar entradas existentes, se hace necesario en primer lugar leer el contenido de dicha clave, añadir al principio nuestra nueva línea, y después volver a escribir la clave. Opcionalmente nos queda reiniciar, cosa que explicaré cómo hacer en una próxima entrada.

El ejemplo (en C++/CLI)
Esta vez he optado por un ejemplo completo de consola de comandos. Quien quiera probarlo sólo tiene que crearse un proyecto nuevo y sustituir el texto de su fichero principal por el que pongo aquí.

// BootExecute.cpp : main project file.
#include "stdafx.h"
using namespace System;
using namespace Microsoft::Win32;

void BootExecute(String ^nuevoValor)
{
 
//Abrimos la clave con permisos de escritura
  RegistryKey ^key=Registry::LocalMachine->OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager",true);

  //Leemos el valor
  array<String ^> ^values=(array<String ^> ^)key->GetValue("BootExecute",gcnew array<String ^> {"ERROR"});
  array<String ^> ^newValues;

  //Aquí no deberíamos entrar, pero por si acaso...
  if(values->Length==1 && values[0]=="ERROR")
    newValues=gcnew array<String ^>(1) {nuevoValor};
  else
  {
    //Creamos un nuevo array y copiamos los valores antiguos más el nuevo
    newValues=gcnew array<String ^>(values->Length+1);
    newValues[0]=nuevoValor;
    Array::Copy(values,0,newValues,1,values->Length);
  }

  //Escribimos y nos vamos
  key->SetValue("BootExecute",newValues);
  key->Close();
}

int main(array<System::String ^> ^args)
{

  //Lo que vamos a añadir
  String ^nuevoValor="autocheck autochk /p \\??\\C:";

  BootExecute(nuevoValor);

  return 0;
}

El funcionamiento es evidente por sí mismo, aparte de los profusos comentarios que ayudan a entender el programa. Básicamente abrimos la clave del registro, leemos los valores actuales, creamos un nuevo array con el nuevo valor y copiamos el de los valores actuales. Luego escribimos y ya está hecho.

El paso siguiente es explicar cómo reiniciar el sistema operativo, forzando incluso el mismo cierre, lo que requiere hacerlo con código nativo. Todo eso lo explicaré en una próxima entrada.

Archivado en: ,,
Comparte este post:

Comentarios

# re: Ejecutar un programa antes de que se inicie Windows

Wednesday, May 16, 2007 8:58 PM by Peni

Muy muy bueno, esto me lo guardo en el cofre de los tesoros.

Estooooo, no rompe nada, verdad? ;-)

# re: Ejecutar un programa antes de que se inicie Windows

Wednesday, May 16, 2007 9:54 PM by Rafael Ontivero

He hecho pruebas con 3 equipos diferentes aparte del de desarrollo, y no parece romper nada, tanto en XP como el Vista.

En este momento hay 200 máquinas en la calle ejecutando ese código sin problemas bajo XP Embedded (aunque en realidad es una sola, ya que son imágenes replicadas).

Lo que no he probado es con otros comandos, como un cmd.exe o similar, y parece ser que la clave tampoco la borra Windows, así que si añades algo no olvides quitarlo... Mañana pongo otra entrada sobre cómo quitarlo y si tengo tiempo probaré otros comandos.

# Ejecutar un programa antes de que se inicie Windows (y II)

Thursday, May 17, 2007 4:19 PM by .NET o no .NET, esa es la cuestión

En la entrada anterior hablaba sobre cómo lanzar un programa para que se ejecute antes del inicio de

# re: Ejecutar un programa antes de que se inicie Windows

Thursday, May 17, 2007 6:31 PM by Rafael Ontivero

A) Claro que se puede hacer en C# sin problema ninguno. Sólo tienes que traducir directamente, ten en cuenta que no es C++, si no C++/CLI.

B) Sí que se puede, y de hecho tienes un montón de clases para ello en el espacio de nombres System.Diagonstic. Con la clase EventLog, por ejemplo. En http://msdn2.microsoft.com/en-us/library/e6t4tk09(vs.80).aspx tienes más info.

C) En este caso no es necesario, en otros sí. El problema del C# frente al C++/CLI es que con este último tenemos destrucción determinista, algo más de rendimiento y un interop mucho más fácil. Respecto al C++ nativo, está claro que el C# no tiene nada que hacer.

# re: Ejecutar un programa antes de que se inicie Windows

Thursday, September 3, 2009 12:19 PM by Veronica

no m deja iniciar sesion en el windows live msn porque????

# re: Ejecutar un programa antes de que se inicie Windows

Thursday, September 3, 2009 1:06 PM by Rafael Ontivero

Verónica, como habrás podido ver, esto es un tema de programación y no tiene nada que ver con el uso normal de windows.

Pregunta en un foro adecuado.

# re: Ejecutar un programa antes de que se inicie Windows

Wednesday, March 17, 2010 2:14 AM by erick

Podrias, hacerlo en Visual Basic.net?¿¿?

# re: Ejecutar un programa antes de que se inicie Windows

Wednesday, March 17, 2010 10:46 AM by Rafael Ontivero

El programa que instala el programa que se ejecutará antes es trivial hacerlo, como puedes ver. Apenas son unas líneas.

Ni borracho de cocacola en lo que respecta al programa que se ejecutará antes de que Windows termine de arrancar.

Sólo en C/C++ y sin aprovechar todo lo que ofrece Win32.

Ramón Sola tiene un comentario en este blog que explica por qué.

# re: Ejecutar un programa antes de que se inicie Windows

Friday, March 19, 2010 7:53 PM by Argosino

Muy pero que muy buena aportación...

Mañana lo intento en Windows 7 a ver que pasa!!

# re: Ejecutar un programa antes de que se inicie Windows

Thursday, May 6, 2010 11:15 PM by Rey

Me haria falta esto pero bien masticado en C#

# re: Ejecutar un programa antes de que se inicie Windows

Friday, May 7, 2010 9:22 AM by Rafael Ontivero

Eso no se puede hacer en C# de ninguna forma posible.