2009-12-14 35 views
1

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

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

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

谢谢 帕特里克

+0

这是一个耻辱的限制;在ClickOnce的3.5 SP1有这个建于... – 2009-12-14 21:45:02

+0

这在下文[堆栈溢出线程]被彻底回答(http://stackoverflow.com/questions/2993118/how-to-perform-shell-icon-embedding-在视觉工作室 - 10415947分之2010#10415947)。我们一直在使用这个实现,它工作得很好。它也是开源的,并集成到MSBuild中。 – 2012-05-02 14:38:02

回答

1

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

+0

我发现这个http://www.mentalis.org/soft/class.qpx?id=5并将其用作模板,现在我只需要弄清楚如何让图标显示出来,然后加载文件如果它已经在运行,则将其转换为应用程序的一个实例。 – Patrick 2009-12-15 21:37:42

+0

@ patrickst1 - 以这种方式运行应用程序的单个实例本身值得另一个问题。 Windows的默认行为是加载应用程序的新副本,因此您需要进行一些洗牌。 – 2009-12-15 22:03:22

+0

很感谢。所以我除了图标以外都有其他工作,你是在哪里?资源文件夹中的唯一文件(在调试阶段不存在,但这是另一回事)是主应用程序图标。我需要知道我的自定义图标的存储位置。 – Patrick 2009-12-16 19:17:44

0

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

+0

嗨,谢谢这让我更好地了解它如何在系统中工作,但不知道如何运行shell命令在安装程序中。 – Patrick 2009-12-15 21:36:41

+0

@ patrickst1 - 也值得另一个问题。说出你正在使用哪个安装程序。 – 2009-12-15 22:04:06

+0

只是使用VisualStudio 2008创建的默认窗口 – Patrick 2009-12-16 19:54:07

2

wrote this up在几年前的新闻组。浏览它,我发现它不是我写过的最清晰的,但它相当完整。对于它的价值,我也转载如下:


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

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

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

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

做,不过,与“开放”(以及随后的)密钥的唯一的事情,就是创建 另一个关键作为一个所谓的“命令”的一个子项。命令键的默认值必须设置为一个表示该命令的字符串 - 执行该操作所需的命令。例如,“open”键下命令键中的默认字符串可能是“”C:\ Program Files \ JoeBlow \ JoeBlow.exe“”%1“”。请注意您的应用程序的路径\文件名周围的引号和%1。如果路径或文件名中有任何空格,它们只是在应用程序的路径\文件名的周围,但它们绝对是针对32位应用程序的%1的必备条件。 %1就像旧版MS-DOS批处理(.bat)文件中的%1%1被命令行上的第一个参数替换,在这种情况下,该参数将成为应用程序打开文件的文件名。由于您事先并不知道包含应该打开的文件的路径或文件名是否包含空格,因此您必须将引号放在%1左右。

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

有关可替换参数(如上面提到的“%1”)的说明。显然,“%1”参数/可能会被打开的短文件名替换。情况并非总是如此,我还没有弄清楚Windows使用哪些标准来确定它将传递哪些内容。如果注册表中列出的可执行文件路径是长文件名,则Windows将用长文件名替换%1以启动,但如果可执行文件路径是短文件名,或者可以解释为一个,则Windows将替换%1与短文件名。如果您想确保始终获得long文件名,请改为使用“%L”。您可以使用大写L(如我所做的)或小写字母L,但我更喜欢使用大写字母,因为小写字母“l”看起来太像数字“1”。更重要的是,如果你的程序知道如何处理外壳项目ID,你可以得到那个而不是带有“%i”参数的长文件名。同样,大写或小写“i”同样适用,但我发现大写字母“I”难以从小写“l”和数字“1”中分辨出来。如果您不知道壳牌产品编号是什么,那没关系。你可能永远不需要使用一个。

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

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

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

 
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与“注册”开头的所有功能 ,包括RegOpenKeyEx,RegCreateKeyEx,和RegSetValueEx。你也可以通过创建一个“.reg”文件来做到这一点,并简单地使用ShellExecuteEx()来调用“regedit.exe/s”。 (/s使Regedit弹出一个消息框,询问“您确定要将[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”作为文件的第一行,否则将无法正常工作。另外 请务必在最后一行按回车键,否则该行不会被读入。总之,以这种方式将程序添加到注册表并不像听起来那么方便,因为您必须修改REG文件如果您的应用安装在任何地方到C:\ Program Files \ JoeBlow。

上述指令旨在使用C或 C++直接对Win32 API进行编程。对于.NET上的C#,它更容易一些。查看注册表类,或者甚至可以使用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的命令提示符(或以其他方式在你的路径RC.EXE),只需键入:

rc JoeBlow.rc

这么简单。考虑到我已经包含的图标存在,上面的资源脚本应该无错地编译。这将在名为JoeBlow.res的同一目录中创建一个新文件。现在,假设您使用Visual Studio ,您只需编辑项目属性即可包含此资源文件。

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

最后,只是建立你的项目,和急,您可以选择浏览关联您的应用程序文件时,嵌入在本土PE格式的图标访问外壳。现在,如果你设置的HKEY_CLASSES_ROOT\JoeBlowFile\DefaultIcon值要么C:\Program Files\JoeBlow\JoeBlow.exe,1(使用从零开始的索引号),或C:\Program Files\JoeBlow\JoeBlow.exe,-200(使用负的资源标识符,如上面IDI_FILE #define的),你的图标将在资源管理器中显示为.jbf文件。

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

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

+0

嗨,谢谢你,这让我更好地了解它是如何保存在注册表中的。我现在遇到的唯一问题是试图让图标起作用。 – Patrick 2009-12-16 17:46:32

+0

你对图标有什么问题?你如何提供图标?你有它在一个单独的文件(.ico),或者你是否试图编译它到您的.exe或.dll?在关于在C#程序集中包含原生资源的答案中,请参阅我的注释。您必须创建资源脚本(.rc)并使用资源编译器进行编译(启动VS cmd提示符,并使用rc.exe),然后将结果.res文件设置为应用程序资源文件在项目的“应用程序”选项卡中属性。我会尝试用更好的细节稍微更新我的答案。 – 2009-12-16 19:29:28

+0

我已经将它包含在项目的资源中,我只是不知道它在哪里捆绑,我在其中一个清单文件中作了假设,但我不确定。我有一个会在应用程序加载时链接文件类型的类,它只是我无法显示的图标。 – Patrick 2009-12-16 19:53:14