创建快捷方式修改目标路径

Creating shortcut modifies the path to target

我正在尝试在我的 windows 文件系统上创建一个快捷方式 (.lnk)。 我的代码工作正常。但是,当我 运行 相同的控制台应用程序 在 Windows 2008R2 服务器上时,它的行为 不同 .

所以我有我的控制台应用程序,这是发生的事情:
我的程序只是在桌面上创建了一个扩展名为 .docx 的快捷方式,并且在我的本地计算机上一切正常。当我在服务器上 运行 相同的控制台应用程序时,它会创建相同的快捷方式,但 目标已修改 ... 它将目标更改为 。文档 文件。

换句话说,当我 运行 控制台应用程序时:

本地机器

Creates MyWordFile.lnk pointing to U:\test.docx

服务器

Creates MyWordFile.lnk pointing to U:\test.doc


这是一种奇怪的行为。这是代码

代码

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;

namespace TestShortcut
{
    class Program
    {
        static void Main(string[] args)
        {
            //ShortcutTarget
            var sTarget = @"U:\test.docx";

            //ShortCutName
            var sName = @"MyWordFile.lnk";

            IShellLink link = (IShellLink)new ShellLink();
            link.SetPath(sTarget);

            IPersistFile file = (IPersistFile)link;
            string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            file.Save(Path.Combine(desktopPath, sName), false);
        }
    }

    [ComImport]
    [Guid("00021401-0000-0000-C000-000000000046")]
    internal class ShellLink
    {
    }

    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [Guid("000214F9-0000-0000-C000-000000000046")]
    internal interface IShellLink
    {
        void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
        void GetIDList(out IntPtr ppidl);
        void SetIDList(IntPtr pidl);
        void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
        void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
        void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
        void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
        void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
        void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
        void GetHotkey(out short pwHotkey);
        void SetHotkey(short wHotkey);
        void GetShowCmd(out int piShowCmd);
        void SetShowCmd(int iShowCmd);
        void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
        void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
        void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
        void Resolve(IntPtr hwnd, int fFlags);
        void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
    }
}



更新

I noticed that the 4th character gets removed from the target's extension. So, when i have a file "file.abcdef", the link points at "file.abc". Also spaces get replaced for underscores, so "my file.abcd" pointer becomes "my_file.abc"

创建快捷方式不会修改目标名称。

你看到的是别的东西,"my_file.abc" 是 "my file.abcd" 的 short name。此类名称始终在仍启用短名称生成功能的文件系统上创建。几乎所有的人仍然这样做,尽管今天已经很少需要了。保持 "my file.abcd" 与只能处理 MS-Dos 名称的程序兼容确实需要替换 space 并将扩展名缩短为 3 个字母。您还经常在此类名称中看到“~1”,用于将文件名截断为 8 个字母。

您可以看到带DIR /x的简称。

问题中并不清楚您是如何看到该文件的简称的。但是IShellLink接口声明肯定是错误的,方法没有按照正确的顺序列出。这对 ComInterfaceType.InterfaceIsIUnknown 接口有相当严重的后果,您将在运行时调用错误的方法。 Path 属性 setter 实际上是第二种方法。您现在正在调用第 18 个方法,它没有声明,因此很难猜测它可能做什么。好吧,如果它不抛出异常,这是非常令人惊讶的,这符合条件 :) 顺便说一句,这并非完全不可信,添加的第 17 个方法是 getter 用于 Target property,稍后添加界面的版本。您可能会不小心碰到未记录的 setter。有意未记录。

只是不要自己声明接口。最好的方法是使用 Project > Add Reference > Browse button > select C:\Windows\System32\Shell32.dll。 this post.

中有更详细的描述