Muchas veces creamos programas que manejan archivos para guardar nuestra información. El gran problema es que cada vez que corremos nuestro programa y queremos abrir un archivo tenemos que buscarlo en el disco duro. La pregunta que me hago es:
¿Por qué al hacer doble clic en mi archivo, que tiene una extensión propia, no se ejecuta mi programa?
Para explicarme un poco más te presento la imagen de cómo se ve en Windows mi archivo de datos que tiene la extensión .copstone contra la de un archivo de c++ que tiene la extensión .cpp.
Como puedes ver en la imagen, el archivo de C++ que está registrado tiene tres características que mi archivo de Copstone no tiene:
- Tiene un ícono que corresponde a la extensión.
- Tiene una descripción del tipo de archivo “C++ Source”
- Al hacerle doble clic se abrirá el Visual Studio o Code Gear dependiendo de cómo esté configurado mi sistema.
En este artículo te voy a enseñar como registrar la extensión de tu archivo para que se vea así:
Como puedes ver, ahora mi archivo con extensión .copstone ya tiene:
- Su propio ícono
- Tiene una descripción del tipo de archivo “Archivo de datos de copstone”
- Al hacer doble clic se abrirá mi programa y recibirá el nombre del archivo al que le hice clic.
Asociando la extensión
Para asociar una extensión, no es necesario tener ningún conocimiento de programación ya que simplemente se deben crear una serie de valores en el registro de Windows (El registro de Windows es el lugar dónde Windows almacena la información de configuración de todo el sistema).
NOTA: Ten mucho cuidado al editar el registro de Windows, ya que cualquier cambio incorrecto puede hacer que Windows deje de funcionar correctamente. Estás advertido!!
Para abrir el registro de Windows, ejecuta el comando regedit en la ventana de Ejecutar (Win + R)
Después de ejecutar este comando te aparecerá el registro de Windows, mostrando al lado izquierdo una serie de carpetas llamadas Llaves o Keys y dentro de ellas una serie de valores que pueden ser cadenas, números valores booleanos etc.
Para asociar una extensión tienes que seguir los siguientes pasos:
- Crear una nueva llave (key) dentro de HKEY_CLASSES_ROOT con el nombre de tu extensión, por ejemplo .copstone.
- Modifica el valor (Default) dentro de dicha llave y colócale un nombre único que será usado más adelante. Asegúrate de que el nombre no tenga espacios ni caracteres raros como ñ o @. En este caso Copstone.File.
- Crea una llave (key) dentro de HKEY_CLASSES_ROOT con el nombre que colocaste en el paso 2 (Copstone.File).
- Modifica el valor (Default) dentro de dicha llave y colócale la descripción del archivo, en este caso “Archivo de datos de copstone”.
- Crea una llave (key) dentro de la llave del paso 3 llamada DefaultIcon (Tiene que estar escrita exactamente igual a como aparece aquí).
- Modifica el valor (Default) de la llave DefaultIcon y colócale la ruta completa de tu ícono, por ejemplo C:\Program Files\Copstone\copstone.ico
- Crea las llaves (key) shell, open y command una dentro de otra para que tengas la ruta shell\open\command dentro de la llave creada en el paso 3.
- Modifica el valor (Default) de la llave command y colócale la ruta completa de tu ejecutable seguida por %1. Windows automáticamente reemplazará el %1 por el nombre del archivo a abrir al momento de invocar a tu programa. Te recomiendo poner el la ruta del ejecutable y el %1 entre comillas dobles para evitar errores con rutas que contengan espacios en blanco.
Listo!! Ahora cualquier archivo que crees con la extensión .copstone se verá como la segunda imagen de este artículo y cuando le des clic a este archivo se abrirá tu programa.
Nota: Si los archivos con la extensión .copstone aún no se ven como lo esperado seguramente tienes que reiniciar tu PC para que los cambios se vean reflejados.
Asociando la extensión con código
Este proceso puede ser un poco pesado de realizar en cada máquina en la que desees instalar tu programa. Para facilitar este procedimiento puedes crear un instalador como InstallShield que coloque automáticamente estos valores en el registro o puedes agregar un poco de código a tu programa para que cree estas llaves cada vez que se ejecute tu programa.
A continuación te presento una función que realiza todo el procedimiento descrito anteriormente. Te recomiendo invocar a esta función al inicio de tu programa para asegurar que siempre la extensión esté asociada a tu programa.
Nota: Windows protege la escritura del registro por lo que tu programa debe ejecutarse con permisos de administrador para que la función pueda alterar el registro, si no cuenta con los permisos suficientes se mostrará un mensaje de error.
Visual Studio
Code Gear
using namespace Microsoft::Win32;
void registrarExtension(String ^extension,
String ^nombreExtension,
String ^descripcionExtension,
String ^ejecutable,
String ^icono)
{
// Registramos la extensión
try
{
RegistryKey ^reg = Registry::ClassesRoot->CreateSubKey(extension);
reg->SetValue("", nombreExtension);
reg->Close();
// Registramos el ejecutable con el que se abrirá el archivo
reg = Registry::ClassesRoot->CreateSubKey(nombreExtension);
reg->SetValue("", descripcionExtension);
RegistryKey ^reg2 = reg->CreateSubKey("shell");
RegistryKey ^reg3 = reg2->CreateSubKey("open");
RegistryKey ^reg4 = reg3->CreateSubKey("command");
reg4->SetValue("", "\"" + ejecutable + "\" \"%1\"");
reg4->Close();
reg3->Close();
reg2->Close();
// Registramos el icono si existe
if (System::IO::File::Exists(icono))
{
reg2 = reg->CreateSubKey("DefaultIcon");
reg2->SetValue("", icono);
reg2->Close();
}
reg->Close();
}
catch (...)
{
MessageBox::Show("Para asociar la extensión necesita permisos de administrador",
"Error", MessageBoxButtons::OK, MessageBoxIcon::Error);
}
}
#include <Registry.hpp>
void registrarExtension(AnsiString extension,
AnsiString nombreExtension,
AnsiString descripcionExtension,
AnsiString ejecutable,
AnsiString icono)
{
TRegistry *reg = new TRegistry();
try
{
reg->RootKey = HKEY_CLASSES_ROOT;
// Registramos la extensión
reg->OpenKey(extension, true);
reg->WriteString("", nombreExtension);
reg->CloseKey();
// Registramos el ejecutable con el que se abrirá el archivo
reg->OpenKey(nombreExtension, true);
reg->WriteString("", descripcionExtension);
reg->OpenKey("shell", true);
reg->OpenKey("open", true);
reg->OpenKey("command", true);
reg->WriteString("", "\"" + ejecutable + "\" \"%1\"" );
reg->CloseKey();
reg->CloseKey();
reg->CloseKey();
reg->CloseKey();
// Registramos el icono si existe
if (FileExists(icono))
{
reg->OpenKey(nombreExtension, true);
reg->OpenKey("DefaultIcon", true);
reg->WriteString("", icono);
reg->CloseKey();
reg->CloseKey();
}
}
catch (...)
{
MessageDlg("Para asociar la extensión necesita permisos de administrador",
mtError, TMsgDlgButtons() << mbOK, 0);
}
}
A continuación te explico que valores debes mandar a cada uno de los parámetros de la función registrarExtension:
| Parámetro | Descripción | Ejemplo |
|---|---|---|
| extension | El nombre de la extensión a registrar. Debe comenzar con un punto (.) y de preferencia estar escrita en minúsculas. | .copstone |
| nombreExtension | El nombre que se utilizará internamente para reconocer a la extensión. Este nombre no debe contener espacios en blanco y debe comenzar con una letra. | CopstoneFile |
| descripcionExtension | El texto que describe al tipo de archivo. Este debería ser un texto corto que permita describir brevemente el tipo de archivo. | Archivo de datos de copstone |
| ejecutable | La ruta completa del ejecutable que se utilizará para abrir este tipo de archivos. | C:\Files\Copstone.exe |
| icono | La ruta completa de donde se ubica el ícono a utilizar para los archivos con esta extensión. Si manda una cadena vacía por defecto utilizará el ícono del ejecutable. | C:\Files\Copstone.ico |
Por si acaso tienes algún problema con los parámetros te muestro un ejemplo de como invocar a esta función desde el constructor de tu programa visual para que se configure automáticamente en base a la posición del ejecutable.
Acuérdate de que el ejecutable debe tener permisos de administrador para que esto funcione. (En Windows Vista y Windows 7, clic derecho y Ejecutar como Administrador).
Nota: Este código asume que el ícono está ubicado en la misma carpeta del ejecutable y se llama copstone.ico
Visual Studio
Code Gear
Form1(void)
{
InitializeComponent();
registrarExtension(".copstone",
"Copstone.File",
"Archivo de datos de copstone",
Application::ExecutablePath,
System::IO::Path::GetDirectoryName(Application::ExecutablePath) + "\\copstone.ico");
}
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
registrarExtension(".copstone",
"Copstone.File",
"Archivo de datos de copstone",
Application->ExeName,
ExtractFilePath(Application->ExeName) + "copstone.ico");
}
Recibiendo el nombre del archivo
Si has seguido los pasos correctamente, puedes notar que al hacer doble clic en cualquier archivo con extensión .copstone se abrirá nuestro programa. La pregunta es, ¿cómo hacemos para detectar dentro de nuestro programa que archivo ha sido presionado?
La respuesta es muy sencilla, simplemente hay que obtener el primer parámetro que nos ha llegado a la aplicación, este tendrá la ruta completa del archivo que se ha presionado.
Para probar esto simplemente vamos a crear dentro de nuestro programa (en entorno visual) un campo de texto (Edit o Textbox) al que le colocaremos el nombre del archivo que se ha presionado justo cuando arranca nuestro programa.
Visual Studio
Code Gear
Form1(void)
{
InitializeComponent();
if (Environment::GetCommandLineArgs()->Length > 0)
textBox1->Text = Environment::GetCommandLineArgs()->GetValue(1)->ToString();
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
if (ParamCount() > 0)
Edit1->Text = ParamStr(1);
}
Espero que este artículo te sea útil y te sirva como inicio para hacer muchas otras cosas. Si quieres aprender un poco más acerca de las diferentes llaves que se pueden agregar en el registro te recomiendo que mires un poco el registro o que ingreses a http://www.pctools.com/guides/registry/ dónde puedes encontrar muchos tips acerca del registro de Windows.

