בהמשך לפוסט הקודם בו נתתי למשתמש תוכנה שתעתיק קבצים מסויימים בבת אחת, רציתי לייצר קיצור דרך על שולחן העבודה.

    כזכור לא רציתי לתת ללקוח אוסף של קבצים רק קובץ אחד, לכן חיפשתי דרך ליצור קיצור דרך ללא תלות ב – reference חיצוני.

    בסוף מצאתי שאני יכול לעבוד עם IShellLink, כל מה שהייתי צריך לעשות היה להגדיר את הקוד הבא:

     

    Code Snippet
    [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);
    }

     

    לאחר מכן יכולתי פשוט להשתמש בו בצורה הזאת:

    Code Snippet
    IShellLink link = (IShellLink)new ShellLink();

    link.SetDescription("The Link Description");
    link.SetPath(Path.Combine("C:\\TestFolder", "MyFile.exe"));
    link.SetArguments("ABC");

    IPersistFile file = (IPersistFile)link;
    string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);

    string linkPath = Path.Combine(desktopPath, "MyFile.lnk");
    file.Save(linkPath, false);

     

    להלן ההסבר:

    1. יצרתי אובייקט מסוג ShellLink (קיצור דרך)
    2. נתתי לו תיאור
    3. הגדרתי להיכן קיצור הדרך מפנה
    4. נתתי לו פרמטר (לא חובה כמובן) שירוץ במזן לחיצה על קיצור הדרך
    5. קיבלתי את הנתיב לשולחן העבודה, ושמרתי שם את הלינק בעזרת אובייקט מסוג IPersistFile.

     

     

    האתגר הבא שעמד לפני, היה להגדיר את קיצור הדרך שירוץ כמנהל, בדרך כלל עושים זאת בלחיצה על Properties של הלינק, לאחר מכן על Advance, ואז על Run As Administrator

    image

     

    לאחר חיפושים, הבנתי שאין API לדבר הזה, אבל הערך הבולייאני נשמר במקום 21 בקובץ והוא צריך להיות מה שיש בו + 32, ועל כן כתבתי את הקוד הבא

    Code Snippet
    byte[] data = File.ReadAllBytes(linkPath);
    data[21] = (byte)(data[21] + 32);

    File.WriteAllBytes(linkPath, data);