0

Windows shortcuts use the Distributed Link Tracking service to get the current location of shortcut target which has moved or renamed when the link is clicked on. Is there any way of obtaining this location programmatically (in C#)?

3
  • Do you mean get the location in which the EXE was launched?
    – Koby Douek
    Commented May 15, 2017 at 12:54
  • When you say "in C#", does the mean that P/Invoke is unacceptable?
    – Anders
    Commented May 15, 2017 at 12:55
  • The location is the location of the shortcut target - there is no .exe involved. I believe the .lnk file stores a unique file identifier which is then used as an argument to the Link Tracking Service, which then updates the target location if it is has changed, which I think is also stored in the .lnk file. I am happy to use any method to get the location, including P/Invoke if this is required Commented May 15, 2017 at 23:59

3 Answers 3

2

Yes. You can use code from this blog article by Jani Järvinen:

class Program
{

    [STAThread]
    static void Main(string[] args)
    {
        const string shortcut = @"C:\test.lnk"; // Shortcut file name here

        string pathOnly = System.IO.Path.GetDirectoryName(shortcut);
        string filenameOnly = System.IO.Path.GetFileName(shortcut);

        Shell32.Shell shell = new Shell32.Shell();
        Folder folder = shell.NameSpace(pathOnly);
        FolderItem folderItem = folder.ParseName(filenameOnly);
        if (folderItem != null)
        {
            Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink;
            Console.WriteLine(link.Path);
        }

        Console.ReadKey();

    }
}
1
  • This very elegant code unfortunately only gets the current stored link target in the .lnk file. If the target is moved or renamed the returned path does not change. Commented May 16, 2017 at 0:55
0

A small addition to the code put up by Devil_coder /Cody Gray does what I need. Adding link.Resolve as shown below, with flags as defined in https://msdn.microsoft.com/en-us/library/windows/desktop/bb773996(v=vs.85).aspx makes link.Path return the current link target.

Shell32.ShellLinkObject link = (Shell32.ShellLinkObject)folderItem.GetLink; link.Resolve(5); Console.WriteLine(link.Path);

1
  • Using the flag value (5 = 4 (update path) + 1 (don't show dialog), the option to not delete the path to a non-existent target is taken. Using the flag value 4, the dialog stating that the Shortcut target has been moved or deleted is shown and asks if the shortcut should be deleted. This dialog is incorrect, as a moved target is dealt with. Commented May 16, 2017 at 1:19
0

It's easy, just use this lambda expression for getting target path or many other informations of shortcut.

public static string GetShortcutTargetFile(string shortcutFilename) => System.IO.File.Exists(shortcutFilename) ? ((IWshShortcut)new WshShell().CreateShortcut(shortcutFilename)).TargetPath : string.Empty;

Not the answer you're looking for? Browse other questions tagged or ask your own question.