## FileCreateShortcut bug

Report problems with documented functionality
gwarble
Posts: 459
Joined: 30 Sep 2013, 15:01

### FileCreateShortcut bug

noticed what I think is a bug:

Code: Select all

FileCreateShortcut, "S:\IT - Software\Tools\AppName.exe", %A_ProgramsCommon%\AppName\Update now.lnk
S:\ is a mapped network drive. Non-admin user needs elevation to create the shortcut, which means S:\ mapped drive no longer exists.

Created shortcut path is:
S:\IT_-_Software\Tools\Exe.exe
with quotes removed and spaces changes into underscores

When S:\ drive exists, shortcut is created as expected, including quotes

Help files says:
The file does not have to exist at the time the shortcut is created; in other words, shortcuts to invalid targets can be created.
but maybe the folder does??
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
Helgef
Posts: 4461
Joined: 17 Jul 2016, 01:02
Contact:

### Re: FileCreateShortcut bug

The folder where you want to create the link needs to exist, and you need permission to write there.

Cheers.
joefiesta
Posts: 381
Joined: 24 Jan 2016, 13:54
Location: Pa., USA

### Re: FileCreateShortcut bug

this definitely appears worthy of a documentation update. This is too subtle to be gleaned from "The file does not have to exist at the time the shortcut is created; in other words, shortcuts to invalid targets can be created."
safetycar
Posts: 125
Joined: 12 Aug 2017, 04:27

### Re: FileCreateShortcut bug

It also happens with some others like FileMove. In case it's decided to update one, it could be done with others.
lexikos
Posts: 7085
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

### Re: FileCreateShortcut bug

What's the bug? gwarble says that the shortcut is created (success is good; no bug) when S: drive exists, but did not say that the shortcut is not created when S drive does not exist.

It does not matter whether S: drive exists. FileCreateShortcut, "S:\IT - Software\Tools\AppName.exe", test.lnk works for me and I do not have S: drive. Even FileCreateShortcut |foo|, test.lnk will create a shortcut, although it doesn't actually set the target since this isn't a valid path or URL.

By contrast, FileCreateShortcut, "S:\IT - Software\Tools\AppName.exe", %A_ProgramsCommon%\AppName\Update now.lnk does not work for me because %A_ProgramsCommon%\AppName does not exist. This is what Helgef was referring to.

Commands which create directories should always indicate that they do so.
FileCopyDir wrote:Copies a folder along with all its sub-folders and files (similar to xcopy).
FileCreateDir wrote:This command will also create all parent directories given in DirName if they do not already exist.
The OS does not create directories automatically, and in general, neither does AutoHotkey.

Code: Select all

C:\>echo test > foo\bar
The system cannot find the path specified.
gwarble
Posts: 459
Joined: 30 Sep 2013, 15:01

### Re: FileCreateShortcut bug

Edit: This isn't about the destination/LinkFile, rather the "target" parameter of FileCreateShortcut

gwarble wrote:
17 Dec 2018, 14:52
When S:\ drive exists, shortcut is created as expected, including quotes
When S:\ drive doesn't exist:
shortcut pathtarget is:
S:\IT_-_Software\Tools\Exe.exe
with quotes removed and spaces changes into underscores

The "bug" (in my opinion) is that last sentence. If creating the shortcut succeeds, then its target should always match the parameter sent to FileCreateShortcut. The quotes may or may not matter, but "C:\this location\" is definitely not the same file path as "C:\this_location\"

That is, of course, unless those underscores (and stripped quotes) are coming from windows' own api when creating non-existent-target shortcuts, in which case my bad, Microsoft should fix it (and ahk should fail to create maybe?)
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
lexikos
Posts: 7085
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

### Re: FileCreateShortcut bug

I read it backwards and assumed the underscores were to show where the spaces were and not actually part of the path. Now I understand why you think there is a bug. However, as I said, I cannot reproduce the behaviour you describe. Using FileCreateShortcut, "S:\IT - Software\Tools\AppName.exe", test.lnk, the shortcut's target is exactly "S:\IT - Software\Tools\AppName.exe" (copy-pasted from the properties dialog). S drive does not exist. If I map S drive, the result is the same. If I also create the folders and put AppName.exe in, the result is the same.

AutoHotkey doesn't do any processing of the target path. It merely passes the parameter value exactly as is to IShellLink::SetPath. Why do anything more?

Code: Select all

psl->SetPath(aTargetFile);
If you open the lnk file in a text or hex editor, is the path the same as it appears in the properties dialog?

