安装后如何手动注册 ClickOnce 文件关联?

Posted

技术标签:

【中文标题】安装后如何手动注册 ClickOnce 文件关联?【英文标题】:How to manually register ClickOnce file associations after installation? 【发布时间】:2012-02-06 13:10:46 【问题描述】:

Microsoft 的ClickOnce deployment system 提供了一个易于使用的文件关联管理器built into the Visual Studio deployment process。开发人员最多可以添加 8 个文件关联,当用户运行 ClickOnce 安装程序时,这些关联将自动与他们的应用程序关联。

不过,我想更进一步:我希望允许用户在安装后从我的应用程序中手动添加或删除其他文件关联。

我有两个动机来实现这一点:

我不会对用户“强制”附加文件关联,这是通过 ClickOnce 部署处理文件关联的方式。 用户可以在闲暇时添加或删除自己独特的文件关联。

棘手的部分:直接将文件类型与可执行文件相关联与 ClickOnce 部署不兼容

与传统的 Windows 应用程序不同,ClickOnce 应用程序不是直接通过其可执行文件启动的。相反,它们是通过一个特殊的.appref-ms 快捷方式启动的,该快捷方式处理幕后的 ClickOnce 魔法(自动更新、在%LOCALAPPDATA% 的混淆目录中定位可执行文件等)。

如果直接通过其可执行文件打开 ClickOnce 部署的应用程序,则会禁用自动更新,并且 ClickOnce 特定方法将不再起作用。因此,我的用例无法使用传统的注册表文件关联。

Visual Studio 如何处理 ClickOnce 文件关联

下图演示了 Visual Studio 2010 的内置 ClickOnce 文件关联管理器。此信息存储在应用程序的 .manifest 文件中,并在安装时添加到 Windows 注册表中。

我已经对我的注册表进行了一些挖掘,并确定了 ClickOnce 安装程序创建的几个条目,以将文件类型与 ClickOnce 部署的应用程序相关联。

我在注册表中找到的 ClickOnce 文件类型关联的示例注册表项:

rundll32.exe dfshim.dll, ShOpenVerbExtension ae74407a-1faa-4fda-9056-b178562cf98f %1

其中ae74407a-1faa-4fda-9056-b178562cf98f 是在注册表中其他几个位置用于关联应用程序的 GUID。

我的目标是了解必须(以编程方式)将哪些信息添加到注册表,以手动将文件与 ClickOnce 部署的应用程序关联。

感谢任何帮助!

【问题讨论】:

看看这个问题:***.com/questions/1387769/…(C++,但概念应该是一样的)。接受的答案有一些非常有用的信息。 您还可以从使用 ProcessExplorer 之类的应用程序中受益,具体查看在 ClickOnce 安装期间设置的内容。 也许 GUID 是当前 clickonce 安装目录的标识符。您是否尝试在注册表中搜索此 GUID? 【参考方案1】:

解决方法: 您可以与位于以下位置的 ClickOnce 应用程序的快捷方式关联:

C:\Users\[Your username]\AppData\Roaming\Microsoft\Windows\Start Menu\[Program folder]\[Shortcut name]

【讨论】:

【参考方案2】:

好的,在遇到同样的问题并进行了一些认真的挖掘之后,我想我有一个解决方案。 Evan Wondrasek 使用 rundll 命令走在正确的道路上,我能够在测试环境中获得以下工作。

基本上 Uri Abramson 是正确的,rundll.exe 命令中的 Guid 是对 clickonce 应用程序的引用,但它没有出现在注册表中的其他任何地方。它引用的实际上是HKCU\Software\Classes 中的其他键。

要使文件引用工作,您首先需要为您的应用程序提供ProgID。据我所知,这可以是您想要的任何内容,也可以是您通常在 Visual Studio 的 ClickOnce 发布菜单中设置的任何内容。

您还需要创建一个新的 Guid,并了解您的应用程序参考 (.appref-ms) 文件的内容。

对于我的示例,我将使用以下内容:

ProgId: FASERVER.TestApp
Guid: ce6b2c69-ec54-4182-a87f-74c5dfe1a03e
AppRefFileContents: http://SomeAddress.SomeDomain/TestApp/TestApp.application#TestApp.application, Culture=neutral, PublicKeyToken=df31b9b884b9be10, processorArchitecture=x86

请在以下代码中使用与上述值相同的值。

首先,使用以下字符串在HKCU\Software\Classes 下创建一个名为FASERVER.TestApp 的新注册表项:

(Default) = SomeFileType
AppId = TestApp.application, Culture=neutral, PublicKeyToken=df31b9b884b9be10, processorArchitecture=x86
DeploymentProviderUrl = http://SomeAddress.SomeDomain/TestApp/TestApp.application
Guid = ce6b2c69-ec54-4182-a87f-74c5dfe1a03e

设置这些值后,创建两个新的子键shellshellex

shell(Default) 值设置为open。然后创建shell的子键openopen的子键command。将command(Default) 值设置为:

rundll32.exe dfshim.dll, ShOpenVerbExtension ce6b2c69-ec54-4182-a87f-74c5dfe1a03e %1

创建一个名为IconHandlershellex 子键并将其(Default) 值设置为ce6b2c69-ec54-4182-a87f-74c5dfe1a03e

导航到HKCU\Software\Classes\CLSID 并使用以下字符串创建一个新密钥ce6b2c69-ec54-4182-a87f-74c5dfe1a03e

