关联文件类型和图标

问题描述 投票:1回答:3

好的,我已经看了一遍,我很难找到如何将自定义文件类型与我的C#应用​​程序相关联。我正在使用Visual Studio 2008,由于公司部署,我仅限于.NET 2.0。

基本上我真正想做的就是允许用户双击我的自定义文件类型或将其拖放到应用程序图标上并加载数据,以及在文件本身上显示自定义图标。我可以通过一个对话框打开文件,一切都很好。

试图阅读Micosoft的在线文档很难理解,并没有真正给我所需的所有细节。如果有人在那里知道我可以在哪里找到一个好的教程或者可以解释它我会很感激。

谢谢帕特里克

c# windows file-association
3个回答
1
投票

这个CodeProject article有一些源代码,通过代码演示文件关联。


2
投票

几年前我在新闻组中的wrote this up。浏览它,我发现它并不是我写过的最清晰的,但它相当完整。对于它的价值,我在下面重印了它:


首先,您需要在HKEY_CLASSES_ROOT下创建一个子键,该子键将包含启动应用程序的命令。您应该将此键命名为半描述性的。您的文件扩展名[s]将映射到此密钥。例如,默认情况下,TXT文件映射到名为txtfile的键。使用此设置的好处是,如果您的应用可以处理多个扩展,则可以将它们全部映射到此键。例如,许多图像编辑应用程序创建一个名为“imagefile”的子键,并将.bmp,.jpg,.gif等映射到该键。我们会将您的密钥称为“JoeBlowFile”。接下来,您需要将新JoeBlowFile键的“default”值设置为一个文本字符串,向用户描述它们具有哪种类型的文件。这是Windows资源管理器中“类型”下显示的内容。同样,要使用TXT文件示例,这里的好字符串将是“文本文件”或“文本文档”。 (默认情况下是后者。)您的字符串可能是“Joe Blow Data”。

现在,在新密钥下,您可以创建另一个名为“DefaultIcon”的子项。顾名思义,这设置了与此类文件一起使用的图标。您应该创建一个自定义图标,以图形方式表示程序处理的文档。您可以将此图标另存为应用程序目录中的ICO文件,但更好的是,您可以将其作为资源包含在EXE或DLL中。无论哪种方式,您都需要将子项的默认值设置为表示ICO,EXE或DLL的完整路径和文件名的字符串。如果文件中有多个图标(特别是如果将其作为EXE或DLL中的资源包含在内),您还需要添加一个逗号,并且基于零的正索引号代表您的哪个图标想要使用资源ID,或使用负资源ID,使用资源脚本中为图标分配的任何ID的否定值。所以你可以,例如“C:\ Program Files \ JoeBlow \ JoeBlow.exe,2”。

上段中C#开发人员的注释。不幸的是,C#项目不能有资源脚本。通过将.NET应用程序添加到项目并将其指定为“嵌入式资源”而添加到.NET应用程序中的资源包含在与以前方法不兼容的新.NET特定格式中。在VS.NET上使用C#正确嵌入应用程序的唯一图标是应用程序图标,可从项目属性访问。如果你需要额外的图标 - 例如。一个图标来表示由您的应用处理的文档文件而不是代表应用程序本身 - 您需要自己包含ICO文件,使用嵌入了图标的C ++编译DLL,或创建和编译资源脚本并包含它来自项目属性的项目。

无论您是否选择使用DefaultIcon密钥,您现在需要在JoeBlowFile密钥下创建一个名为“shell”的子项。在shell键下,您将从上下文菜单(右键单击菜单)为您希望用户能够对文件类型执行的每个命令创建单独的键。这些项目称为“动词”。为了保持一致性,其中一个应该是“打开” - 如果该密钥存在,则该密钥将是默认密钥(即,当用户双击您的类型的文件时,将执行打开命令)。相反,您可以将“shell”键的默认值设置为等于默认情况下要执行的谓词。当用户右键单击您的类型文件时,您可以选择将每个动词键的默认值设置为您希望在上下文菜单中显示的文本。在该文本中可以使用与号(&)来指示下面的字符将加下划线,这意味着用户可以按下与该字符对应的键以从上下文菜单中选择该命令。例如,对于“打开”键,您可以将“打开&Joe Blow的应用程序”作为默认值。那个带有下划线J的文本将出现在该类型文件的上下文菜单中,用户可以按下字母J来启动Joe Blow的应用程序。

