Page 1 of 1

FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 30 Apr 2018, 10:24
by zotune

Code: Select all

;requires a 64 bit windows system

;1 - create .lnk shortcut 'C:\test.lnk'
;2 - set target to an executable in 'C:\Program Files', for example: 'C:\Program Files\test.exe'

;3 - run this script:
FileGetShortcut, c:\test.lnk, OutTarget, OutDir
msgbox % OutTarget ;wrong 'C:\Program Files (x86)\test.exe' ;results to x86 Program Files for some reason???
msgbox % OutDir ;correct 'C:\Program Files\'

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 01 May 2018, 09:43
by TheDewd
It sounds like you're executing the code using the 32-bit version of AutoHotkey.

If you run the code using the 64-bit version (AutoHotkeyU64.exe), the path is reported correctly.

I wrote a function to help you with this issue. See below:

Code: Select all

MsgBox, % ShortcutGetTarget("C:\test.lnk")

ShortcutGetTarget(ShortcutPath) {
	FileGetShortcut, % ShortcutPath, OT, OD
	RegExMatch(OD, "\\(.*?)\\", ODM)
	RegExMatch(OT, "\\(.*?)\\", OTM)
	return StrReplace(OT, OTM1, ODM1,, 1)
}

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 01 May 2018, 10:52
by jeeswg
I tried two approaches which unfortunately still got the wrong (32-bit) target, but I share them here to avoid people duplicating the effort. (I tried Wow64DisableWow64FsRedirection and using a ShellLinkObject object.)

Code: Select all

;FolderItem object (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/bb787810(v=vs.85).aspx
;ShellLinkObject object (Windows)
;https://msdn.microsoft.com/en-us/library/windows/desktop/bb774004(v=vs.85).aspx

q:: ;get path of lnk file
vPath := A_Desktop "\MyLink.lnk"
if A_Is64bitOS
	DllCall("kernel32\Wow64DisableWow64FsRedirection", PtrP,0)
FileGetShortcut, % vPath, vTarget
MsgBox, % vTarget

SplitPath, vPath, vName, vDir
oShell := ComObjCreate("Shell.Application")
oItem := oShell.NameSpace(vDir).ParseName(vName)
;MsgBox, % oItem.Name
oLink := oItem.GetLink
MsgBox, % oLink.Path
oShell := oItem := oLink := ""
return

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 01 May 2018, 16:10
by malcev
It can be done with wmi:

Code: Select all

lnk := "C:\My Link.lnk"
msgbox % ComObjGet("winmgmts:").ExecQuery("Select * from Win32_ShortcutFile where Name=""" StrReplace(lnk, "\", "\\") """").ItemIndex(0).Target

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 01 May 2018, 16:47
by jeeswg
- Thanks so much malcev, great find. It gives the correct path even in AHK 32-bit.
- If anybody else has any other approaches for getting link targets, that either do or don't do the file redirection, it would be interesting to see them. Thanks.

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 03 May 2018, 03:22
by lexikos
FileGetShortcut gives you the exact path returned by IShellLink::GetPath.

Adding SLGP_RAWPATH (which "may include environment variables that need to be expanded") doesn't help, presumably because the shell does automatic translation for "Program Files", not just "%ProgramFiles%".

The path given by GetPath is correct, from a certain perspective: it accurately reflects the path that will be executed if the .lnk file is executed by the same type of process as the one calling GetPath. For example, if FileGetShortcut C:\test.lnk returns "C:\Program Files (x86)\test.exe", then Run C:\test.lnk will either execute that file or (if the file doesn't exist) fail.

The 32-bit version of cmd.exe (C:\Windows\SysWow64\cmd.exe) also behaves this way.

I would guess that WMI doesn't do the work directly, but in an external 64-bit worker process or service.

Re: FileGetShortcut: Wrong 'OutTarget' for 64 bit program files

Posted: 05 May 2018, 05:03
by zotune
Thanks for the workaround @malcev.

And thanks for all the hard work you do @lexikos