2008-09-16 22 views
45

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 después en el explorador, ejecutará mi ejecutable con el archivo dado como primer argumento. Idealmente, también establecería el ícono para las extensiones de archivo dadas al ícono para mi ejecutable. Gracias a todos.Cómo asociar una extensión de archivo al ejecutable actual en C#

+0

Esto ha sido contestada a fondo en el siguiente hilo: http://stackoverflow.com/questions/2993118/how-to-perform-shell-icon-embedding-in-visual-studio -2010/10415947 # 10415947 –

+0

Esto ha sido completamente respondido en el siguiente [thread overflow thread] (http://stackoverflow.com/questions/2993118/how-to-perform-shell-icon-embedding-in-visual-studio -2010/10415947 # 10415947). Hemos estado usando esta implementación y funciona de maravilla. También es de código abierto y se integra en MSBuild. –

+2

@BlakeNiemyjski ¿Cómo son sus enlaces sobre la incrustación de iconos en ensamblados .NET relevantes para esta pregunta sobre la asociación de extensiones de archivos? –

Respuesta

2

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

Hay un ejemplo de VB.NET here que puedo fácilmente portar a C#.

38

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

Tendrá que 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 crea otra clave bajo HKEY_CLASSES_ROOT con el nombre establecido en "Acme.TextFile". Agregue una subclave llamada "DefaultIcon" y establezca el valor predeterminado de la clave para el archivo que contiene el icono que desea usar para este tipo de archivo. Agregue 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 de Explorer, establezca el valor predeterminado para cada tecla en la ruta al ejecutable seguido de un espacio y "% 1" para representar la ruta al archivo seleccionado.

Por ejemplo, aquí hay un archivo de registro de ejemplo 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] 
@="Text Document" 

[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:\\Program Files\\EmEditor\\EMEDITOR.EXE\" \"%1\"" 

[HKEY_CLASSES_ROOT\emeditor.txt\shell\print] 

[HKEY_CLASSES_ROOT\emeditor.txt\shell\print\command] 
@="\"C:\\Program Files\\EmEditor\\EMEDITOR.EXE\" /p \"%1\"" 
+0

¿Hay alguna manera de pasar algunos argumentos al exe (en este caso a C: \ Program Files \ EmEditor \ EMEDITOR.EXE)? – Apparao

+0

@Apparao sí, mire el comando Imprimir como un ejemplo. Pasa el parámetro a/p antes del nombre del archivo. –

25

Además, si usted decide ir a la forma del 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 las clases de máquinas locales.

Si su programa estará a cargo de los usuarios limitados, usted no será capaz de modificar CLASSES_ROOT de todos modos.

7

Puede haber razones específicas por las que no optar por emplear un paquete de instalación para su proyecto, sino un paquete de instalación es un gran lugar para realizar fácilmente tareas de configuración de aplicaciones tales extensiones de archivo Registro, añadiendo accesos directos del escritorio, etc.

aquí es cómo crear asociación de extensión de archivo usando las herramientas de instalación integradas en Visual Studio:

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

  2. Configurar el instalador (un montón de documentos existentes para esto si necesita ayuda)

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

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

11

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

  • Propiedades del proyecto
  • Publicar
  • Opciones
  • Associatons archivos
  • (añadir lo que sea necesario)

(tenga en cuenta que debe ser de plena confianza, objetivo. NET 3.5, y estar configurado para el uso fuera de línea)

Ver también MSDN: How to: Create File Associations For a ClickOnce Application

+1

Tengo VS2008 Professional, SP1 y no veo esta opción. Debo estar perdiendo algo. – Jerry

5

ser específico acerca de la forma en "Registro de Windows":

creo llaves debajo HKEY_CURRENT_USER \ Software \ Classes (como Ishmaeel dijo)

y siga las instrucciones respondida por X-Cubed.

El código de ejemplo se parece a:

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 tiene que mostrar ustedes una demostración rápida, muy fácil de entender. Podrías modificar esos valores clave y todo está bien para ir.

+1

No olvide agregar el código necesario para notificar al shell que use el ícono. 'SHChangeNotify (0x8000000, 0, 0, 0);' – randomsolutions

8

Aquí está 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; 
    } 
0

Hay dos herramientas cmd que han existido desde Windows 7, que hacen que sea muy fácil crear 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 ejecutar cuando el usuario abre un "tipo de archivo" dado.

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

Así que para asociar una aplicación con una extensión .bob, puede abrir una ventana de cmd (WindowKey + R, escribe cmd, pulse enter) y ejecute los siguientes:

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

Esto es mucho más simple que ensuciar con el registro y es más probable que funcione en la versión de Windows en el futuro.

envolviéndolo, aquí es 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

El código siguiente es una función del deberían trabajar, que añade los valores requeridos en el registro de Windows. Por lo general, ejecuto SelfCreateAssociation (". Abc") en mi ejecutable.(form constructor o onload o 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 ClassesRoot general. 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); 
    } 
+0

Dejar un gran bloque de código sin explicación difícilmente ayuda a los lectores futuros. Intenta agregar alguna explicación sobre lo que hace este código. – Nisarg

Cuestiones relacionadas