使用clickonce应用程序打开filetype(xml)

时间:2014-05-19 12:31:37

标签: c# .net registry clickonce windows-shell

我有一个可离线和在线使用的clickonce应用程序。它用于打开和编辑.xml文件。如果它们的路径作为启动参数(如

)给出,它可以打开.xml文件
"c:Path\Name.appref-ms" "Xmlpath\name.xml"

使用控制台窗口。

现在我想添加一个注册表项,这样我就可以右键单击任何.xml并在打开下找到我的应用程序。我在 HKCR \ .xml \ OpenWithProgids 下添加了一个密钥,并在 HKCR \ myapp.xml \ shell \ open \ command 中添加了一个密钥,但我无法弄清楚,如何编写该命令。我的理解是,该命令应该与我在控制台窗口中可以使用的命令相同,所以我试过

"c:Path\Name.appref-ms" "%1"

这似乎不起作用,我也尝试过很多不同用途的引号但总是得到

name.xml is not a valid win 32 application

作为错误消息。有谁知道,如果我想做什么是可能的,怎么做?


附加信息:
  - 如果我使用它可以使用的可执行文件,只是看起来不能用clickonce thingy

- 应用程序使用如下参数:

if(AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData!=null)
{ 
    //Do something 
}

1 个答案:

答案 0 :(得分:0)

首先,这是结果,shell扩展的外观如何(灰显其他扩展): enter image description here

您需要在注册表中添加一些条目。我为它写了一个注册表助手类。您可以使用它,也可以只应用密钥。您只需调整名称并调用方法EnsureRegistryKeyIntegrity()。注意:我添加了一个配置开关来启用或禁用shell扩展功能。如果你不想把你的shell搞得太多,这可能会很有用。

一个重要事情:您需要使用管理员权限运行该方法,否则您将收到异常。

internal static class RegistryHelper
{
    ////////////////////////////////////////////////
    #region Statics

    /// <summary>
    /// A dictionary of registry roots and their subkeys to handle.
    /// </summary>
    private static readonly Dictionary<RegistryHive, string[]> RegistryKeys = new Dictionary<RegistryHive, string[]>
    {
        {
            RegistryHive.ClassesRoot,
            new []
            {
                @"*\shell\QuickHash",
                @"*\shell\QuickHash\command",
                @"Directory\shell\QuickHash",
                @"Directory\shell\QuickHash\command"
            }
        }
    };

    /// <summary>
    /// The registry default value for the command keys.
    /// </summary>
    private static readonly string RegistryCommandValue;

    #endregion

    ////////////////////////////////////////////////
    #region Constructors

    static RegistryHelper()
    {
        RegistryCommandValue = String.Format("\"{0}\" /file \"%1\"", Assembly.GetExecutingAssembly().Location);
    }

    #endregion

    ////////////////////////////////////////////////
    #region Public Methods

    /// <summary>
    /// Ensures that all required registry keys exist and adjusts their values if required.
    /// </summary>
    public static void EnsureRegistryKeyIntegrity()
    {
        foreach (var registryRoot in RegistryKeys.Keys)
        {
            foreach (var registryKeyName in RegistryKeys[registryRoot])
            {
                if (((App)Application.Current).Config.EnableExplorerContextMenu)
                {
                    var regKey = GetOrAddKey(registryRoot, registryKeyName);
                    AdjustKey(regKey);
                    regKey.Close();
                }
                else
                {
                    DeleteKey(registryRoot, registryKeyName);
                }
            }
        }
    }

    #endregion

    ////////////////////////////////////////////////
    #region Private Methods

