Создание ярлыка изменяет путь к целевому

Я пытаюсь создать ярлык (.lnk) в моей файловой системе Windows. Код, который у меня есть, работает нормально. Однако, когда я запускаю одно и то же консольное приложение на сервере Windows 2008R2, он действует по-разному.

Итак, у меня есть консольное приложение, и вот что происходит:
Моя программа просто создает ярлык на рабочем столе с расширением .docx, и все идет хорошо на моем локальном компьютере. Когда я запускаю одно и то же консольное приложение на своем Сервере, он создает тот же ярлык, но target был изменен... он изменил цель на файл .doc.

Другими словами, когда я запускаю консольное приложение:

LocalMachine

Создает MyWordFile.lnk, указывающий на U:\test.docx

Сервер

Создает MyWordFile.lnk, указывая на 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);
    }
}



Обновление

Я заметил, что 4-й символ удаляется из целевого расширения. Итак, когда у меня есть файл "file.abcdef", ссылка указывает на "file.abc". Кроме того, пробелы заменяются для подчеркивания, поэтому указатель "my file.abcd" становится "my_file.abc"

Ответ 1

Создание ярлыка не изменяет имя цели.

Вы видите что-то еще, "my_file.abc" - это короткое имя "my file.abcd". Такие имена всегда создаются в файловой системе, в которой включена функция генерации коротких имен. Почти все они все еще делают, хотя сегодня это очень редко необходимо. Сохранение "my file.abcd", совместимого с программами, которые могут обрабатывать только имена MS-Dos, требует замены пространства и расширения, сокращенного до 3 букв. Вы также часто видите "~ 1" в таких именах, которые используются для усечения имени файла до 8 букв.

Вы можете увидеть короткие имена с помощью DIR /x.

Точно так же, как вы получили краткое имя для этого файла, не ясно из вопроса. Но объявление интерфейса IShellLink, безусловно, неверно, методы не указаны в правильном порядке. Это имеет очень серьезные последствия для интерфейса ComInterfaceType.InterfaceIsIUnknown, вы вызовете неправильный метод во время выполнения. Свойство свойства Path является фактически вторым методом. Вы теперь называете 18-й метод, он не объявляется так трудно угадать, что он может сделать. Ну, что-то очень удивительное, если оно не вызывает исключение, это может быть оценено:) Это не совсем неправдоподобно. Кстати, 17-й метод, который был добавлен, был getter для Целевое свойство, добавленное в более позднюю версию интерфейса. Возможно, вы случайно удалили недокументированного сеттера. Преднамеренно недокументирован.

Просто не объявляйте интерфейс самостоятельно. Лучший способ сделать это - использовать Project > Добавить ссылку > Обзоp > выбрать C:\Windows\System32\Shell32.dll. Более подробно описано в этом сообщении.