简体   繁体   English

使用 C# 将 *.lnk 文件固定到 Windows 7 任务栏

[英]Pin *.lnk file to Windows 7 Taskbar using C#

Even the programmatic pinning of icons in Windows 7 seems it's not permitted (like it says here: http://msdn.microsoft.com/en-us/library/dd378460(v=VS.85).aspx ), there are some methods for doing this by using some VB scripts.即使在 Windows 7 中以编程方式固定图标似乎也是不允许的(就像这里说的: http : //msdn.microsoft.com/en-us/library/dd378460(v=VS.85 ) .aspx ),有一些通过使用一些 VB 脚本来执行此操作的方法。 Someone found a way of doing this in C# like this:有人在 C# 中找到了一种方法,如下所示:

private static void PinUnpinTaskBar(string filePath, bool pin)
{
     if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);

     // create the shell application object
     dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));

     string path = Path.GetDirectoryName(filePath);
     string fileName = Path.GetFileName(filePath);

     dynamic directory = shellApplication.NameSpace(path);
     dynamic link = directory.ParseName(fileName);

     dynamic verbs = link.Verbs();
     for (int i = 0; i < verbs.Count(); i++)
        {
            dynamic verb = verbs.Item(i);
            string verbName = verb.Name.Replace(@"&", string.Empty).ToLower();

            if ((pin && verbName.Equals("pin to taskbar")) || (!pin && verbName.Equals("unpin from taskbar")))
            {

                verb.DoIt();
            }
        }

        shellApplication = null;
}

As can be seen, the code makes use of .NET Framework 4.0 features.可以看出,该代码使用了 .NET Framework 4.0 功能。 The question I want to ask is: can this function be transformed so it would make the same thing, but using just 3.5 Framework?我想问的问题是:这个函数可以转换成同样的东西,但只使用 3.5 框架吗? Any ideas?有任何想法吗?

Simple...简单的...

    private static void PinUnpinTaskBar(string filePath, bool pin) {
        if (!File.Exists(filePath)) throw new FileNotFoundException(filePath);

        // create the shell application object
        Shell shellApplication = new ShellClass();

        string path = Path.GetDirectoryName(filePath);
        string fileName = Path.GetFileName(filePath);

        Folder directory = shellApplication.NameSpace(path);
        FolderItem link = directory.ParseName(fileName);

        FolderItemVerbs verbs = link.Verbs();
        for (int i = 0; i < verbs.Count; i++) {
            FolderItemVerb verb = verbs.Item(i);
            string verbName = verb.Name.Replace(@"&", string.Empty).ToLower();

            if ((pin && verbName.Equals("pin to taskbar")) || (!pin && verbName.Equals("unpin from taskbar"))) {

                verb.DoIt();
            }
        }

        shellApplication = null;
    }

Be sure to add a COM reference to "Microsoft Shell Controls And Automation".请务必添加对“Microsoft Shell 控件和自动化”的 COM 引用。

If you want to keep the existing method of using Activator.CreateInstance so you don't have to have the extra COM interop DLL then you'll have to use reflection.如果您想保留使用 Activator.CreateInstance 的现有方法,这样您就不必拥有额外的 COM 互操作 DLL,那么您必须使用反射。 But that would make the code a lot uglier.但这会使代码更加丑陋。

regardless what localization the Windows user was using:无论 Windows 用户使用什么本地化:

        int MAX_PATH = 255;
        var actionIndex = pin ? 5386 : 5387; // 5386 is the DLL index for"Pin to Tas&kbar", ref. http://www.win7dll.info/shell32_dll.html
        StringBuilder szPinToStartLocalized = new StringBuilder(MAX_PATH);
        IntPtr hShell32 = LoadLibrary("Shell32.dll");
        LoadString(hShell32, (uint)actionIndex, szPinToStartLocalized, MAX_PATH);
        string localizedVerb = szPinToStartLocalized.ToString();

        // create the shell application object
        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));

        string path = Path.GetDirectoryName(filePath);
        string fileName = Path.GetFileName(filePath);

        dynamic directory = shellApplication.NameSpace(path);
        dynamic link = directory.ParseName(fileName);

        dynamic verbs = link.Verbs();
        for (int i = 0; i < verbs.Count(); i++)
        {
            dynamic verb = verbs.Item(i);

            if ((pin && verb.Name.Equals(localizedVerb)) || (!pin && verb.Name.Equals(localizedVerb)))
            {
                verb.DoIt();
                break;
            }
        }

In windows 10 the above methods don't work.在 Windows 10 中,上述方法不起作用。 The "Pin to Taskbar" verb doesn't appear in the list in your program, only in explorer. “固定到任务栏”动词不会出现在您程序的列表中,只会出现在资源管理器中。 For this to work in windows 10, you have two options.要使其在 Windows 10 中工作,您有两个选择。 Either rename you program to explorer.exe, or you have to fool the object in to thinking your program is called explorer.exe.要么将您的程序重命名为 explorer.exe,要么您必须让对象误以为您的程序名为 explorer.exe。 You have to find the PEB and change the Image Path Field.您必须找到PEB并更改图像路径字段。 I wrote a post here on how to do it.在这里写了一篇关于如何做到这一点的帖子。

Update for UWP apps running on Windows 10 with the Fall Creators Update (Build 16299 or higher):使用 Fall Creators Update(内部版本 16299 或更高版本)更新在 Windows 10 上运行的 UWP 应用程序:

You can programmatically pin your own app to the taskbar, just like you can pin your app to the Start menu.您可以以编程方式将您自己的应用程序固定到任务栏,就像您可以将您的应用程序固定到“开始”菜单一样。 And you can check whether your app is currently pinned, and whether the taskbar allows pinning.您可以检查您的应用程序当前是否已固定,以及任务栏是否允许固定。

You can access the TaskbarManager API directly, as described in MS docs .您可以直接访问TaskbarManager API,如MS docs 中所述

I wanted to do this with a WinForms application, but it does not seem like it is going to work because I cannot reference the Windows.Foundation APIs.我想用 WinForms 应用程序来做到这一点,但它似乎不会工作,因为我无法引用Windows.Foundation API。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM