关于Windows:如何将文件扩展名与C#中的当前可执行文件相关联

关于Windows:如何将文件扩展名与C#中的当前可执行文件相关联

How to associate a file extension to the current executable in C#

我想将文件扩展名与C#中的当前可执行文件相关联。
这样,当用户随后在资源管理器中单击文件时,它将以给定文件作为第一个参数运行我的可执行文件。
理想情况下,还将给定文件扩展名的图标设置为我的可执行文件的图标。
谢谢大家


似乎没有用于直接管理文件关联的.Net API,但是您可以使用注册表类来读取和写入所需的键。

您需要在HKEY_CLASSES_ROOT下创建一个名称设置为文件扩展名的密钥(例如:"。txt")。将此键的默认值设置为文件类型的唯一名称,例如" Acme.TextFile"。然后在HKEY_CLASSES_ROOT下创建另一个名称设置为" Acme.TextFile"的密钥。添加一个名为" DefaultIcon"的子项,并将该项的默认值设置为包含要用于此文件类型的图标的文件。添加另一个名为" shell"的兄弟姐妹。在"外壳"键下,通过资源管理器上下文菜单为每个希望添加的操作添加一个键,将每个键的默认值设置为可执行文件的路径,后跟一个空格和"%1"以表示该路径到所选文件。

例如,这是一个示例注册表文件,用于在.txt文件和EmEditor之间创建关联:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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""

另外,如果您决定采用注册表方式,请记住当前用户关联位于HKEY_CURRENT_USER Software Classes下。最好将应用程序添加到那里而不是本地计算机类。

如果您的程序将由受限用户运行,则无论如何您将无法修改CLASSES_ROOT。


如果使用ClickOnce部署,则将为您全部处理(至少在VS2008 SP1中);只是:

  • 项目属性
  • 发布
  • 选件
  • 文件关联
  • (添加您需要的任何内容)

(请注意,它必须是完全信任的,目标是.NET 3.5,并且已设置为脱机使用)

另请参见MSDN:如何:为ClickOnce应用程序创建文件关联


这是一个完整的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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;
    }

您可能选择特定的原因来选择不为项目使用安装包,但是安装包是轻松执行应用程序配置任务(例如注册文件扩展名,添加桌面快捷方式等)的好地方。

