29

I have a bunch of .lnk files and need to treat them differently depending on the target that the shortcut points to. I've found very little of how to this with other languages, but nothing about doing this with powershell.

I've tried this:

$sh = New-Object -COM WScript.Shell
$target = $sh.CreateShortcut('<path>').Target

But this returns an empty string even though I can see in the .lnk properties that the Target is specified.

Any idea on how to accomplish this?

Mythio
  • 671
  • 2
  • 7
  • 18
  • 3
    I seem to be lucky(?) when googling: [use TargetPath](http://powershellblogger.com/2016/01/create-shortcuts-lnk-or-url-files-with-powershell/) – wOxxOm Mar 13 '17 at 11:11
  • I've used [this function](http://stackoverflow.com/questions/484560/editing-shortcut-lnk-properties-with-powershell/21967566#21967566) to get shortcut properties as it returns an object with them all in. – henrycarteruk Mar 13 '17 at 11:27
  • As i replied below, I'm not looking for TargetPath but Target. – Mythio Mar 13 '17 at 13:03
  • 3
    Do not confuse what is presented in the GUI with the actual field names when you manipulate the object with a COM Object. The field you want is in fact `TargetPath`, as indicated in my answer below. – Jeff Zeitlin Mar 13 '17 at 13:21
  • Seems that this never work with \\host\share\xxxx.lnk – fcm Jul 23 '18 at 18:03
  • @fcm it works fine for \\host\share\name.lnk for me. – stephenwade Nov 16 '20 at 23:53

2 Answers2

29

You have made an error in the property; as wOxxOm suggests, you should be using TargetPath rather than Target:

$sh = New-Object -ComObject WScript.Shell
$target = $sh.CreateShortcut('<full-path-to-shortcut>').TargetPath

Google and MSDN were indeed helpful here; additionally, piping objects to Get-Member can often be useful and educational. This question also shows how to manipulate shortcuts using PowerShell, and uses the same technique as seen here.

If you want the arguments to the executable as well, those are stored separately:

$arguments = $sh.CreateShortcut('<full-path-to-shortcut>').Arguments

Again, piping objects to Get-Member - in this case, the object returned by WScript.Shell.CreateShortcut() - provides useful information.

It should be noted that there are issues with using this technique and these calls when the path contains Unicode emoji characters; there is a workaround for this case in this StackOverflow question.

Jeff Zeitlin
  • 9,773
  • 2
  • 21
  • 33
  • This doesn't do what I want. Yes, it gets the TargetPath which is equal to the "Start in" property of the .lnk file, but I want the Target property which includes parameter switches etc. – Mythio Mar 13 '17 at 13:03
  • That's a very interesting assertion, as when I tried it before posting, I got the path of the executable, including the exe file name itself - which is _not_ the "Start In" field of the shortcut. – Jeff Zeitlin Mar 13 '17 at 13:06
  • See the edit above for argument retreival. Note that you did not specify that you wanted the complete information, only that you were not getting the results that you expected - which is not unexpected given that there is no attribute `Target` for a `WScript.Shell.CreateShortcut()` object. – Jeff Zeitlin Mar 13 '17 at 13:19
  • 1
    Thank you Jeff, it seems that was indeed the confusion. This works fine indeed. I'll start using the get-member more as it seems to help a lot :-) – Mythio Mar 13 '17 at 13:22
  • 3
    Important: Make sure you pass the **full path** to `CreateShortcut()`. `TargetPath` will be empty if you pass a relative path (like `.\myshortcut.lnk`). – Sebastian Krysmanski Oct 18 '17 at 07:08
  • 1
    Relative paths are fine, but they're relative to `$sh.CurrentDirectory`, which is independent of `$PWD`, just like anything in **System.IO** (like `[IO.Path]::GetFullPath('file.txt')`) is relative to `[IO.Path]::GetFullPath('.')` (which may match `[Environment]::CurrentDirectory`). – brianary Jun 06 '18 at 20:44
  • Sorry, this doesn't do anything for me. UPD: perhaps because my shortcut targets a Windows Store app. – tolache Sep 09 '22 at 07:55
9

It may seem obvious to experts but to us simpletons there seems to be a key lightbulb moment here:

<full-path-to-shortcut> = the Full Name! Doh!

Make sure you use .FullName if you use Get_ChildItem | ForEach-Object, etc. with the Shell .CreateShortcut call if you want the current target of a shortcut. For me:

  • .CreateShortcut($_.FullName) returned an appropriate value; whereas
  • .CreateShortcut($_) returned 'null'
TylerH
  • 20,799
  • 66
  • 75
  • 101
Old_Idiot
  • 91
  • 1
  • 1