it-swarm-es.tech

Cómo asociar una extensión de archivo al ejecutable actual en C #

Me gustaría asociar una extensión de archivo al ejecutable actual en C #. De esta manera, cuando el usuario haga clic en el archivo luego en el Explorador, ejecutará mi archivo ejecutable con el archivo dado como primer argumento. Lo ideal sería que también estableciera el icono para las extensiones de archivo dadas al icono para mi ejecutable. Gracias a todos.

51
Chris

No parece haber una API .Net para administrar directamente las asociaciones de archivos, pero puede usar las clases del Registro para leer y escribir las claves que necesita.

Deberá crear una clave en HKEY_CLASSES_ROOT con el nombre establecido en su extensión de archivo (por ejemplo: ".txt"). Establezca el valor predeterminado de esta clave en un nombre único para su tipo de archivo, como "Acme.TextFile". Luego cree otra clave debajo de HKEY_CLASSES_ROOT con el nombre configurado en "Acme.TextFile". Agregue una subclave llamada "DefaultIcon" y establezca el valor predeterminado de la clave en el archivo que contiene el icono que desea usar para este tipo de archivo. Añadir otro hermano llamado "Shell". Debajo de la tecla "Shell", agregue una clave para cada acción que desee tener disponible a través del menú contextual del Explorador, configurando el valor predeterminado para cada clave a la ruta de su ejecutable seguido de un espacio y "% 1" para representar la ruta al archivo seleccionado.

Por ejemplo, aquí hay un ejemplo de archivo de registro para crear una asociación entre los archivos .txt y EmEditor:

 Windows Registry Editor Version 5.00 
 
 [HKEY_CLASSES_ROOT\.txt] 
 @ = "Emeditor.txt" 
 
 [HKEY_CLASSES_ROOT\emeditor.txt] 
 @ = "Documento de texto" 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\DefaultIcon] 
 @ = "% SystemRoot% \\ SysWow64\\ imageres.dll, -102 "
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell] 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open] 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\open\command] 
 @ = "\" C: \\ Archivos de programa \\ EmEditor \\ EMEDITOR.EXE\"\"% 1\"" 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print] 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print\command] 
 @ = "\" C: \\ Archivos de programa \\ EmEditor \\ EMEDITOR.EXE\"/ p \"% 1\"" 
40
X-Cubed

Además, si decide ir por el registro, tenga en cuenta que las asociaciones de usuarios actuales están bajo HKEY_CURRENT_USER\Software\Classes. Podría ser mejor agregar su aplicación allí en lugar de clases de máquinas locales.

Si su programa será ejecutado por usuarios limitados, no podrá modificar CLASSES_ROOT de todos modos.

25
Ishmaeel

Si usa la implementación de ClickOnce, todo esto se maneja por usted (al menos, en VS2008 SP1); simplemente:

  • Propiedades del proyecto
  • Publicar
  • Opciones
  • Asociaciones de archivos
  • (Añade lo que necesites)

(tenga en cuenta que debe ser de plena confianza, destino .NET 3.5 y configurarse para el uso sin conexión)

Vea también MSDN: Cómo: Crear asociaciones de archivos para una aplicación ClickOnce

11
Marc Gravell

Aquí hay un ejemplo completo:

public class FileAssociation
{
    public string Extension { get; set; }
    public string ProgId { get; set; }
    public string FileTypeDescription { get; set; }
    public string ExecutableFilePath { get; set; }
}

public class FileAssociations
{
    // needed so that Explorer windows get refreshed after the registry is updated
    [System.Runtime.InteropServices.DllImport("Shell32.dll")]
    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);

    private const int SHCNE_ASSOCCHANGED = 0x8000000;
    private const int SHCNF_FLUSH = 0x1000;

    public static void EnsureAssociationsSet()
    {
        var filePath = Process.GetCurrentProcess().MainModule.FileName;
        EnsureAssociationsSet(
            new FileAssociation
            {
                Extension = ".binlog",
                ProgId = "MSBuildBinaryLog",
                FileTypeDescription = "MSBuild Binary Log",
                ExecutableFilePath = filePath
            },
            new FileAssociation
            {
                Extension = ".buildlog",
                ProgId = "MSBuildStructuredLog",
                FileTypeDescription = "MSBuild Structured Log",
                ExecutableFilePath = filePath
            });
    }

    public static void EnsureAssociationsSet(params FileAssociation[] associations)
    {
        bool madeChanges = false;
        foreach (var association in associations)
        {
            madeChanges |= SetAssociation(
                association.Extension,
                association.ProgId,
                association.FileTypeDescription,
                association.ExecutableFilePath);
        }

        if (madeChanges)
        {
            SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero);
        }
    }

    public static bool SetAssociation(string extension, string progId, string fileTypeDescription, string applicationFilePath)
    {
        bool madeChanges = false;
        madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + extension, progId);
        madeChanges |= SetKeyDefaultValue(@"Software\Classes\" + progId, fileTypeDescription);
        madeChanges |= SetKeyDefaultValue([email protected]"Software\Classes\{progId}\Shell\open\command", "\"" + applicationFilePath + "\" \"%1\"");
        return madeChanges;
    }

    private static bool SetKeyDefaultValue(string keyPath, string value)
    {
        using (var key = Registry.CurrentUser.CreateSubKey(keyPath))
        {
            if (key.GetValue(null) as string != value)
            {
                key.SetValue(null, value);
                return true;
            }
        }

        return false;
    }
