it-swarm-pt.tech

Como associar uma extensão de arquivo para o executável atual em c #

Gostaria de associar uma extensão de arquivo ao executável atual em C #. Dessa forma, quando o usuário clicar no arquivo posteriormente no Explorer, ele executará meu executável com o arquivo fornecido como o primeiro argumento. O ideal seria também definir o ícone das extensões de arquivo para o ícone do meu executável. Obrigado a todos.

51
Chris

Não parece haver uma API .Net para gerenciar diretamente as associações de arquivos, mas você pode usar as classes do Registro para ler e gravar as chaves necessárias.

Você precisará criar uma chave em HKEY_CLASSES_ROOT com o nome definido para sua extensão de arquivo (por exemplo: ".txt"). Defina o valor padrão dessa chave para um nome exclusivo para o tipo de arquivo, como "Acme.TextFile". Em seguida, crie outra chave em HKEY_CLASSES_ROOT com o nome definido como "Acme.TextFile". Adicione uma subchave chamada "DefaultIcon" e defina o valor padrão da chave para o arquivo que contém o ícone que você deseja usar para este tipo de arquivo. Adicione outro irmão chamado "Shell". Sob a chave "Shell", adicione uma chave para cada ação que você deseja ter disponível através do menu de contexto do Explorer, definindo o valor padrão de cada chave para o caminho do executável seguido por um espaço e "% 1" para representar o caminho para o arquivo selecionado.

Por exemplo, aqui está um arquivo de registro de amostra para criar uma associação entre os arquivos .txt e o EmEditor:

 Windows Registry Editor Versão 5.00 
 
 [HKEY_CLASSES_ROOT\.txt] 
 @ = "Emeditor.txt" 
 
 [HKEY_CLASSES_ROOT\emeditor.txt] 
 @ = "Documento de Texto" 
 
 [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\comando] 
 @ = "\" C: \\ Arquivos de Programas \\ EmEditor \\ EMEDITOR.EXE\"\"% 1\"" 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\imprimir] 
 
 [HKEY_CLASSES_ROOT\emeditor.txt\Shell\print\comando] 
 @ = "\" C: \\ Arquivos de Programas \\ EmEditor \\ EMEDITOR.EXE\"/ p \"% 1\"" 
40
X-Cubed

Além disso, se você decidir seguir o caminho do registro, tenha em mente que as associações de usuários atuais estão em HKEY_CURRENT_USER\Software\Classes . Pode ser melhor adicionar seu aplicativo lá em vez de classes de máquina local.

Se o seu programa for executado por usuários limitados, você não poderá modificar CLASSES_ROOT de qualquer maneira.

25
Ishmaeel

Se você usar a implantação ClickOnce, tudo isso será feito para você (pelo menos no VS2008 SP1); simplesmente:

  • Propriedades do Projeto
  • Publicar
  • Opções
  • Associações de arquivos
  • (adicione o que você precisa)

(observe que ele deve ser totalmente confiável, ter como alvo o .NET 3.5 e ser definido para uso off-line)

Consulte também MSDN: Como: Criar associações de arquivos para um aplicativo ClickOnce

11
Marc Gravell

Aqui está um exemplo completo:

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([email protected]"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

Pode haver motivos específicos pelos quais você opta por não usar um pacote de instalação para seu projeto, mas um pacote de instalação é um ótimo lugar para executar facilmente as tarefas de configuração do aplicativo, como registrar extensões de arquivo, adicionar atalhos da área de trabalho etc.

Veja como criar associações de extensões de arquivos usando as ferramentas integradas do Visual Studio Install:

  1. Dentro da sua solução C # existente, adicione um novo projeto e selecione o tipo de projeto como Other Project Types -> Setup and Deployment -> Setup Project (ou tente o Assistente de Configuração)

  2. Configure seu instalador (muitos documentos existentes para isso, se precisar de ajuda)

  3. Clique com o botão direito do mouse no projeto de instalação no Solution Explorer, selecione View -> File Types e, em seguida, adicione a extensão que você deseja registrar junto com o programa para executá-lo.

Esse método tem o benefício adicional de limpar depois de si mesmo se um usuário executar a desinstalação de seu aplicativo.

7
Paul J

Para ser específico sobre o modo "Registro do Windows":

Eu crio chaves em HKEY_CURRENT_USER\Software\Classes (como Ishmaeel disse)

e siga as instruções respondidas por X-Cubed.

O código de amostra é semelhante:

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

Basta mostrar a vocês uma demonstração rápida, muito fácil de entender. Você pode modificar esses valores-chave e tudo está pronto.

5
Strong

As associações de arquivos são definidas no registro em HKEY_CLASSES_ROOT.

Há um exemplo de VB.NET aqui que eu sou você pode portar facilmente para c #.

2
Steve Morgan

O código abaixo é uma função que deve funcionar, ele adiciona os valores necessários no registro do Windows. Normalmente eu corro SelfCreateAssociation (". Abc") no meu executável. (construtor de formulário ou onload ou onshown) Ele atualizará a entrada do registrador para o usuário atual, toda vez que o executável for executado. (bom para depuração, se você tiver algumas alterações). Se você precisar de informações detalhadas sobre as chaves de registro envolvidas, verifique este link do MSDN.

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

Para obter mais informações sobre a chave geral do Registro ClassesRoot. Veja este artigo do MSDN.

https://msdn.Microsoft.com/pt-br/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.

Existem duas ferramentas cmd que existem desde o Windows 7, o que torna muito fácil criar associações de arquivos simples. Eles são assoc e ftype . Aqui está uma explicação básica de cada comando.

  • Assoc - associa uma extensão de arquivo (como '.txt') com um "tipo de arquivo".
  • FType - define um executável para ser executado quando o usuário abre um determinado "tipo de arquivo".

Note que estas são ferramentas cmd e não arquivos executáveis ​​(exe). Isso significa que eles só podem ser executados em uma janela cmd ou usando ShellExecute com "cmd/c assoc". Você pode aprender mais sobre eles nos links ou digitando "assoc /?" e "ftype /?" em um cmd Prompt. 

Então, para associar um aplicativo a uma extensão .bob, você poderia abrir uma janela cmd (WindowKey + R, digitar cmd, pressionar enter) e executar o seguinte:

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

Isso é muito mais simples do que mexer com o registro e é mais provável que funcione na versão futura do Windows. 

Resumindo, aqui está uma função C # para criar uma associação de arquivos:

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