web-dev-qa-db-fra.com

Recherche de l'application par défaut pour ouvrir un type de fichier particulier sous Windows

Je suis en train de développer une application ciblant .NET Framework 2.0 à l'aide de C # pour laquelle je dois être en mesure de trouver l'application par défaut utilisée pour ouvrir un type de fichier particulier.

Je sais que, par exemple, si vous voulez simplement ouvrir un fichier en utilisant cette application, vous pouvez utiliser quelque chose comme:

System.Diagnostics.Process.Start( "C:\...\...\myfile.html" );

pour ouvrir un document HTML dans le navigateur par défaut, ou

System.Diagnostics.Process.Start( "C:\...\...\myfile.txt" );

pour ouvrir un fichier texte dans l'éditeur de texte par défaut.

Cependant, ce que je veux pouvoir faire, c'est ouvrir des fichiers qui n'ont pas nécessairement une extension . Txt (par exemple), dans l'éditeur de texte par défaut, donc je dois pouvoir trouver sur l'application par défaut pour l'ouverture des fichiers . txt, ce qui me permettra de l'invoquer directement.

Je suppose qu'il y aura une API Win32 que je devrai P/Invoke pour ce faire, cependant un rapide coup d'œil avec Google et MSDN n'a révélé rien d'intéressant; J'ai trouvé un très grand nombre de pages complètement hors de propos, mais rien de tel que je recherche.

52
Bart Read

Vous pouvez vérifier dans la section du registre HKEY_CLASSES_ROOT pour les détails de l'extension et de l'action. La documentation pour cela est sur MSDN . Alternativement, vous pouvez utiliser l'interface IQueryAssociations .

17
curtisk

Toutes les réponses actuelles ne sont pas fiables. Le registre est un détail d'implémentation et en effet un tel code est cassé sur ma machine Windows 8.1. La bonne façon de procéder consiste à utiliser l'API Win32, en particulier AssocQueryString :

using System.Runtime.InteropServices;

[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode)]
public static extern uint AssocQueryString(
    AssocF flags, 
    AssocStr str,  
    string pszAssoc, 
    string pszExtra, 
    [Out] StringBuilder pszOut, 
    ref uint pcchOut
); 

[Flags]
public enum AssocF
{
    None = 0,
    Init_NoRemapCLSID = 0x1,
    Init_ByExeName = 0x2,
    Open_ByExeName = 0x2,
    Init_DefaultToStar = 0x4,
    Init_DefaultToFolder = 0x8,
    NoUserSettings = 0x10,
    NoTruncate = 0x20,
    Verify = 0x40,
    RemapRunDll = 0x80,
    NoFixUps = 0x100,
    IgnoreBaseClass = 0x200,
    Init_IgnoreUnknown = 0x400,
    Init_Fixed_ProgId = 0x800,
    Is_Protocol = 0x1000,
    Init_For_File = 0x2000
}

public enum AssocStr
{
    Command = 1,
    Executable,
    FriendlyDocName,
    FriendlyAppName,
    NoOpen,
    ShellNewValue,
    DDECommand,
    DDEIfExec,
    DDEApplication,
    DDETopic,
    InfoTip,
    QuickTip,
    TileInfo,
    ContentType,
    DefaultIcon,
    ShellExtension,
    DropTarget,
    DelegateExecute,
    Supported_Uri_Protocols,
    ProgID,
    AppID,
    AppPublisher,
    AppIconReference,
    Max
}

Documentation pertinente:

Exemple d'utilisation:

static string AssocQueryString(AssocStr association, string extension)
{
    const int S_OK = 0;
    const int S_FALSE = 1;

    uint length = 0;
    uint ret = AssocQueryString(AssocF.None, association, extension, null, null, ref length);
    if (ret != S_FALSE)
    {
        throw new InvalidOperationException("Could not determine associated string");
    }

    var sb = new StringBuilder((int)length); // (length-1) will probably work too as the marshaller adds null termination
    ret = AssocQueryString(AssocF.None, association, extension, null, sb, ref length);
    if (ret != S_OK)
    {
        throw new InvalidOperationException("Could not determine associated string"); 
    }

    return sb.ToString();
}
66
Ohad Schneider

Ah! Bien sûr.

HKEY_CLASSES_ROOT\.txt

comprend une référence à

HKEY_CLASSES_ROOT\txtfile

qui contient une sous-clé

HKEY_CLASSES_ROOT\txtfile\Shell\open\command

qui fait référence au Bloc-notes.

Trié, merci beaucoup!

Bart

9
Bart Read

Voici un article de blog sur ce sujet. Les exemples de code sont dans VB.net, mais il devrait être facile de les porter en C #.

5
xsl

Vous pouvez simplement interroger le registre. Obtenez d'abord l'entrée par défaut sous HKEY_CLASSES_ROOT\.ext

Cela vous donnera le nom de classe. Par exemple .txt a une valeur par défaut de txtfile

Ouvrez ensuite HKEY_CLASSES_ROOT\txtfile\Shell\Open\Command

Cela vous donnera la commande par défaut utilisée.

3
Tom

Une réponse tardive, mais il existe un bon package NUGET qui gère les associations de fichiers: File Association

Lier l'association de fichiers NUGET

L'utilisation est simple, par exemple pour ajouter toutes les extensions de fichiers autorisées à un menu contextuel:

private void OnMenuSourceFileOpening(object sender, ...)
{   // open a context menu with the associated files + ".txt" files
    if (File.Exists(this.SelectedFileName))
    {
        string fileExt = Path.GetExtension(this.SelectedFileNames);
        string[] allowedExtensions = new string[] { fileExt, ".txt" };
        var fileAssociations = allowedExtensions
            .Select(ext => new FileAssociationInfo(ext));
        var progInfos = fileAssociations
            .Select(fileAssoc => new ProgramAssociationInfo (fileAssoc.ProgID));
        var toolstripItems = myProgInfos
            .Select(proginfo => new ToolStripLabel (proginfo.Description) { Tag = proginfo });
        // add also the prog info as Tag, for easy access
        //  when the toolstrip item is selected
        // of course this can also be done in one long linq statement

        // fill the context menu:
        this.contextMenu1.Items.Clear();
        this.contextMenuOpenSourceFile.Items.AddRange (toolstripItems.ToArray());
    }
}
2
Harald Coppoolse