9
Kirill Osenkov

Puede haber razones específicas por las que elige no usar un paquete de instalación para su proyecto, pero un paquete de instalación es un gran lugar para realizar fácilmente las tareas de configuración de la aplicación, como registrar extensiones de archivos, agregar accesos directos de escritorio, etc.

Aquí se explica cómo crear una asociación de extensión de archivo mediante las herramientas integradas de instalación de Visual Studio:

  1. Dentro de su solución de C # existente, agregue un nuevo proyecto y seleccione el tipo de proyecto como Other Project Types -> Setup and Deployment -> Setup Project (o pruebe el Asistente de configuración)

  2. Configure su instalador (hay muchos documentos existentes para esto si necesita ayuda)

  3. Haga clic con el botón derecho en el proyecto de instalación en el Explorador de soluciones, seleccione View -> File Types, y luego agregue la extensión que desea registrar junto con el programa para ejecutarlo.

Este método tiene el beneficio adicional de limpiar después de sí mismo si un usuario ejecuta la desinstalación para su aplicación.

7
Paul J

Para ser específico sobre la forma de "Registro de Windows":

Creo claves bajo HKEY_CURRENT_USER\Software\Classes (como dijo Ishmaeel)

y siga las instrucciones respondidas por X-Cubed.

El código de muestra se ve así:

private void Create_abc_FileAssociation()
{
    /***********************************/
    /**** Key1: Create ".abc" entry ****/
    /***********************************/
    Microsoft.Win32.RegistryKey key1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key1.CreateSubKey("Classes");
    key1 = key1.OpenSubKey("Classes", true);

    key1.CreateSubKey(".abc");
    key1 = key1.OpenSubKey(".abc", true);
    key1.SetValue("", "DemoKeyValue"); // Set default key value

    key1.Close();

    /*******************************************************/
    /**** Key2: Create "DemoKeyValue\DefaultIcon" entry ****/
    /*******************************************************/
    Microsoft.Win32.RegistryKey key2 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key2.CreateSubKey("Classes");
    key2 = key2.OpenSubKey("Classes", true);

    key2.CreateSubKey("DemoKeyValue");
    key2 = key2.OpenSubKey("DemoKeyValue", true);

    key2.CreateSubKey("DefaultIcon");
    key2 = key2.OpenSubKey("DefaultIcon", true);
    key2.SetValue("", "\"" + "(The icon path you desire)" + "\""); // Set default key value

    key2.Close();

    /**************************************************************/
    /**** Key3: Create "DemoKeyValue\Shell\open\command" entry ****/
    /**************************************************************/
    Microsoft.Win32.RegistryKey key3 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software", true);

    key3.CreateSubKey("Classes");
    key3 = key3.OpenSubKey("Classes", true);

    key3.CreateSubKey("DemoKeyValue");
    key3 = key3.OpenSubKey("DemoKeyValue", true);

    key3.CreateSubKey("Shell");
    key3 = key3.OpenSubKey("Shell", true);

    key3.CreateSubKey("open");
    key3 = key3.OpenSubKey("open", true);

    key3.CreateSubKey("command");
    key3 = key3.OpenSubKey("command", true);
    key3.SetValue("", "\"" + "(The application path you desire)" + "\"" + " \"%1\""); // Set default key value

    key3.Close();
}

Solo les muestro una demostración rápida, muy fácil de entender. Podrías modificar esos valores clave y todo está listo.

5
Strong

Las asociaciones de archivos se definen en el registro en HKEY_CLASSES_ROOT.

Hay un ejemplo de VB.NET aquí que puedo transportar fácilmente a C #.

2
Steve Morgan

El siguiente código es una función que debería funcionar, agrega los valores requeridos en el registro de Windows. Normalmente ejecuto SelfCreateAssociation (". Abc") en mi ejecutable. (constructor de formularios o onload u onshown) Actualizará la entrada de registro para el usuario actual, cada vez que se ejecute el ejecutable. (bueno para la depuración, si tiene algunos cambios). Si necesita información detallada sobre las claves de registro involucradas, consulte este enlace de MSDN.

https://msdn.Microsoft.com/en-us/library/windows/desktop/dd758090 (v = vs.85) .aspx

Para obtener más información sobre la clave de registro general de ClassesRoot. Vea este artículo de MSDN.

