web-dev-qa-db-fra.com

Comment associer une extension de fichier à l'exécutable actuel en C #

J'aimerais associer une extension de fichier à l'exécutable actuel en C # . Ainsi, lorsque l'utilisateur cliquera ensuite sur le fichier dans l'explorateur, il exécutera mon exécutable avec le fichier donné en premier argument ..__ Idéalement, l'icône des extensions de fichiers données serait également définie sur l'icône de mon exécutable ... Merci à tous.

51
Chris

Il ne semble pas exister d'API .Net permettant de gérer directement les associations de fichiers, mais vous pouvez utiliser les classes du registre pour lire et écrire les clés nécessaires.

Vous devrez créer une clé sous HKEY_CLASSES_ROOT en attribuant le nom à votre extension de fichier (par exemple, ".txt"). Définissez la valeur par défaut de cette clé sur un nom unique pour votre type de fichier, tel que "Acme.TextFile". Créez ensuite une autre clé sous HKEY_CLASSES_ROOT avec le nom défini sur "Acme.TextFile". Ajoutez une sous-clé appelée "DefaultIcon" et définissez la valeur par défaut de la clé sur le fichier contenant l'icône que vous souhaitez utiliser pour ce type de fichier. Ajoutez un autre frère appelé "Shell". Sous la clé "Shell", ajoutez une clé pour chaque action que vous souhaitez rendre disponible via le menu contextuel de l'explorateur, en définissant la valeur par défaut de chaque clé sur le chemin de votre exécutable, suivi d'un espace et de "% 1" pour représenter le chemin. au fichier sélectionné.

Par exemple, voici un exemple de fichier de registre permettant de créer une association entre les fichiers .txt et EmEditor:

 Éditeur de registre Windows, version 5.00 

 [HKEY_CLASSES_ROOT\.txt] 
 @ = "Emeditor.txt" 

 [HKEY_CLASSES_ROOT\emeditor.txt] 
 @ = "Texte 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\"" 
40
X-Cubed

De même, si vous décidez d'utiliser le registre, n'oubliez pas que les associations d'utilisateurs actuelles se trouvent sous HKEY_CURRENT_USER\Software\Classes . Il peut être préférable d’ajouter votre application à la place des classes d’ordinateur locales.

Si votre programme sera exécuté par un nombre limité d'utilisateurs, vous ne pourrez pas modifier CLASSES_ROOT de toute façon.

25
Ishmaeel

Si vous utilisez le déploiement ClickOnce, tout cela est géré pour vous (au moins, dans VS2008 SP1); simplement:

  • Propriétés du projet
  • Publier
  • Les options
  • Associés de fichiers
  • (ajoutez ce dont vous avez besoin)

(notez qu'il doit s'agir d'une confiance totale, d'une cible .NET 3.5 et configurée pour une utilisation hors connexion)

Voir aussi MSDN: Comment: créer des associations de fichiers pour une application ClickOnce

11
Marc Gravell

Voici un exemple complet:

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($@"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

Il peut y avoir des raisons spécifiques pour lesquelles vous choisissez de ne pas utiliser de package d'installation pour votre projet, mais un package d'installation est un endroit idéal pour effectuer facilement des tâches de configuration d'application telles que l'enregistrement d'extensions de fichier, l'ajout de raccourcis sur le bureau, etc.

Voici comment créer une association d'extension de fichier à l'aide des outils d'installation intégrés de Visual Studio:

  1. Dans votre solution C # existante, ajoutez un nouveau projet et sélectionnez le type de projet en tant que Other Project Types -> Setup and Deployment -> Setup Project (ou essayez l'Assistant d'installation).

  2. Configurez votre programme d'installation (beaucoup de documents existants pour cela si vous avez besoin d'aide)

  3. Cliquez avec le bouton droit sur le projet d'installation dans l'explorateur de solutions, sélectionnez View -> File Types, puis ajoutez l'extension que vous souhaitez enregistrer avec le programme pour l'exécuter.

Cette méthode présente l’avantage supplémentaire de se nettoyer si un utilisateur exécute la désinstallation de votre application.

7
Paul J

Pour être précis sur le "Registre Windows":

Je crée des clés sous HKEY_CURRENT_USER\Software\Classes (comme Ishmaeel l'a dit)

et suivez les instructions données par X-Cubed.

L'exemple de code ressemble à ceci:

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();
}

Il suffit de vous montrer une brève démonstration, très facile à comprendre. Vous pouvez modifier ces valeurs clés et tout va bien.

5
Strong

Les associations de fichiers sont définies dans le registre sous HKEY_CLASSES_ROOT.

Il y a un exemple VB.NET ici que je suis, vous pouvez porter facilement en C #.

2
Steve Morgan

Le code ci-dessous est une fonction qui devrait fonctionner, il ajoute les valeurs requises dans le registre Windows. Généralement, je lance SelfCreateAssociation (".abc") dans mon exécutable. (constructeur de formulaire ou onload ou onshown) Il mettra à jour l'entrée de registre pour l'utilisateur actuel à chaque exécution de l'exécutable. (bon pour le débogage, si vous avez quelques modifications) . Si vous avez besoin d'informations détaillées sur les clés de registre impliquées, consultez ce lien MSDN.

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

Pour obtenir plus d'informations sur la clé de registre générale ClassesRoot. Voir cet article 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.

Depuis Windows 7, il existe deux outils cmd qui facilitent la création de simples associations de fichiers. Ils sont assoc et ftype . Voici une explication de base de chaque commande.

  • Assoc - associe une extension de fichier (comme ".txt") à un "type de fichier".
  • FType - définit un exécutable à exécuter lorsque l'utilisateur ouvre un "type de fichier" donné.

Notez que ce sont des outils cmd et non des fichiers exécutables (exe). Cela signifie qu'ils ne peuvent être exécutés que dans une fenêtre cmd ou en utilisant ShellExecute avec "cmd/c assoc". Vous pouvez en apprendre plus à leur sujet sur les liens ou en tapant "assoc /?" et "ftype /?" à l'invite cmd. 

Ainsi, pour associer une application à une extension .bob, vous pouvez ouvrir une fenêtre cmd (WindowKey + R, tapez cmd, appuyez sur entrée) et exécutez les opérations suivantes:

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

Ceci est beaucoup plus simple que de jouer avec le registre et que cela fonctionnera probablement dans les futures versions de Windows. 

En résumé, voici une fonction C # pour créer une association de fichier:

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