Encontrando o aplicativo padrão para abrir um tipo de arquivo específico no Windows

Eu estou desenvolvendo um aplicativo visando o .NET Framework 2.0 usando C # para o qual eu preciso ser capaz de encontrar o aplicativo padrão que é usado para abrir um tipo de arquivo específico.

Eu sei que, por exemplo, se você quer apenas abrir um arquivo usando esse aplicativo, você pode usar algo como:

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

para abrir um documento HTML no navegador padrão ou

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

para abrir um arquivo de texto no editor de texto padrão.

No entanto, o que eu quero ser capaz de fazer é abrir arquivos que não tenham necessariamente uma extensão .txt (por exemplo), no editor de texto padrão, então eu preciso ser capaz de descobrir o aplicativo padrão para abrir . arquivos txt , o que me permitirá invocá-lo diretamente.

Eu estou supondo que há alguma API Win32 que eu preciso P / Invoke para fazer isso, no entanto, uma olhada rápida com o Google e MSDN não revelou nada de muito interesse; Eu encontrei um número muito grande de páginas completamente irrelevantes, mas nada como eu estou procurando.

Você pode verificar na seção de registro HKEY_CLASSES_ROOT os detalhes da extensão e ação. Documentação para isso está no MSDN . Como alternativa, você pode usar a interface IQueryAssociations .

Todas as respostas atuais não são confiáveis. O registro é um detalhe de implementação e, na verdade, esse código está quebrado na minha máquina Windows 8.1. A maneira correta de fazer isso é usando a API do Win32, especificamente 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 } 

Documentação relevante:

  • AssocQueryString
  • ASSOCF
  • ASSOCSTR

Uso da amostra:

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

Doh! Claro.

 HKEY_CLASSES_ROOT\.txt 

inclui uma referência a

 HKEY_CLASSES_ROOT\txtfile 

que contém uma subchave

 HKEY_CLASSES_ROOT\txtfile\shell\open\command 

que faz referência ao bloco de notas.

Ordenado, muito obrigado!

Bart

Aqui está uma postagem do blog sobre este tópico. Os exemplos de código estão no VB.net, mas deve ser fácil de portá-los para o C #.

Você pode apenas consultar o registro. Primeiro, obtenha a input Padrão em HKEY_CLASSES_ROOT \ .ext

Isso lhe dará o nome da class. Por exemplo, .txt tem um padrão de txtfile

Em seguida, abra HKEY_CLASSES_ROOT \ txtfile \ Shell \ Open \ Command

Isso lhe dará o comando padrão usado.

Uma resposta tardia, mas há um bom pacote NUGET que lida com associações de arquivos: Associação de arquivos

Associação de arquivos NUGET Link

O uso é simples, por exemplo, para adicionar todas as extensões de arquivo permitidas a um menu de contexto:

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