https://msdn.Microsoft.com/en-us/library/windows/desktop/ms724475 (v = vs.85) .aspx

public enum KeyHiveSmall
{
    ClassesRoot,
    CurrentUser,
    LocalMachine,
}

/// <summary>
/// Create an associaten for a file extension in the windows registry
/// CreateAssociation(@"vendor.application",".tmf","Tool file",@"C:\Windows\SYSWOW64\notepad.exe",@"%SystemRoot%\SYSWOW64\notepad.exe,0");
/// </summary>
/// <param name="ProgID">e.g. vendor.application</param>
/// <param name="extension">e.g. .tmf</param>
/// <param name="description">e.g. Tool file</param>
/// <param name="application">e.g.  @"C:\Windows\SYSWOW64\notepad.exe"</param>
/// <param name="icon">@"%SystemRoot%\SYSWOW64\notepad.exe,0"</param>
/// <param name="Hive">e.g. The user-specific settings have priority over the computer settings. KeyHive.LocalMachine  need admin rights</param>
public static void CreateAssociation(string ProgID, string extension, string description, string application, string icon, KeyHiveSmall Hive = KeyHiveSmall.CurrentUser)
{
    RegistryKey selectedKey = null;

    switch (Hive)
    {
        case KeyHiveSmall.ClassesRoot:
            Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.ClassesRoot.CreateSubKey(ProgID);
            break;

        case KeyHiveSmall.CurrentUser:
            Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Classes\" + ProgID);
            break;

        case KeyHiveSmall.LocalMachine:
            Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + extension).SetValue("", ProgID);
            selectedKey = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"Software\Classes\" + ProgID);
            break;
    }

    if (selectedKey != null)
    {
        if (description != null)
        {
            selectedKey.SetValue("", description);
        }
        if (icon != null)
        {
            selectedKey.CreateSubKey("DefaultIcon").SetValue("", icon, RegistryValueKind.ExpandString);
            selectedKey.CreateSubKey(@"Shell\Open").SetValue("icon", icon, RegistryValueKind.ExpandString);
        }
        if (application != null)
        {
            selectedKey.CreateSubKey(@"Shell\Open\command").SetValue("", "\"" + application + "\"" + " \"%1\"", RegistryValueKind.ExpandString);
        }
    }
    selectedKey.Flush();
    selectedKey.Close();
}

 /// <summary>
    /// Creates a association for current running executable
    /// </summary>
    /// <param name="extension">e.g. .tmf</param>
    /// <param name="Hive">e.g. KeyHive.LocalMachine need admin rights</param>
    /// <param name="description">e.g. Tool file. Displayed in Explorer</param>
    public static void SelfCreateAssociation(string extension, KeyHiveSmall Hive = KeyHiveSmall.CurrentUser, string description = "")
    {
        string ProgID = System.Reflection.Assembly.GetExecutingAssembly().EntryPoint.DeclaringType.FullName;
        string FileLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
        CreateAssociation(ProgID, extension, description, FileLocation, FileLocation + ",0", Hive);
    }
2
Carsten R.

Existen dos herramientas de cmd que existen desde Windows 7 que facilitan la creación de asociaciones de archivos simples. Son assoc y ftype . Aquí hay una explicación básica de cada comando.

  • Assoc - asocia una extensión de archivo (como '.txt') con un "tipo de archivo".
  • FType - define un ejecutable para ejecutarse cuando el usuario abre un "tipo de archivo" dado.

Tenga en cuenta que estas son herramientas de cmd y no archivos ejecutables (exe). Esto significa que solo se pueden ejecutar en una ventana cmd, o usando ShellExecute con "cmd/c assoc". Puede obtener más información sobre ellos en los enlaces o escribiendo "assoc /?" y "ftype /?" en un mensaje de cmd.

Entonces, para asociar una aplicación con una extensión .bob, puede abrir una ventana cmd (WindowKey + R, escribir cmd, presionar intro) y ejecutar lo siguiente:

assoc .bob=BobFile
ftype BobFile=c:\temp\BobView.exe "%1"

Esto es mucho más simple que jugar con el registro y es más probable que funcione en una versión futura de Windows.

Para terminar, aquí hay una función de C # para crear una asociación de archivos:

public static int setFileAssociation(string[] extensions, string fileType, string openCommandString) {
    int v = execute("cmd", "/c ftype " + fileType + "=" + openCommandString);
    foreach (string ext in extensions) {
        v = execute("cmd", "/c assoc " + ext + "=" + fileType);
        if (v != 0) return v;
    }
    return v;
}
public static int execute(string exeFilename, string arguments) {
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = true;
    startInfo.FileName = exeFilename;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.Arguments = arguments;
    try {
        using (Process exeProcess = Process.Start(startInfo)) {
            exeProcess.WaitForExit();
            return exeProcess.ExitCode;
        }
    } catch {
        return 1;
    }
}
0
Mike