但是,你必须做的唯一事情就是使用“open”(和后续)键,创建另一个键作为那个名为“command”的子键。必须将命令键的默认值设置为仅表示执行该操作所需的命令的字符串。例如,“open”键下命令键中的默认字符串可能是“”C:\ Program Files \ JoeBlow \ JoeBlow.exe“”%1“”。请注意应用程序的路径\文件名周围和%1周围的引号。如果路径或文件名中有任何空格,它们只需要围绕应用程序的路径\文件名,但它们绝对是针对32位应用程序的%1的要求。 %1就像旧的MS-DOS批处理(.bat)文件中的%1一样。 %1将替换为命令行中的第一个参数,在这种情况下,该参数将成为应用程序打开的文件的文件名。因为您事先不知道包含您打算打开的文件的路径或文件名是否包含空格,所以必须在%1周围加上引号。

还应包括应用程序的其他必需参数。例如,“print”键下“command”键中的默认值可能是“”C:\ Program Files \ JoeBlow \ JoeBlow.exe“”%1“/ print”,或“”C:\ Program Files \ JoeBlow \ JoeBlow.exe“/ print”%1“”。由您决定如何在应用程序中处理命令行参数。

关于可更换参数的说明,如上文提到的“%1”。显然,“%1”参数/可以用要打开的短文件名替换。情况并非总是如此,我还没有弄清楚Windows使用什么标准来确定它将通过短或长。可能是如果注册表中列出的可执行文件路径是长文件名,Windows将用长文件名替换%1以启动,但如果可执行文件路径是短文件名,或者可以解释为1,则Windows将替换%1短文件名。如果您想确保始终获得长文件名,请改用“%L”。您可以使用大写L(我已经完成)或小写,但我更喜欢使用大写,因为小写“l”看起来太像数字“1”。

更重要的是,如果您的程序知道如何处理Shell项ID,则可以使用“%i”参数获取该文件而不是长文件名。同样,大写或小写“i”同样适合,但我发现大写“I”更难从小写“l”和数字“1”中分离出来。如果您不知道Shell项目ID是什么,那就没关系。你可能永远不需要使用它。

你终于完成了JoeBlowFile键。其余的相对简单。您只需要在HKEY_CLASSES_ROOT下创建(如果它尚不存在)另一个子项,并将其命名为与文档类型的扩展名相同。要使用txtfile示例,名称将为“.txt”(带点,但不带引号)。你的(Joe Blow)可能是“.jbf”(对于Joe Blow文件)。此键的默认值现在必须设置为您创建的第一个键的名称,在我们使用的示例中,这是“JoeBlowFile”。

而已。你在注册表中完成了。请记住,您必须确保您的应用程序以与您在“shell”键下设置的命令一致的方式处理命令行。当您的应用程序启动时,Window将不会自动为您打开该文件...您必须这样做。

从图形上看,它看起来像这样:

HKEY_CLASSES_ROOT 
| +--.jbf = JoeBlowFile 
| 
+--JoeBlowFile = Joe Blow Data 
     | 
     +--DefaultIcon = C:\Program Files\JoeBlow\JoeBlow.exe, 2 
     | 
     +--Shell 
          | 
          +--open = Open with &Joe Blow's App 
          |     | 
          |     +--command = "C:\Program Files\JoeBlow\JoeBlow.exe" "%1" 
          | 
          +--print 
               | 
               +--command = "C:\Program Files\JoeBlow\JoeBlow.exe" "%1" /print

如果您还不知道如何修改注册表,请在MSDN中查找以“Reg”开头的所有函数,包括RegOpenKeyEx,RegCreateKeyEx和RegSetValueEx。您也可以通过创建“.reg”文件以简单的方式执行此操作,并使用ShellExecuteEx()在其上调用“regedit.exe / s”。 (/s让Regedit不会弹出一个消息框,询问“你确定要将[name of file.reg]中的信息添加到注册表中吗?”)REG文件的格式简单直接。这是一个示例REG文件,用于添加上面的“JoeBlow”示例:

REGEDIT4 

[HKEY_CLASSES_ROOT\.jbf]
@="JoeBlowFile"

[HKEY_CLASSES_ROOT\JoeBlowFile]
@="Joe Blow Data"

[HKEY_CLASSES_ROOT\JoeBlowFile\DefaultIcon]
@="C:\\Program Files\\JoeBlow\\JoeBlow.exe, 2"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell]

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\open]
@="Open with &Joe Blow's app"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\open\command]
@="\"C:\\Program Files\\JoeBlow\\JoeBlow.exe\" \"%1\""

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\print]
@="&Print"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\print\command]
@="\"C:\\Program Files\\JoeBlow\\JoeBlow.exe \"%1\" /print" 

确保包含“REGEDIT4”作为文件的第一行,否则它将不起作用。还要确保在最后一行按Enter键,否则该行不会被读入。总之,以这种方式将程序添加到注册表并不像听起来那么方便,因为如果你需要修改你的REG文件,您的应用程序安装在除C:\ Program Files \ JoeBlow之外的任何位置。

