首页 > 解决方案 > WPF程序作为任务栏中的另一个程序打开?

问题描述

问题

我正在使用任何文件上的自定义 Windows上下文菜单项创建一个 C# WPF 程序。

But when any .lnk file ( shortcuts ) are selected and right clicked to be opened with my program through the context menu items, it opens my WPF window in the taskbar with the icon of another program.

.

示例

如此gif所示,当右键单击 discord.lnk 文件并选择我的自定义上下文菜单项之一时,它会将我的 WPF 窗口页面打开为Discord。任何其他 .lnk 文件也会发生同样的情况。

它应该在任务栏中打开它自己的窗口,如此 gif所示。如图所示,如果文件不是.lnk ,它会正常运行。

.

问题

这个问题有哪些可能的解决方案?有没有办法避免.lnk文件这样做,并打开我自己的程序?


应用程序启动代码:

    private void Application_Startup(object sender, StartupEventArgs e)
    {
        Args = e.Args;

        TryAssociate();

        MainWin main = new MainWin();
        main.Show();
    }

// FILE ASSOCIATION

    public static void TryAssociate() { if (!IsAssociated()) Associate(); }
    static bool IsAssociated() { return Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.chi", false) != null; }

    public static void Deassociate()
    {
        try
        {
            Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\.chi");
            Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\Applications\chi.exe");
            Registry.CurrentUser.DeleteSubKeyTree(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.chi");
            Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\*\shell\chi_Action1");
            Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\*\shell\chi_Action2");


            SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
        }
        catch { }
    }

    public static void Associate()
    {
        Deassociate();
        try
        {
            RegistryKey FileReg = Registry.CurrentUser.CreateSubKey(@"Software\Classes\.chi", RegistryKeyPermissionCheck.ReadWriteSubTree);
            RegistryKey AppReg = Registry.CurrentUser.CreateSubKey(@"Software\Classes\Applications\chi.exe", RegistryKeyPermissionCheck.ReadWriteSubTree);
            RegistryKey AppAssoc = Registry.CurrentUser.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.chi", RegistryKeyPermissionCheck.ReadWriteSubTree);

            RegistryKey Encrypt = Registry.CurrentUser.CreateSubKey(@"Software\Classes\*\shell\chi_Action1");
            RegistryKey Decrypt = Registry.CurrentUser.CreateSubKey(@"Software\Classes\*\shell\chi_Action2");

            Encrypt.SetValue("", "Action1 with Chi");
            Encrypt.SetValue("Icon", AppData + "clf_icon.ico");
            //Encrypt.SetValue("MultiSelectModel", "Player");
            Encrypt.CreateSubKey("command").SetValue("", "\"" + AppPath + "\" \"%1\" " + "/Action1");

            Decrypt.SetValue("", "Action2 with Chi");
            Decrypt.SetValue("Icon", AppData + "clf_icon.ico");
            //Decrypt.SetValue("MultiSelectModel", "Player");
            Decrypt.CreateSubKey("command").SetValue("", "\"" + AppPath + "\" \"%1\" " + "/Action2");

            FileReg.CreateSubKey("DefaultIcon").SetValue("", AppData + "clf_icon.ico");
            FileReg.CreateSubKey("PerceivedType").SetValue("", "Document");
            FileReg.CreateSubKey("OpenWithProgids").SetValue(@"Applications\chi.exe", new byte[0], RegistryValueKind.None );

            AppReg.CreateSubKey("shell\\open\\command").SetValue("", "\"" + AppPath + "\" \"%1\" " + "/Open");
            AppReg.CreateSubKey("DefaultIcon").SetValue("", AppData + "clf_icon.ico");

            AppAssoc.CreateSubKey("UserChoice").SetValue("ProgId", @"chi.exe");
        }
        finally
        {
            SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
        }
    }

标签: c#wpfwinformsshellcontextmenu

解决方案


解释:

我一直在研究和发现WPFWinForms中的新事物。其中之一是由于某种原因,当您在regedit上为任何文件创建自定义 shell 命令时,当您尝试在.lnk文件(窗口快捷方式)上使用它们时,它可能会变得如此混乱和错误。发生这种情况是因为快捷方式将解释 shell 命令发送的操作,并使用该快捷方式的根文件 ID 和参数直接打开它。


解决方法:

解决此问题的方法应该是将快捷方式读取为 .lnk 文件而不是快捷方式。(我给出的另一个答案可以达到几乎相同的结果,但它不能修复 .lnk 文件)

为此,我们需要在快捷方式注册表上覆盖我们的自定义 shell 命令(如果您有多个 shell 命令,则应该覆盖所有这些命令)。这是一个例子:

using System;
using Microsoft.Win32;
using System.Runtime.InteropServices;

 

[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern void SHChangeNotify(uint Id, uint Flags, IntPtr Item1, IntPtr Item2);

 

RegistryKey programLnk = Registry.CurrentUser.CreateSubKey(@"Software\Classes\lnkfile\shell\MyProgram");

programLnk.SetValue("", "Open with MyProgram");
programLnk.SetValue("Icon", AppPath);
programLnk.CreateSubKey("command").SetValue("", "\"" + AppPath + "\" \"%1\"");

SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
// This will notify window of the change made in the registry.

这应该可以修复您的程序在任务栏中作为另一个程序打开并为其提供预期的参数。


推荐阅读