c# registry file-association

c# - Asociar extensión de archivo con aplicación



registry file-association (7)

He escrito un programa que edita un tipo de archivo específico, y quiero darle al usuario la opción de configurar mi aplicación como el editor predeterminado para este tipo de archivo (ya que no quiero un instalador) al inicio.

Intenté escribir un método reutilizable que asociara un archivo para mí (preferiblemente en cualquier sistema operativo, aunque estoy ejecutando Vista) agregando una clave a HKEY_CLASSES_ROOT, y lo estoy usando con mi aplicación, pero no lo hace parece que funciona

public static void SetAssociation(string Extension, string KeyName, string OpenWith, string FileDescription) { RegistryKey BaseKey; RegistryKey OpenMethod; RegistryKey Shell; RegistryKey CurrentUser; BaseKey = Registry.ClassesRoot.CreateSubKey(Extension); BaseKey.SetValue("", KeyName); OpenMethod = Registry.ClassesRoot.CreateSubKey(KeyName); OpenMethod.SetValue("", FileDescription); OpenMethod.CreateSubKey("DefaultIcon").SetValue("", "/"" + OpenWith + "/",0"); Shell = OpenMethod.CreateSubKey("Shell"); Shell.CreateSubKey("edit").CreateSubKey("command").SetValue("", "/"" + OpenWith + "/"" + " /"%1/""); Shell.CreateSubKey("open").CreateSubKey("command").SetValue("", "/"" + OpenWith + "/"" + " /"%1/""); BaseKey.Close(); OpenMethod.Close(); Shell.Close(); CurrentUser = Registry.CurrentUser.CreateSubKey(@"HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Explorer/FileExts/" + Extension); CurrentUser = CurrentUser.OpenSubKey("UserChoice", RegistryKeyPermissionCheck.ReadWriteSubTree, System.Security.AccessControl.RegistryRights.FullControl); CurrentUser.SetValue("Progid", KeyName, RegistryValueKind.String); CurrentUser.Close(); }

¿Alguna idea de por qué no funciona? Un ejemplo de uso podría ser

SetAssociation(".ucs", "UCS_Editor_File", Application.ExecutablePath, "UCS File");

