我遇到了文件关联问题。我的 C# 应用程序可以为其自己的扩展名设置文件关联,这样用户双击它使用的项目文件就会打开我的应用程序并加载该文件。
这会导致两个第三方组件出现问题。每个组件都使用许可。
双击时,会出现两个组件的许可证对话框。从可执行文件运行应用程序时不会发生这种情况。如果我将相应的文件拖到我的应用程序快捷方式上,应用程序将以该文件启动,并且不会出现许可证对话框。
因此我不得不得出结论,问题出在 Windows 执行文件关联操作的方式上。
编写许可证代码的人告诉我,问题可能是可执行文件名称已更改,而许可证代码拒绝了它。我只能假设这与包含文件名的参数有关。
我曾尝试通过代码中的断点来捕获代码执行,但即使断点位于执行的第一行,也无法实现。无论 Windows 做什么,都会越过该点。
答案1
协会如何运作
当您在 Windows 资源管理器中双击某个文件时,Windows shell 会在注册表中查找该文件的扩展名,以查看该扩展名是否已注册。如果扩展名未注册,Windows 将显示“打开方式”对话框,让用户选择与该文件类型关联的应用程序。如果扩展名已注册,Windows 将使用“打开”命令调用 ShellExecute() 函数。它还会将双击的文件的名称作为命令行参数传递。
不过,关联的作用远不止打开文件那么简单。如果在资源管理器中右键单击文本文件 (.TXT),您将在上下文菜单顶部看到两个项目。第一个项目名为“打开”。选择此菜单项与在资源管理器中双击文件相同。选择“打开”时,NOTEPAD.EXE 将启动并加载所选文件(假设 Windows 默认安装)。第二个菜单项名为“打印”。单击此菜单项将导致打印文件而不显示记事本。
其他文件类型在 Explorer 的上下文菜单中显示的项目更多。例如,如果您右键单击 Microsoft PowerPoint 文件,您将看到名为“打开”、“新建”、“打印”和“显示”的上下文菜单项。特定文件类型的上下文菜单上显示的项目是从注册表中获取的。
在 Windows 中至少有两种方法可以创建文件关联。一种方法是在 Windows 资源管理器中右键单击文件,然后从上下文菜单中选择“打开方式…”。执行此操作后,Windows 将显示“打开方式”对话框。当然,这种方法需要用户干预。部署应用程序时,您可能不想强迫用户手动设置文件关联。
创建关联的更好方法是从应用程序创建各种注册表项。好的安装程序会为您创建注册表项,但有时您需要更好地控制此过程。
注册协会
注册文件关联需要创建两个单独的注册表项。两个项均在HKEY_CLASSES_ROOT
注册表的部分中创建。
文件扩展名键
第一个键是文件扩展名的名称,前面有一个点。
HKEY_CLASSES_ROOT\.zzy
在生产应用程序中,您应该在尝试创建新密钥之前检查注册表以确保密钥不存在。如果密钥已经存在,您的应用程序将需要提示用户替换文件关联,或者准备使用完全不同的文件扩展名。
此键的值与您将要创建的第二个键相关联。实际上,它是第二个键的名称。对于示例程序,我给此键的值赋值为“Test App File”。此值可以是您选择的任何值,但与第一个键一样,您必须确保该键在注册表中尚不存在。
应用程序关联密钥
第二个键具有与第一个键的默认值相同的名称。
HKEY_CLASSES_ROOT\Test App File
此键必须至少有一个子键。Windows 在执行应用程序时使用此子键。整个键的结构如下:
HKEY_CLASSES_ROOT
Test App File
shell
open
command
传递给命令键的字符串是应用程序的完整路径和文件名,后跟%1。 例如:
C:\MyApp\MyApp.exe %1
当 Windows 启动该应用程序时,它会替换%1符号,其中包含在 Windows 资源管理器中双击的文件的路径和文件名。此值将作为命令行参数传递给您的应用程序。
附加键
您还可以在文件关联键下创建其他子键。其中一个子键是键DefaultIcon
。此键用于指定 Windows shell 将在已注册类型的文件旁边显示的图标。如果您只注册了一种文件类型,并且该文件类型应使用应用程序图标,则不需要此键。以下是 DefaultIcon 键的值如何查找指定默认应用程序图标的关联:
C:\MyApp\MyApp.exe,0
这指定应使用应用程序的 EXE 文件中找到的第一个图标作为文件关联的显示图标。如果您的应用程序有多种文件类型,您可以通过更改逗号后面的图标索引来指定其他图标。例如,C++Builder 有项目文件、表单文件、源文件等的图标。如果您查看下面的注册表,HKEY_CLASSES_ROOT\BCBProject\DefaultIcon
您将看到项目文件的图标是图标索引 4(至少对于 C++Builder 4 而言)。
如果要允许用户打印文档,您可以在 open 子键之外添加 print 子键。print 子键的值与 open 子键的值类似,但有一点不同:
C:\MyApp\MyApp.exe /p %1
请注意,此值有一个命令行开关/p插入应用程序名称和%1符号。您的应用程序可以观察/p切换并在检测到切换时采取适当的措施。
您可以为特定文件类型添加任意数量的子键。每个子键的名称将显示在资源管理器上下文菜单中。您只需为每种命令类型添加一个命令行开关,以便您的应用程序可以识别所选的上下文菜单项。如果您为子键提供默认值,Windows 将使用该文本作为上下文菜单项文本。如果您不提供默认值,Windows 将使用键名称本身作为菜单项。
所有信息均取自此文章。