C# ClickOnce部署-文件关联未注册

C# ClickOnce部署-文件关联未注册,c#,file,deployment,clickonce,associations,C#,File,Deployment,Clickonce,Associations,下面是问题的简要总结: 摘要: 我设置了ClickOnce应用程序的文件关联,但是,当我运行/更新我的程序时,它们没有注册(如中所示,我试图关联的.bvr文件没有图标,我无法双击它们来启动我的应用程序) 额外信息: 我首先尝试进入属性->发布->选项->文件关联,然后从那里设置关联。尝试失败后,我尝试直接在app.manifest中设置它: <fileAssociation xmlns="urn:schemas-microsoft-com:clickonce.v1" extension="

下面是问题的简要总结:

摘要:

我设置了ClickOnce应用程序的文件关联,但是,当我运行/更新我的程序时,它们没有注册(如中所示,我试图关联的.bvr文件没有图标,我无法双击它们来启动我的应用程序)

额外信息:

我首先尝试进入属性->发布->选项->文件关联,然后从那里设置关联。尝试失败后,我尝试直接在app.manifest中设置它:

<fileAssociation
xmlns="urn:schemas-microsoft-com:clickonce.v1"
extension=".bvr"
description="Behavior File"
progid="GGS.Behavior"
defaultIcon="bvrico.ico"
/>

我读了很多关于这方面的文章,我开始感到沮丧。一些信息:

  • 我已将其设置为完全信任应用程序(在安全->启用ClickOnce安全设置->这是完全信任应用程序下)
  • 我正在使用.NET4.0和VisualStudio2010
  • 启用“脱机”模式
  • 我也处理通过AppDomain传递的数据,但我怀疑这是否真的会改变任何事情

    我想知道可能文件关联只在安装时设置

    不管怎样,我真的希望能对这个问题有所了解。我真的想在我的项目中的文件关联

    提前谢谢大家

    附言: 在Windows XP和Windows 7上测试

    编辑:顺便说一句,我也在微软上发布了这篇文章

    如果有人想把答案也贴在上面。我真的搞不懂这个D

    ClickOnce不以通常的方式传递命令行参数,而是通过

    AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData
    
    因此,在应用程序启动时,您需要检查它是否包含任何字符串,并相应地修改您的启动行为

    这是因为ClickOnce应用程序是通过服务器上的部署清单启动的,而不是通过.exe启动的。顺便说一句:通过属性->发布->选项->文件关联设置文件关联应该可以正常工作

    编辑:(我是如何创建示例应用程序的)

    • 创建windows窗体应用程序
    • 激活ClickOnce安全设置,选择完全受信任的应用程序
    • 在ClickOnce options->descriptions中,设置发布者、套件和产品名称
    • 在ClickOnce选项->文件关联中添加新扩展名
    • 发布应用程序,安装应用程序,测试是否在打开文件时启动(确实如此)
    未提及的所有设置均未被触摸。。。这就是我所做的一切


    看起来这正是您所做的-也许可以尝试创建一个简单的测试应用程序,看看它是否适合您。由于此答案不能真正回答您的问题,请在完成后通知我,以便我可以将其删除。

    您确定以下项目没有出现在Open With。。。文件选项-Clickonce应用程序部署支持库是否带有问号图标?尝试将其设置为默认值


    我和你的问题一样,但我注意到这个奇怪的选项在我安装应用程序后出现。经过这么多的尝试和谷歌搜索,我尝试了一件简单的事情——同意将这个Clickonce应用程序部署支持库作为所需文件类型的默认设置。还有塔达!文件的图标变成了我的应用图标,它启动了我的应用。我想问题是我想要的文件类型已经与记事本关联,因此ClickOnce拒绝覆盖此设置。

    当我们增加版本号并在不同的子文件夹下发布应用程序时,发生了这种情况。 比如说

    • 版本1.0已发布到
      \\server\product\Version 1.0\
    • 版本2.0已发布到
      \\server\product\Version 2.0\
    我按照@EvAlex的回答,出现了一个对话框,我点击了“详细信息”按钮,打开了一个日志文件。在日志文件中,我注意到程序试图从旧版本的路径下载,它所寻找的路径仍然是
    \\server\product\version 1.0\

    然后我意识到它应该在注册处

    我打开了
    regedit
    ,搜索了
    product
    (这是我的产品名),在以下几个键下找到了日志错误投诉的路径:

    • HKEY_当前用户\软件\类.myext
    • HKEY\ U当前\用户\软件\类\ MyProgId
    • HKEY\U类\U根\MyProgId
    我删除了那些键,并重复了用操作打开的
    ,图标又回来了,然后它像一个符咒一样工作


    因此,该应用程序似乎未完全卸载,或者由于未知原因,存在ClickOnce更新这些密钥的错误。

    如果您尝试注册的文件类型以前已在其他程序(如记事本)中注册过,甚至在记事本中打开过,然后我发现让它工作的唯一方法是从注册表中删除两个位置的文件类型,然后重新启动。之后发布应用程序的更新,如果是这样的问题,你的状态会很好

    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.bvr

    HKEY_CLASSES_ROOT\.bvr

    重新启动


    发布应用程序更新。

    我发现上面艾伦的帖子非常有用。它在我的一台电脑上为我写的,但在另一台电脑上,它并没有让我达到目的。我本想在他的帖子上加一条评论,但Stack Overflow说我没有这方面的声望

    如果你需要它,希望你能在这里找到它

    对于每个扩展映射,我还必须删除一个键,如下所示:

    HKEY_CLASSES_ROOT\AppName.FileType.0
    

    将此项添加到Adam删除其他
    .ext
    项的操作中,解决了我的另一台机器上的问题。

    在ClickOnce部署后使此项工作的唯一方法是在代码中添加/更新几个注册表项。见下文

    已经8年了,甚至在最新版本的VisualStudio2019和Windows10中也是如此
    Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.xxxxxx
    
    Computer\HKEY_CLASSES_ROOT\xxxxxxxxxxx
    
    using Microsoft.Win32;
    using System;
    using System.Collections.Generic;
    
    namespace MyLibrary
    {
        public class FileAssociations
        {
            [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 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;
            }
        }
    }
    
    string[] args = Environment.GetCommandLineArgs();
    FileAssociations.SetAssociation(FileExtension, ProgID, FileExtensionDescription, args[0]);