    /// <summary>
    /// Gets or adds a specific key for a specific registry root.
    /// </summary>
    /// <param name="registryRoot">The registry root.</param>
    /// <param name="registryKeyName">The registry key.</param>
    /// <returns>Returns the gotten or added registry key.</returns>
    private static RegistryKey GetOrAddKey(RegistryHive registryRoot, string registryKeyName)
    {
        switch (registryRoot)
        {
            case RegistryHive.ClassesRoot:
                return Registry.ClassesRoot.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.ClassesRoot.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.CurrentUser:
                return Registry.CurrentUser.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.CurrentUser.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.LocalMachine:
                return Registry.LocalMachine.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.LocalMachine.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.Users:
                return Registry.Users.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.Users.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.PerformanceData:
                return Registry.PerformanceData.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.PerformanceData.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.CurrentConfig:
                return Registry.CurrentConfig.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.CurrentConfig.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            case RegistryHive.DynData:
                // DynData is obsolete
                return Registry.PerformanceData.OpenSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue) ??
                       Registry.PerformanceData.CreateSubKey(registryKeyName, RegistryKeyPermissionCheck.ReadWriteSubTree);
            default:
                throw new ArgumentOutOfRangeException("registryRoot");
        }
    }

    /// <summary>
    /// Deletes an unused registry key.
    /// </summary>
    /// <param name="registryRoot">The registry root.</param>
    /// <param name="registryKeyName">The registry key.</param>
    private static void DeleteKey(RegistryHive registryRoot, string registryKeyName)
    {
        const string missingRightsText = "You don't have the permissions to perform this action.";
        const string missingRightsCaption = "Error";
        try
        {
            switch (registryRoot)
            {
                case RegistryHive.ClassesRoot:
                    Registry.ClassesRoot.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.CurrentUser:
                    Registry.CurrentUser.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.LocalMachine:
                    Registry.LocalMachine.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.Users:
                    Registry.Users.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.PerformanceData:
                    Registry.PerformanceData.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.CurrentConfig:
                    Registry.CurrentConfig.DeleteSubKeyTree(registryKeyName, false);
                    break;
                case RegistryHive.DynData:
                    // DynData is obsolete
                    Registry.PerformanceData.DeleteSubKeyTree(registryKeyName, false);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("registryRoot");
            }
        }
        catch (SecurityException)
        {
            MessageBox.Show(missingRightsText, missingRightsCaption, MessageBoxButton.OK, MessageBoxImage.Error);
        }
        catch (UnauthorizedAccessException)
        {
            MessageBox.Show(missingRightsText, missingRightsCaption, MessageBoxButton.OK, MessageBoxImage.Error);
        }
    }

    /// <summary>
    /// Adjusts the registry keys value.
    /// </summary>
    /// <param name="regKey">The registry key to adjust.</param>
    private static void AdjustKey(RegistryKey regKey)
    {
        if (regKey.Name.EndsWith("QuickHash"))
        {
            SetExplorerShellName(regKey);
            SetExplorerShellIcon(regKey);
            return;
        }
        if (regKey.Name.EndsWith("command"))
        {
            var keyDefaultValue = regKey.GetValue("") as String;
            if (String.IsNullOrEmpty(keyDefaultValue)
             || keyDefaultValue != RegistryCommandValue)
            {
                regKey.SetValue(null, RegistryCommandValue, RegistryValueKind.String);
            }
            return;
        }

        throw new NotSupportedException("Given registry key is not supported.");
    }

    private static void SetExplorerShellName(RegistryKey regKey)
    {
        const string quickHashDisplayName = "Quick Hash";
        var keyDefaultValue = regKey.GetValue("") as String;
        if (String.IsNullOrEmpty(keyDefaultValue)
            || keyDefaultValue != quickHashDisplayName)
        {
            regKey.SetValue(null, quickHashDisplayName, RegistryValueKind.String);
        }
    }

    private static void SetExplorerShellIcon(RegistryKey regKey)
    {
        var executingAssembly = (new Uri(Assembly.GetExecutingAssembly().CodeBase)).AbsolutePath;
        regKey.SetValue("Icon", String.Format("{0},0", executingAssembly));
    }

    #endregion
}