(Default) = Shell Icon Handler For Tif File
AppId = TestApp.application, Culture=neutral, PublicKeyToken=df31b9b884b9be10, processorArchitecture=x86
DeploymentProviderUrl = http://SomeAddress.SomeDomain/TestApp/TestApp.application
IconFile = YourIconFile.ico

注意:您的图标必须在 ClickOnce 项目中。

现在在ce6b2c69-ec54-4182-a87f-74c5dfe1a03e 下创建一个名为InProcServer32 的子键,其值如下:

(Default) = dfshim.dll
ThreadingModel = Apartment

最后,我们需要将之前的键与我们想要的文件关联链接起来。为此,请导航至 HKCU\Software\Classes 并为每个所需的文件扩展名执行以下操作。

如下设置 FileExt 字符串:

(Default) = FASERVER.TestApp
AppId = TestApp.application, Culture=neutral, PublicKeyToken=df31b9b884b9be10, processorArchitecture=x86
DeploymentProviderUrl = http://SomeAddress.SomeDomain/TestApp/TestApp.application
Guid = ce6b2c69-ec54-4182-a87f-74c5dfe1a03e

就是这样!你应该完成了。

请注意,这不会将您的应用程序设置为该文件类型的默认程序,而只会在“打开方式”菜单中添加一个“ClickOnce 应用程序支持库”条目。

希望这对我以外的其他人有用,对于冗长的例子感到抱歉。

【讨论】:

【参考方案3】:

您可以使用 Windows Sysinternals Process Monitor(以前称为 RegMon)确定要添加的注册表项。

在您使用具有默认文件关联的 ClickOnce 安装应用程序时捕获事件。它将记录所有注册表操作(很多)。

您需要使用一些过滤器来轻松识别注册表项。

【讨论】:

这个建议对我很有帮助。进程监视器的基本教程可以在http://www.howtogeek.com/school/sysinternals-pro/lesson5/all/找到。【参考方案4】:

如果您想手动注册文件关联,这与 ClickOnce 无关。您可以手动将密钥添加到注册表以设置文件关联。如果您想删除通过单击设置的关联,只需删除注册表项即可。

    private static void SetFileAssociation(string icon, string application, string openArg, string extension , string progId , string description )
    
        Trace.WriteLine("-----Create File Association-----");
        RegistryKey classesKey = Registry.CurrentUser.OpenSubKey(@"Software\Classes", true);
        classesKey.CreateSubKey(extension).SetValue(string.Empty, progId);
        RegistryKey progKey = classesKey.CreateSubKey(progId);
        if (description != null)
        
            progKey.SetValue(string.Empty, description);
        
        if (icon != null)
        
            progKey.CreateSubKey("DefaultIcon").SetValue(string.Empty, icon);
        

        progKey.CreateSubKey(@"Shell\Open\Command").SetValue(string.Empty,
            application + openArg);
        Trace.WriteLine("-----Finish File Association-----");
    

【讨论】:

感谢您的回答。与传统的 Windows 应用程序不同,ClickOnce 应用程序不是通过它们的可执行文件直接启动的。相反,它们由一个特殊的.appref-ms 快捷方式启动,该快捷方式处理幕后的 ClickOnce 魔法(自动更新、在%LOCALAPPDATA% 的混淆目录中定位可执行文件等)。如果直接通过其可执行文件打开 ClickOnce 部署的应用程序,则会禁用自动更新,并且 ClickOnce 特定方法将不再起作用。因此,我的用例无法使用传统的注册表文件关联。 是的,你是对的。该应用程序不会直接启动它的 exe。您的问题有一个解决方案:您不发布应用程序的 exe,您只需创建一个新的 exe,它是您的基本 exe 的包装器,它所做的只是启动您的基本 exe。然后,将基本 exe 作为文件包含到 ClickOnce 部署中。完成这些后,您可以手动将注册表添加到您的基本 exe。但是您需要注意应用程序的更新。您还应该在 ClickOnce 更新后更新注册表中的真实 exe 路径。【参考方案5】:

Assoc 命令呢?

http://support.microsoft.com/kb/184082


联想/?

显示或修改文件扩展名关联

ASSOC [.ext[=[fileType]]]

.ext 指定与文件类型相关联的文件扩展名 fileType 指定与文件扩展名关联的文件类型

键入不带参数的 ASSOC 以显示当前文件关联。 如果仅使用文件扩展名调用 ASSOC,它将显示当前 该文件扩展名的文件关联。不为文件指定任何内容 键入,该命令将删除文件扩展名的关联。


文件关联可以是机器级别或用户级别 - 通常,HKCR 区域中的内容用于机器级文件关联。 HKCU/Software/Classes 区域中的东西是用户自定义(或您为他们自定义)的每个用户的东西。 像“assoc”这样的东西可以在 XP、7 和可能的 Win 8 上运行(虽然我还没有在 win 8 上使用过这个 cmd)。

【讨论】:

以上是关于安装后如何手动注册 ClickOnce 文件关联?的主要内容,如果未能解决你的问题,请参考以下文章

在 ClickOnce 应用程序中包含文件夹

从 Windows 10 运行时,ClickOnce 不会取消注册/重新注册 VSTO 解决方案

如何让ClickOnce进行手动更新

手动更新已签名的 ClickOnce 应用程序会引发 TrustNotGrantedException

如何在卸载时取消注册 wpf clickonce 应用程序?

请教ClickOnce部署