2008-10-02 10 views
47

Je développe une application ciblant .NET Framework 2.0 en utilisant C# pour laquelle je dois pouvoir trouver l'application par défaut utilisée pour ouvrir un type de fichier particulier.Recherche de l'application par défaut pour ouvrir un type de fichier particulier sous Windows

Je sais que, par exemple, si vous voulez juste d'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 est d'ouvrir les fichiers qui n'ont pas forcément une extension .txt (par exemple), dans l'éditeur de texte par défaut, donc je dois être capable de trouver l'application par défaut pour ouvrir .txt fichiers, ce qui me permettra de l'invoquer directement.

Je suppose qu'il y a une API Win32 dont j'ai besoin pour P/Invoke afin de faire cela, mais un coup d'œil rapide avec Google et MSDN n'a pas révélé beaucoup d'intérêt; J'ai trouvé un très grand nombre de pages complètement non pertinentes, mais rien de tel que je cherche.

Répondre

17

Vous pouvez vérifier sous la section de registre HKEY_CLASSES_ROOT pour les détails d'extension et d'action. La documentation pour cela est on MSDN. Vous pouvez également utiliser l'interface IQueryAssociations.

+1

à mon avis, l'utilisation de FindExecutable est la plus belle façon: http://stackoverflow.com/a/9540278/2427749 –

5

Here is a blog post with about this topic. Les exemples de code sont dans VB.net, mais il devrait être facile de les porter en C#.

+1

J'ai pris la liberté de convertir ce code en C# et de le modifier un peu: http: // stackoverflow.com/a/17773554/67824 –

3

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 la classe. Par exemple txt a une valeur par défaut de txtfile

ouvrir ensuite HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command

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

9

Doh! 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 référence le bloc-notes.

Trié, merci beaucoup!

Bart

+0

Qui est '% SystemRoot% \ system32 \ NOTEPAD.EXE% 1'. Ce n'est pas le programme par défaut dans mon cas. En outre, vous ne pouvez pas utiliser 'Process.Start' avec ceci, à cause du littéral'% SystemRoot% 'et du'% 1'. Tout cela nécessite un traitement spécial dans votre code qui ne peut pas être complètement et définitivement couvert, car qui sait quoi d'autre peut être prévu dans une telle chaîne. – bytecode77

51

Toutes les réponses en cours ne sont pas fiables. Le registre est un détail d'implémentation et en effet ce code est cassé sur ma machine Windows 8.1.La bonne façon de faire est d'utiliser l'API Win32, spécifiquement 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 
} 

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

Cela a été refusé, mais a bien fonctionné pour moi avec juste une correction mineure (édité ci-dessus). Vous aurez besoin de "using System.Runtime.InteropServices". Je ne pouvais pas trouver les énumérations, donc les copiés à partir de MSDN: [ASSOCF] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb762471 (v = vs.85) .aspx) et [ASOCSTR] (https://msdn.microsoft.com/en-us/library/windows/desktop/bb762475 (v = vs.85) .aspx). Pour toujours accéder à l'éditeur de texte, j'ai appelé cette méthode avec AssocStr.ASSOCSTR_EXECUTABLE et ".txt". – Giles

+2

C'est vraiment un triste état de choses où les réponses acceptées et hautement votées sont fondamentalement fausses et reposent sur des détails d'implémentation qui peuvent changer avec n'importe quelle mise à jour, alors que l'API officielle est downvoted ... –

+2

Cela a fonctionné avec brio, merci beaucoup! – Cardin

1

Une réponse tardive, mais il y a un bon paquet de NuGet qui gère les associations de fichiers: File Association

Link NUGET File Association

L'utilisation est simple, par exemple pour ajouter toutes les extensions de fichier 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()); 
    } 
} 
Questions connexes