Как связать расширение файла с текущим исполняемым файлом в C # - PullRequest
51 голосов
/ 16 сентября 2008

Я хотел бы связать расширение файла с текущим исполняемым файлом в C #. Таким образом, когда пользователь щелкает файл впоследствии в проводнике, он запускает мой исполняемый файл с указанным файлом в качестве первого аргумента. В идеале было бы также установить значок для указанных расширений файла на значок моего исполняемого файла. Спасибо всем.

Ответы [ 9 ]

40 голосов
/ 16 сентября 2008

Похоже, что .Net API для непосредственного управления ассоциациями файлов не существует, но вы можете использовать классы Registry для чтения и записи необходимых вам ключей.

Вам потребуется создать ключ в HKEY_CLASSES_ROOT с именем, указанным для вашего расширения файла (например: ".txt"). Установите значение по умолчанию для этого ключа уникальное имя для вашего типа файла, например, «Acme.TextFile». Затем создайте еще один ключ в HKEY_CLASSES_ROOT с именем, установленным в «Acme.TextFile». Добавьте подраздел «DefaultIcon» и задайте значение ключа по умолчанию для файла, содержащего значок, который вы хотите использовать для этого типа файлов. Добавьте еще одного родного брата под названием «ракушка». Под ключом «shell» добавьте ключ для каждого действия, которое вы хотите сделать доступным через контекстное меню проводника, установив значение по умолчанию для каждого ключа, путь к вашему исполняемому файлу, затем пробел и «% 1» для представления пути. к выбранному файлу.

Например, вот пример файла реестра для создания связи между файлами .txt и EmEditor:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.txt]
@="emeditor.txt"

[HKEY_CLASSES_ROOT\emeditor.txt]
@="Text Document"

[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\command]
@="\"C:\\Program Files\\EmEditor\\EMEDITOR.EXE\" \"%1\""

[HKEY_CLASSES_ROOT\emeditor.txt\shell\print]

[HKEY_CLASSES_ROOT\emeditor.txt\shell\print\command]
@="\"C:\\Program Files\\EmEditor\\EMEDITOR.EXE\" /p \"%1\""
25 голосов
/ 16 сентября 2008

Кроме того, если вы решили пойти по пути регистрации, имейте в виду, что текущие ассоциации пользователей находятся под HKEY_CURRENT_USER \ Software \ Classes . Может быть, лучше добавить туда свое приложение, а не классы локальной машины.

Если ваша программа будет запускаться ограниченным числом пользователей, вы все равно не сможете изменить CLASSES_ROOT.

11 голосов
/ 25 августа 2009

Если вы используете развертывание ClickOnce, это все обрабатывается за вас (по крайней мере, в VS2008 SP1); просто:

  • Свойства проекта
  • Публикация
  • Опции
  • File Associatons
  • (добавьте все, что вам нужно)

(обратите внимание, что он должен быть с полным доверием, иметь цель .NET 3.5 и быть установлен для автономного использования)

См. Также MSDN: Как создать файловые ассоциации для приложения ClickOnce

9 голосов
/ 29 июня 2017

Вот полный пример:

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($@"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;
    }
7 голосов
/ 22 мая 2009

Могут быть конкретные причины, по которым вы решите не использовать установочный пакет для своего проекта, но установочный пакет - отличное место для простого выполнения задач по настройке приложения, таких как регистрация расширений файлов, добавление ярлыков на рабочем столе и т. Д.

Ниже описано, как создать сопоставление расширений файлов с помощью встроенных инструментов установки Visual Studio:

  1. В существующем решении C # добавьте новый проект и выберите тип проекта как Other Project Types -> Setup and Deployment -> Setup Project (или попробуйте мастер установки)

  2. Сконфигурируйте свой установщик (достаточно документации для этого, если вам нужна помощь)

  3. Щелкните правой кнопкой мыши проект установки в обозревателе решений, выберите View -> File Types, а затем добавьте расширение, которое вы хотите зарегистрировать, вместе с программой для его запуска.

Этот метод имеет дополнительное преимущество очистки после себя, если пользователь запускает деинсталляцию для вашего приложения.

5 голосов
/ 18 февраля 2015

Если говорить конкретно о способе «Реестр Windows»:

Я создаю ключи в HKEY_CURRENT_USER \ Software \ Classes (как сказал Измаил)

и следуйте инструкциям X-Cubed.

Пример кода выглядит так:

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

Просто покажите вам, ребята, быстрое демо, очень простое для понимания. Вы можете изменить эти ключевые значения, и все хорошо.

2 голосов
/ 24 октября 2017

Код ниже - это функция, которая должна работать, она добавляет необходимые значения в реестр Windows. Обычно я запускаю SelfCreateAssociation (". Abc") в моем исполняемом файле. (конструктор формы или onload или onshown) Он будет обновлять запись в реестре для текущего пользователя каждый раз, когда исполняемый файл выполняется. (хорошо для отладки, если у вас есть некоторые изменения). Если вам нужна подробная информация о ключах реестра, воспользуйтесь этой ссылкой MSDN.

https://msdn.microsoft.com/en-us/library/windows/desktop/dd758090(v=vs.85).aspx

Для получения дополнительной информации об общем разделе реестра ClassesRoot. См. Эту статью MSDN.

https://msdn.microsoft.com/en-us/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 голосов
/ 16 сентября 2008

Ассоциации файлов определены в реестре в разделе HKEY_CLASSES_ROOT.

Вот пример VB.NET здесь , который вы можете легко перенести на C #.

0 голосов
/ 24 октября 2017

Начиная с Windows 7 существует два инструмента cmd, которые позволяют легко создавать простые ассоциации файлов. Это assoc и ftype . Вот основное объяснение каждой команды.

  • Assoc - связывает расширение файла (например, «.txt») с «типом файла».
  • FType - определяет исполняемый файл, запускаемый, когда пользователь открывает заданный «тип файла».

Обратите внимание, что это инструменты cmd, а не исполняемые файлы (exe). Это означает, что их можно запустить только в окне cmd или с помощью ShellExecute с «cmd / c assoc.» Вы можете узнать о них больше по ссылкам или набрав "assoc /?" и "ftype /?" по подсказке cmd.

Таким образом, чтобы связать приложение с расширением .bob, вы можете открыть окно cmd (WindowKey + R, введите cmd, нажмите enter) и запустить следующее:

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

Это намного проще, чем возиться с реестром, и с большей вероятностью будет работать в будущих версиях Windows.

Подводя итог, вот функция C # для создания ассоциации файлов:

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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...