Encontrar o aplicativo padrão para a abertura de um determinado tipo de arquivo no Windows

StackOverflow https://stackoverflow.com/questions/162331

  •  03-07-2019
  •  | 
  •  

Pergunta

Estou desenvolvendo um aplicativo direcionamento .NET Framework 2.0 usando C # para que eu preciso ser capaz de encontrar o aplicativo padrão que é usado para abrir um tipo de arquivo particular.

Eu sei que, por exemplo, se você só quer 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 têm necessariamente um .txt extensão (por exemplo), no editor de texto padrão, então eu preciso ser capaz de descobrir o aplicativo padrão para a abertura .txt arquivos, que me permita chamá-lo diretamente.

Eu estou supondo que há algum Win32 API que eu vou ter de P / Invoke, a fim de fazer isso, no entanto, um olhar rápido com o Google e MSDN não revelou nada de muito interesse; Eu fiz encontrar um número muito grande de páginas completamente irrelevantes, mas nada como eu estou procurando.

Foi útil?

Solução

Você pode verificar sob registro seção HKEY_CLASSES_ROOT para a extensão e ação detalhes. Documentação para isso é no MSDN . Alternativamente, você pode usar o IQueryAssociations interface.

Outras dicas

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

Exemplo de uso:

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

cujas referências bloco de notas.

Ordenado, muito obrigado!

Bart

Aqui está um post de blog com sobre este tópico. Os exemplos de código estão em VB.net, mas deve ser fácil para a porta-los para C #.

Você pode simplesmente consultar o registro. Primeiro obtenha a entrada padrão em HKEY_CLASSES_ROOT \ .ext

Isso vai dar-lhe o nome da classe. Por exemplo .txt tem um padrão de txtfile

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

Isso vai dar-lhe o comando padrão usado.

A resposta final, mas há uma boa Nuget pacote que associações de arquivo alças: Arquivo Associação

Associação Link de arquivo Nuget

O uso é simples, por exemplo, para adicionar todas as extensões de arquivos 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());
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top