Gracias por el dato… es lo que estaba buscando
voy a probarlo a ver que tal me va…. Saludos
Es exacto lo que buscaba, pero uso c# con el visual studio express para hacer mi pequeñas utilidades. ¿Seria posible para ti escribirlo en c sharp?
Hay algo que no termine de entender, tu dices: “Te recomiendo invocar a esta función al inicio de tu programa para asegurar que siempre la extensión esté asociada a tu programa.” Al crease en el registro las llaves, ¿es necesario volverlas a crear cada vez que se ejecuta el programa?
Gracias de antemano,
Corpa
No es ningun problema hacerlo en C# lo voy a tener en cuenta para futuros post. Sin embargo en este caso la logica es la misma y es mas, el codigo en C# es muy parecido a la que se usa en el codigo de C++ para Visual Studio porque usa las mismas librerias ya que es .NET.
Por otro lado, lo que mencionas con respecto a invocar a la función una sola vez es cierto, no es necesario volver a crear las llaves en el registro, pero si ves programas como firefox o internet explorer puedes notar que siempre te preguntan si quieres convertirlo en tu navegador por defecto que viene a ser la misma idea. Claro está que tienes que modificar un poco el código del ejemplo para que valide si tu programa es el que maneja la extensión u otro programa se ha apoderado de ella.
HEQR4k Excellent article, I will take note. Many thanks for the story!
Cool post.
Esto es lo que buscaba, pero el icono no me funciona , si tienes alguna idea , por favor hasmelo saber
Prueba reiniciando tu máquina para que los cambios hagan efecto.
Estimado Alfredo: Es muy interesante tu post, incluso lo implemente en Visual Basic 2008, funciona perfectamente. Pero… ¿Como le hago para que se muestre un archivo si mi aplicación ya se inicio?
Lo que va a pasar de todas maneras es que se va a abrir una nueva instancia de tu programa, pero lo que puedes hacer es detectar que es una segunda instancia, mandarle el mensaje a la primera instancia para que abra un proyecto determinado y luego cierras la segunda instancia. Para el usuario va a parecer que el proyecto se abrió de frente en la primera instancia pero tu sabes que no es así. Te recomiendo que veas el post Como permitir una sola instancia de un programa http://copstone.com/2010/04/como-permitir-una-sola-instancia-de-un-programa/
Es una gran aportación, y funciona muy bien. Pero tengo una duda: ¿Como le hago para que abra mi archivo si mi programa ya arranco?
Por ejemplo: Inicio mi programa, trabajo con un proyecto y cierro dicho proyecto; ahora sin cerrar mi programa, doy doble clic a un proyecto cualquiera.
Lo que va a pasar de todas maneras es que se va a abrir una nueva instancia de tu programa, pero lo que puedes hacer es detectar que es una segunda instancia, mandarle el mensaje a la primera instancia para que abra un proyecto determinado y luego cierras la segunda instancia. Para el usuario va a parecer que el proyecto se abrió de frente en la primera instancia pero tu sabes que no es así. Te recomiendo que veas el post Como permitir una sola instancia de un programa
Excelente
100 Puntos, muchas gracias.
Espectacular el artículo y la explicación. Muchisimas Gracias!!!!!