Crear una entrada del registro para asociar la extensión de archivo con la aplicación en C++


Me gustaría saber la forma más limpia de registrar una extensión de archivo con mi aplicación C++ para que cuando se haga doble clic en un archivo de datos asociado con mi programa, se abra la aplicación y se pase el nombre del archivo como parámetro a la aplicación.

Actualmente, lo hago a través de mi instalador de wix, pero hay algunos casos en los que la aplicación no se instalará en el equipo del usuario, por lo que también necesito la opción de crear la clave de registro a través del aplicación.

Además, ¿esto también significará que si se elimina la aplicación, las entradas no utilizadas en el registro se dejarán por ahí?

Author: Seth, 2009-09-07

3 answers

Su descripción básica del proceso se encuentra en este artículo de MSDN. Las partes clave están al final de la lista:

  • Registrar el ProgID

Un ProgID (esencialmente, la clave de registro de tipo de archivo) es lo que contiene sus propiedades de tipo de archivo importantes, como el icono, la descripción y los elementos del menú contextual, incluida la aplicación utilizada cuando se hace doble clic en el archivo. Muchas extensiones pueden tener el mismo tipo de archivo. Ese mapeo se realiza en el siguiente paso:

  • Registrar la extensión de nombre de archivo para el tipo de archivo

Aquí, establece un valor de registro para su extensión, estableciendo el tipo de archivo de esa extensión al ProgID que creó en el paso anterior.

La cantidad mínima de trabajo requerido para obtener un archivo para abrir con su aplicación es establecer/crear dos claves de registro. En este ejemplo de archivo .reg, creo un tipo de archivo (blergcorp.blergapp.v1) y asocio una extensión de archivo (.blerg) con él.

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command]
@="c:\path\to\app.exe \"%1\""
[HKEY_CURRENT_USER\Software\Classes\.blerg]
@="blergcorp.blergapp.v1"

Ahora, usted probablemente quiera lograr esto programáticamente. Para ser absolutamente kosher, podría comprobar la existencia de estas claves, y cambiar el comportamiento de su programa en consecuencia, especialmente si está asumiendo el control de alguna extensión de archivo común. Sin embargo, el objetivo se puede lograr configurando esas dos teclas usando la función setValue.

No estoy seguro de la sintaxis exacta de C++, pero en C# la sintaxis se ve algo como esto:

Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\blergcorp.blergapp.v1\shell\open\command", null, @"c:\path\to\app.exe \"%1\"");
Registry.SetValue(@"HKEY_CURRENT_USER\Software\Classes\.blerg", null, "blergcorp.blergapp.v1");

Por supuesto, usted podría manualmente abra cada subclave, cree manualmente la subclave ProgID y extension, y luego establezca el valor de la clave, pero una cosa agradable acerca de la función SetValue es que si las claves o los valores no existen, se crearán automáticamente. Muy práctico.

Ahora, una palabra rápida sobre qué colmena usar. Muchos ejemplos de asociación de archivos en línea, incluidos los de MSDN, muestran estas claves configuradas en HKEY_CLASSES_ROOT. No recomiendo hacer esto. Esa colmena es una vista virtual fusionada de HKEY_LOCAL_MACHINE\Software\Classes (los valores predeterminados del sistema) y HKEY_CURRENT_USER\Software\Classes (la configuración por usuario), y escribe en cualquier subclave en la colmena se redirigen a la misma clave en HKEY_LOCAL_MACHINE\Software\Classes. Ahora, no hay ningún problema directo al hacer esto, pero puede encontrarse con este problema: Si escribe en HKCR (redirigido a HKLM), y el usuario ha especificado las mismas claves con diferentes valores en HKCU, los valores de HKCU tendrán prioridad. Por lo tanto, sus escrituras tendrán éxito, pero no verá ningún cambio, porque la configuración de HKEY_CURRENT_USER tiene prioridad sobre la configuración de HKEY_LOCAL_MACHINE.

Por lo tanto, usted debe tener esto en cuenta al diseñar su aplicación. Ahora, por otro lado, solo puedes escribir a HKEY_CURRENT_USER, como muestran mis ejemplos aquí. Sin embargo, esa configuración de asociación de archivos solo se cargará para el usuario actual, y si la aplicación se ha instalado para todos los usuarios, la aplicación no se iniciará cuando ese otro usuario abra el archivo en Windows.

Eso debería ser un manual decente para lo que quieres hacer. Para mayor lectura sugiero

Y ver también mi respuesta similar a una pregunta similar:

 71
Author: Factor Mystic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:56

Este es un proceso de dos pasos:

 1. Define a program that would take care of extension: (unless you want to use existing one)
      1.1 create a key in "HKCU\\Software\\Classes\\" for example 
          "Software\\Classes\\YourProgramName.file.ext"
      1.2 create subkey "Software\\Classes\\YourProgramName.file.ext\\DefaultIcon"
        1.2.1 set default value ("") to your application full path to get
              icon from resources
      1.3 create a subkey "Software\\Classes\\YourProgramName.file.ext\\Shell\\OperationName\\Command"
          OperationName = for example Open, Print or Other
        1.3.1 set default value ("") to your application full path +optional runtime params (filename)

2.Associate file extension with program.
  2.1 create a key HKCU\\Software\\Classes\\.ext   - here goes your extension
  2.2 set default value to the program definition key
    ("YourProgramName.file.ext")

A continuación se muestra parte del programa escrito en c# que asocia la extensión de archivo. No es c++ pero creo que es lo suficientemente simple para explicarse y AFAIK es verv simmilar si no idéntico al código en c++

1.


    RegistryKey keyPFCTExt0 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc", true);
        if (keyPFCTExt0 == null)
        {
            keyPFCTExt0 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc");
            keyPFCTExt0.CreateSubKey("DefaultIcon");
                RegistryKey keyPFCTExt0ext = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\DefaultIcon", true);
                    keyPFCTExt0ext.SetValue("", Application.ExecutablePath +",0");
                keyPFCTExt0ext.Close();
            keyPFCTExt0.CreateSubKey("Shell\\PFCT_Decrypt\\Command");
        }
    keyPFCTExt0.SetValue("", "PFCT.file.enc");
    keyPFCTExt0.Close();

2.


    RegistryKey keyPFCTExt1 = Registry.CurrentUser.OpenSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command", true);
        if (keyPFCTExt1 == null)
            keyPFCTExt1 = Registry.CurrentUser.CreateSubKey("Software\\Classes\\PFCT.file.enc\\Shell\\PFCT_Decrypt\\Command");
        keyPFCTExt1.SetValue("", Application.ExecutablePath + " !d %1"); //!d %1 are optional params, here !d string and full file path
        keyPFCTExt1.Close(); 

 7
Author: beermann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-09 21:52:16

No entiendo por qué la gente sigue diciendo que el valor predeterminado de HKEY_CURRENT_USER\Software\Classes\<.ext> (que te redirigirá a otra clase (creada por software).

Funciona, pero será anulado por

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\<.ext>\UserChoice

Y creo que Microsoft recomienda la segunda práctica - porque es lo que el built-in "abrir con" está haciendo. El valor de la clave Progid" es igual al valor predeterminado de HKEY_CURRENT_USER\Software\Classes\<.ext> en este caso.

 6
Author: fireattack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-10 08:33:25