上述说明针对的是用户使用C或C ++直接编程到Win32 API。对于.NET上的C#,它更容易一些。请参阅Registry类,或者您甚至可以使用VS.NET中的部署项目以图形方式执行大部分操作。


要向.NET程序集添加本机可访问资源,您需要一个资源脚本。资源脚本是纯文本文件,如代码文件。实际上,这是代码;由资源编译器rc.exe编译的声明性代码。示例资源脚本如下:

#include <windows.h>

#define IDI_APP    100
#define IDI_FILE   200
#define ID_VERSION   1

IDI_APP  ICON "Resources\\Application.ico"
IDI_FILE ICON "Resources\\JowBlowFile.ico"

ID_VERSION VERSIONINFO
    FILEVERSION 1, 0, 19, 186     // change this to your version
    PRODUCTVERSION 1, 0, 19, 186  // change this to your version
    FILEOS VOS__WINDOWS32
    FILETYPE VFT_APP {
        BLOCK "StringFileInfo" {
            BLOCK "040904B0" { // 0x409 = U.S. English, 0x04B0 = dec 1200 = Unicode
                VALUE "CompanyName",      "Joe Blow, Inc.\0"
                VALUE "FileDescription",  "Joe Blow's App\0"
                VALUE "FileVersion",      "1.0.19.186\0" // change this to your version
                VALUE "InternalName",     "JoeBlow\0"
                VALUE "LegalCopyright",   "Copyright © 2008-2009 Joe Blow Incorporated\0"
                VALUE "OriginalFilename", "JoeBlow.exe\0"
                VALUE "ProductName",      "Joe Blow\0"
                VALUE "ProductVersion",   "1.0.19.189\0" // change this to your version
            }
        }
        BLOCK "VarFileInfo" {
            VALUE "Translation", 0x409 /*U.S. English*/, 1200 /*Unicode*/
        }
    }

这样做的最大缺点是您必须手动将版本信息添加到资源脚本中(除非您只想放弃版本信息)。在我的应用程序中,我添加了一个自定义构建步骤,该步骤运行我编写的程序,该程序直接在可执行文件中更新版本信息,这样我就不必手动更新资源脚本中的版本号,但该程序不适合公开发布,超出了本文的范围。

现在,您需要调用资源编译器将此资源脚本构建到二进制资源文件中。将此脚本保存为JoeBlow.rc,然后启动Visual Studio命令提示符。它位于Visual Studio开始菜单文件夹中的Tools下。如果您没有安装Visual Studio,我相信您将rc.exe作为SDK的一部分。微软似乎也提供最新版本here

一旦处于VS cmd提示符(或路径中有rc.exe),只需键入:

rc JoeBlow.rc

就那么简单。鉴于我所包含的图标存在,上述资源脚本应该编译没有错误。这将在名为JoeBlow.res的同一目录中创建一个新文件。现在,假设您使用的是Visual Studio,您所要做的就是编辑项目属性以包含此资源文件。

这些说明适用于Visual Studio 2005或2008.我不记得如何做到这一点,或者即使你可以,在旧版本中,我还没有尝试过2010年,但它可能类似。在解决方案资源管理器中右键单击项目,然后选择“属性”(或从主菜单栏的“项目”菜单中选择“属性”)。在“应用程序”选项卡上,您应该看到第一个选项卡,底部是“资源”组框。在这里,您有两个选项:“图标和清单”或“资源文件”。选择后一个选项。这将启用文本框,您可以在其中键入(或浏览到)新资源文件JoeBlow.res。

最后,只需构建您的项目,并且在浏览与您的应用程序关联的文件时,您可以在shell中访问本机PE格式的嵌入式图标。现在,如果您将HKEY_CLASSES_ROOT\JoeBlowFile\DefaultIcon的值设置为C:\Program Files\JoeBlow\JoeBlow.exe,1(使用从零开始的索引号)或C:\Program Files\JoeBlow\JoeBlow.exe,-200(使用资源标识符的否定,#define上面为IDI_FILE),您的图标将显示在资源管理器中以显示.jbf文件。

要在安装时立即显示新图标,您可能需要刷新shell的图标缓存。我已经找到了如何做here的说明。基本要点是将shell图标大小(在HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics)从其当前值更改为另一个,然后再返回,在每次更改后广播WM_SETTINGCHANGE消息。

祝好运。需要帮助请叫我。


0
投票

Here是关于如何使用命令行实用程序assocftype来执行此操作的讨论。您可以在程序部署期间(或运行应用程序时)调用命令shell来执行此操作。

© www.soinside.com 2019 - 2024. All rights reserved.