La parte del método que usa "CurrentUser" parece funcionar si hago lo mismo usando regedit, pero al usar mi aplicación no funciona.


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 = ".ucs", ProgId = "UCS_Editor_File", FileTypeDescription = "UCS File", 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($@"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; }


Está utilizando una versión anterior de Visual Studio, Vista tratará su programa como una aplicación de Windows "heredada". Y redirija las escrituras de registro que realiza. Incluya un manifiesto en su programa para que se vea consciente de Vista. Este manifiesto es incluido automáticamente por VS2008 y superior.

Tenga en cuenta que esto aún no resolverá el problema para su usuario, es muy poco probable que ejecute su aplicación con UAC desactivado. Tendrá que escribir una aplicación separada que tenga un manifiesto como vinculado y solicite privilegios de administrador. Necesita el manifiesto con requiredExecutionLevel establecido en requireAdministrator.


La respuesta fue mucho más simple de lo que esperaba. Windows Explorer tiene su propia anulación para el abierto con la aplicación, y yo estaba tratando de modificarlo en las últimas líneas de código. Si solo elimina la anulación del Explorer, entonces la asociación de archivos funcionará.

También le dije al explorador que había cambiado una asociación de archivos llamando a la función no administrada SHChangeNotify()

public static void SetAssociation(string Extension, string KeyName, string OpenWith, string FileDescription) { // The stuff that was above here is basically the same // Delete the key instead of trying to change it CurrentUser = Registry.CurrentUser.OpenSubKey("Software//Microsoft//Windows//CurrentVersion//Explorer//FileExts//" + Extension, true); CurrentUser.DeleteSubKey("UserChoice", false); CurrentUser.Close(); // Tell explorer the file association has been changed SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero); } [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);


La solución anterior no funcionó para mí con Windows 10. Aquí está mi solución para abrir archivos con la extensión .myExt con% localappdata% / MyApp / MyApp.exe para el usuario actual. Optimizado después de leer los comentarios.

String App_Exe = "MyApp.exe"; String App_Path = "%localappdata%"; SetAssociation_User("myExt", App_Path + App_Exe, App_Exe); public static void SetAssociation_User(string Extension, string OpenWith, string ExecutableName) { try { using (RegistryKey User_Classes = Registry.CurrentUser.OpenSubKey("SOFTWARE//Classes//", true)) using (RegistryKey User_Ext = User_Classes.CreateSubKey("." + Extension)) using (RegistryKey User_AutoFile = User_Classes.CreateSubKey(Extension + "_auto_file")) using (RegistryKey User_AutoFile_Command = User_AutoFile.CreateSubKey("shell").CreateSubKey("open").CreateSubKey("command")) using (RegistryKey ApplicationAssociationToasts = Registry.CurrentUser.OpenSubKey("Software//Microsoft//Windows//CurrentVersion//ApplicationAssociationToasts//", true)) using (RegistryKey User_Classes_Applications = User_Classes.CreateSubKey("Applications")) using (RegistryKey User_Classes_Applications_Exe = User_Classes_Applications.CreateSubKey(ExecutableName)) using (RegistryKey User_Application_Command = User_Classes_Applications_Exe.CreateSubKey("shell").CreateSubKey("open").CreateSubKey("command")) using (RegistryKey User_Explorer = Registry.CurrentUser.CreateSubKey("Software//Microsoft//Windows//CurrentVersion//Explorer//FileExts//." + Extension)) using (RegistryKey User_Choice = User_Explorer.OpenSubKey("UserChoice")) { User_Ext.SetValue("", Extension + "_auto_file", RegistryValueKind.String); User_Classes.SetValue("", Extension + "_auto_file", RegistryValueKind.String); User_Classes.CreateSubKey(Extension + "_auto_file"); User_AutoFile_Command.SetValue("", "/"" + OpenWith + "/"" + " /"%1/""); ApplicationAssociationToasts.SetValue(Extension + "_auto_file_." + Extension, 0); ApplicationAssociationToasts.SetValue(@"Applications/" + ExecutableName + "_." + Extension, 0); User_Application_Command.SetValue("", "/"" + OpenWith + "/"" + " /"%1/""); User_Explorer.CreateSubKey("OpenWithList").SetValue("a", ExecutableName); User_Explorer.CreateSubKey("OpenWithProgids").SetValue(Extension + "_auto_file", "0"); if (User_Choice != null) User_Explorer.DeleteSubKey("UserChoice"); User_Explorer.CreateSubKey("UserChoice").SetValue("ProgId", @"Applications/" + ExecutableName); } SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero); } catch (Exception excpt) { //Your code here } } [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);


Puede hacerlo de forma administrada a través de ClickOnce . No te preocupes por el registro tú mismo. Esto está disponible a través de herramientas (es decir, no xml) en VS2008 y superior (incluido Express) en Project Properties => Publish => Options => File Associations


Si escribe las claves en HKEY_CURRENT_USER/Software/Classes lugar de HKEY_CLASSES_ROOT , esto debería funcionar sin privilegios de administrador en Vista y posterior.


Si está usando Visual Studio 2015, instale la extensión de instalación y despliegue. Cree un Asistente de configuración y luego adjunte su archivo .exe. Haga clic con el botón derecho en su programa principal en el explorador de soluciones vaya a -view, -file types, y luego haga clic derecho en los tipos de archivos y seleccione agregar nuevo tipo de archivo. Cambie todas las propiedades a sus necesidades y luego construya el instalador de MSI.

NOTA : volví a leer su pregunta y me di cuenta de que no deseaba un instalador. Perdón por eso, aunque debes considerar usar uno porque te da mucha más personalización sobre tu (s) programa (s).