The properties dialog sometimes lies about the target of the shortcut - probably due to link resolution.

You may also try this, which I would expect to produce a shortcut file with the same properties.

Code: Select all

l := FileGetShellLink(A_ProgramsCommon "\AppName\Update now.lnk")
l.Path := """S:\IT - Software\Tools\AppName.exe"""
l.Save()

if !FileExist(lnkpath)
FileOpen(lnkpath, "w")
Loop Files, % lnkpath
lnkpath := A_LoopFileLongPath
SplitPath lnkpath, name, dir
throw
return sl
}
gwarble
Posts: 459
Joined: 30 Sep 2013, 15:01

### Re: FileCreateShortcut bug

Thanks for the explanation.

Its definitely consistent for me in Win7 using Ahk1.1.30.01 U32: When the target doesn't exist, the spaces are changed to underscores. Its not just as its displayed in the properties either, the target is actually wrong. Even more odd, in WinXP I get spaces changes to underscores AND truncated to 8 characters when the target doesn't exist, ie target becomes "S:\IT_-_Sof"

So my guess is that this is actually a Windows bug, or that windows API doesn't technically "allow" creating shortcuts that don't resolve, and that AHK is somehow doing it anyway exposing this bug. And maybe they fixed it in newer windows (don't have one handy now, but if you can't recreate it and are on Win10 that would make sense.)

Edit: I guess its not a Microsoft bug:
https://devblogs.microsoft.com/oldnewthing/20180509-00/?p=98715
According to Raymond:
Apparently SetPath should only be used when the target exists.
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
lexikos
Posts: 7085
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

### Re: FileCreateShortcut bug

It seems to me that understanding how this can be the intended behaviour of SetPath would require a very specific and uncommon point of view. Raymond's explanation doesn't change the fact that the behaviour is at least undocumented, if not contrary to the documentation. I would also say it is counter-intuitive in multiple ways, but I suppose that is more opinion than fact (and ranting about it in further detail seems futile, so I'll stop there).

I will implement this workaround. Thanks.

Edit: Maybe not. The initial article makes the workaround look trivial: create a "simple PIDL" and call SetIDList. However, a "simple PIDL" seems to be something Raymond invented, implemented by the program (not the system) through several helper functions and a class which implements a COM interface. I just want to take this string, and shove it into a lnk file...
gwarble
Posts: 459
Joined: 30 Sep 2013, 15:01

### Re: FileCreateShortcut bug

You're welcome, and thanks for looking into it.

I'm not sure a fix needs to be implemented, but at the very least maybe a note added to the documentation since its a known issue that contradicts the current documentation.

Edit: On ancient versions of windows:
For the easy and undocumented way, Shell32.dll contains a rather neat little undocumented function that essentially duplicates what GetPIDLFromPath does (calls ParseDisplayName with the path passed to it converted to Unicode and returns the path's pidl) called SHSimpleIDListFromPath. Here's the declare:

Declare Function SHSimpleIDListFromPath Lib "shell32" Alias "#162" _
(ByVal szPath As String) As Long
I don't know if this undocumented function survived over the years...
Prior to Windows 7, this function was declared in Shlobj.h. In Windows 7 and later versions, it is declared in Shobjidl.h.

Note This function is available through Windows 7 and Windows Server 2003. It is possible that it will not be present in future versions of Windows.

An alternative to this function is as follows:
Call SHGetDesktopFolder to obtain IShellFolder for the desktop folder.
Get the IShellFolder's bind context (IBindCtx).
Call IShellFolder::ParseDisplayName with the IBindCtx and the path.
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
lexikos
Posts: 7085
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

### Re: FileCreateShortcut bug

SHSimpleIDListFromPath appears to work on Windows 10.0.18362 (v1903).

Having said that, it appears that it cannot be used to create a shortcut to a folder, at least on this version of Windows. The shortcut's properties show the target file type as "File folder", but the icon is blank. The shortcut's default action is "Open with", but it does nothing. "Open File Location" from the shortcut's properties does nothing, but from the context menu it opens the folder containing the shortcut (not target).

This is also what happens if I create a shortcut to a file (even manually) or non-existent target and then create a directory at that location (replacing the file if there was one). Related: FileCreateShortcut not working for folder.

From what I recall reading, the "simple ID list" implements interface functions that return information about the object that the ID list identifies. I suppose that this implementation identifies as a file, not a folder, so maybe it is possible to create a "folder shortcut" to a non-existent/inaccessible target using a custom ID list implementation, but that would require knowing that it should be a folder shortcut first.