以下是使用内置的Visual Studio安装工具创建文件扩展名关联的方法:

  • 在现有的C#解决方案中,添加一个新项目,然后选择项目类型为Other Project Types-> Setup and Deployment-> Setup Project(或尝试使用安装向导)

  • 配置您的安装程序(如果需要帮助,可以使用很多现有文档)

  • 右键单击"解决方案资源管理器"中的安装项目,选择View-> File Types,然后添加要注册的扩展以及运行它的程序。

  • 如果用户为您的应用程序运行卸载,则此方法还有一个额外的好处就是可以自行清理。


    要具体说明" Windows注册表"方式:

    我在HKEY_CURRENT_USER Software Classes下创建密钥(如Ishmaeel所说)

    并按照X-Cubed回答的说明进行操作。

    示例代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    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();
    }

    只是向大家展示一个快速演示,非常容易理解。您可以修改这些键值,一切顺利。


    下面的代码是应该起作用的功能,它在Windows注册表中添加了所需的值。通常,我在可执行文件中运行SelfCreateAssociation("。abc")。 (窗体构造函数,onload或onshown)每次执行可执行文件时,它将更新当前用户的注册条目。 (如果有一些更改,则非常适合调试)。
    如果您需要有关所涉及的注册表项的详细信息,请查看此MSDN链接。

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

    获取有关常规ClassesRoot注册表项的更多信息。请参阅此MSDN文章。

    https://msdn.microsoft.com/zh-CN/library/windows/desktop/ms724475(v=vs.85).aspx

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    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
    otepad.exe",@"%SystemRoot%\SYSWOW64
    otepad.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
    otepad.exe"</param>
    /// <param name="
    icon">@"%SystemRoot%\SYSWOW64
    otepad.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);
        }

    文件关联在注册表中的HKEY_CLASSES_ROOT下定义。

    这里有一个VB.NET示例,您可以轻松移植到C#。


    自Windows 7以来,已经有两种cmd工具可供使用,它们使创建简单的文件关联变得非常容易。它们是assoc和ftype。这是每个命令的基本说明。

    • Assoc-将文件扩展名(如" .txt")与"文件类型"相关联。
    • FType-定义当用户打开给定的"文件类型"时运行的可执行文件。

    请注意,这些是cmd工具,而不是可执行文件(exe)。这意味着它们只能在cmd窗口中运行,或通过将ShellExecute与" cmd / c assoc"一起使用来运行。您可以通过链接或键入" assoc /?"来了解有关它们的更多信息。和" ftype /?"在cmd提示下。

    因此,要将应用程序与.bob扩展名关联,可以打开一个cmd窗口(WindowKey + R,键入cmd,按Enter)并运行以下命令:

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

    这比弄乱注册表简单得多,并且在将来的Windows版本中更可能工作。

    打包起来,下面是一个C#函数来创建文件关联:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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;
        }
    }

    推荐阅读

      linux文件异或命令?

      linux文件异或命令?,数字,系统,工作,管理,命令,数据,网络,文件,第一,单位,基

      linux文件复制的命令?

      linux文件复制的命令?,系统,文件,命令,目录,源文件,基本知识,位置,目标,选

      linux命令所有用户?

      linux命令所有用户?,系统,密码,信息,情况,名称,命令,用户,时间,地址,位置,如

      linux命令进入用户?

      linux命令进入用户?,系统,密码,用户,地址,信息,软件,命令,用户名,联系方式,

      linux复制命令文件?

      linux复制命令文件?,系统,文件,命令,目录,基本知识,源文件,目标,文件夹,路

      linux下文件均分命令?

      linux下文件均分命令?,管理,情况,系统,工作,信息,地址,命令,目录,单位,设备,L

      linux命令用户管理?

      linux命令用户管理?,系统,密码,管理,工作,信息,地址,工具,命令,用户,基础,LIn

      linux用户与组的命令?

      linux用户与组的命令?,管理,系统,名称,用户组,密码,用户,命令,情况,信息,单

      linux的文件替换命令?

      linux的文件替换命令?,系统,工作,实时,命令,文件,批量,字符串,内容,方法,表

      linux查文件数量命令?

      linux查文件数量命令?,系统,数据,电脑,命令,文件,信息,代码,对比,软件,第三,l

      linux添加用户的命令?

      linux添加用户的命令?,密码,系统,软件,联系方式,用户,新增,信息,管理人员,

      linux看系统用户命令?

      linux看系统用户命令?,系统,信息,密码,命令,服务,名称,网络,情况,软件,工具,L

      linux赋权用户命令?

      linux赋权用户命令?,系统,密码,用户,权限,地址,状态,数字,软件,管理,电脑,Lin

      linux命令去重文件?

      linux命令去重文件?,系统,工作,命令,信息,数据,环境,代码,文件,目录,操作,Lin

      linux写大文件命令?

      linux写大文件命令?,服务,数据,第三,较大,基础,工具,设备,文件,大小,命令,lin

      linux查询文件夹命令?

      linux查询文件夹命令?,系统,软件,电脑,命令,文件,文件夹,单位,第三,档案,数

      linux匹配文件名命令?

      linux匹配文件名命令?,系统,时间,发行,位置,工具,软件,名称,盘后,电脑,盘中,l

      linux上编辑文件命令?

      linux上编辑文件命令?,系统,信息,工作,状态,命令,文件,标准,检测,工具,设备,L

      改文件名linux命令?

      改文件名linux命令?,名字,软件,文件,命令,位置,系统,文件名,目录,指令,方面,l