[a132] FileInstall generates an error

Report problems with documented functionality
TAC109
Posts: 1096
Joined: 02 Oct 2013, 19:41
Location: New Zealand

[a132] FileInstall generates an error

Post by TAC109 » 20 Apr 2021, 22:42

Attempts to use FileInstall generates an error. (BTW the test script also tests #Include which gives rise to the odd line numbers shown in the error messages, otherwise not relevant to the reported bug.)

When using quotes around the first parameter:

Code: Select all

---------------------------
Test21v2.ahk
---------------------------
Error:  Failed

	Line#
	001: SetWorkingDir(A_ScriptDir)
	002: MsgBox('Test21')
	002: MsgBox('test2')
--->	006: fileinstall('test22V2.ahk', 'test22V2.ahk', 1)
	007: Exit

The current thread will exit.
---------------------------
OK   
---------------------------
With no quotes:

Code: Select all

---------------------------
Test21v2.ahk
---------------------------
Warning:  This variable appears to never be assigned a value.

Specifically: global test22V2

	Line#
	001: SetWorkingDir(A_ScriptDir)
	002: MsgBox('Test21')
	002: MsgBox('test2')
--->	006: fileinstall(test22V2.ahk, 'test22V2.ahk', 1)
	007: Exit

For more details, read the documentation for #Warn.
---------------------------
OK   
---------------------------
, followed by:

Code: Select all

---------------------------
Test21v2.ahk
---------------------------
Error:  This variable has not been assigned a value.

Specifically: global test22V2

	Line#
	001: SetWorkingDir(A_ScriptDir)
	002: MsgBox('Test21')
	002: MsgBox('test2')
--->	006: fileinstall(test22V2.ahk, 'test22V2.ahk', 1)
	007: Exit

Try to continue anyway?
---------------------------
Yes   No   
---------------------------
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a132] FileInstall generates an error

Post by lexikos » 21 Apr 2021, 03:48

There is nothing at all special about FileInstall's syntax; it is just an ordinary function, and test22V2.ahk in fileinstall(test22V2.ahk, ...) is a variable and property reference, not literal text.

Even if you specify that the file should be replaced, you cannot copy a file from one location to the same location, because the file must be opened for reading at the same time it is opened for overwriting. FileInstall therefore fails, just as FileCopy fails. As far as I am aware, the only difference from v1 is that an exception is thrown instead of setting ErrorLevel.

I haven't touched it yet since I don't use FileInstall (or generally compile scripts). I was fairly certain Ahk2Exe didn't support the necessary v2 syntax for FileInstall anyway, but I guess you've fixed that now.

I considered a few ways it could be improved:
  • Detect when both paths refer to the same file. The most accurate way I've found so far (but not tested) requires opening the files, calling GetFileInformationByHandle and comparing the volume serial number and file index. This does not work when the same file is referenced by different network file shares (or a network path and local path), which is probably not important for our purposes (it just means an error in that case).
  • Detect when both paths, resolved to full paths, are an exact match. This might be simpler than the above and would still cover the most common case. It would not detect when both paths refer to the same file through different paths (e.g. one through a symbolic link, junction point, network share, drive map, etc.).
  • Allow FileInstall("filename") to mean that the file should be installed into the same location when compiled, and no action should be taken when uncompiled. This is simpler and still covers the most common case, so is preferable. However, I'm not sure how relative paths should behave:
    • Source and destination are both relative to A_ScriptDir, ignoring A_WorkingDir. It's less flexible, but simpler; there's no need to do anything when uncompiled.
    • Source is relative to A_ScriptDir but destination is relative to A_WorkingDir (even when both paths come from the same parameter). More flexible, but it brings back the issue of detecting when the source (A_ScriptDir) and destination (A_WorkingDir) are the same. In other words, it provides a minor convenience but not a fix for the problem.

The error code (A_LastError = ERROR_SHARING_VIOLATION) is too ambiguous to be much help.

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a132] FileInstall generates an error

Post by lexikos » 21 Apr 2021, 05:51

Given that you're testing with fileinstall(), I guess you've probably already noticed or will soon notice: the pattern "i)^FileInstall[, \t]" used in Ahk2Exe does not match function calls.

Note that it is valid for a script to redefine built-in functions, including FileInstall in v2. It could still be useful for Ahk2Exe to parse calls to such a function and add resources as appropriate. It might be sufficient to permit and ignore FileInstall(word, ...) if that's easier than detecting the opening brace of the body. Due to the parentheses, word is never a literal filename in any version.

TAC109
Posts: 1096
Joined: 02 Oct 2013, 19:41
Location: New Zealand

Re: [a132] FileInstall generates an error

Post by TAC109 » 22 Apr 2021, 19:53

Well, my silly mistake lead to an interesting post.
I considered a few ways it could be improved:
Some good ideas here.

I’ll change Ahk2Exe to accept the optional trailing '('. Note that the V2 documentation on this command is not very accurate:
  • source: ”The file name must not contain double quotes ...” is not accurate. In addition source must be supplied as a literal. (Not a reference to a variable, etc.)
  • It should also be mentioned that FileInstallmust be the first function on the line.
  • The example is not very realistic, as the .exe would need administrative privileges to write to this location.
Cheers
My scripts:-
XRef - Produces Cross Reference lists for scripts
ReClip - A Text Reformatting and Clip Management utility
ScriptGuard - Protects Compiled Scripts from Decompilation
I also maintain Ahk2Exe

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a132] FileInstall generates an error

Post by lexikos » 23 Apr 2021, 21:29

source: ”The file name must not contain double quotes ...” is not accurate.
It is accurate. The file name must not contain quote marks, or the program will fail to copy or extract the file. AutoHotkey does not strip out embedded, leading or trailing literal quote characters, even if Ahk2Exe does. You are required to quote the string when literally writing it in the script, but those quote marks are not contained within the path (the value being passed to the function), just as the string value of "a`tb" will not contain the characters ", ` or t. (Filenames can't usually contain control characters anyway.)

Although the original purpose of the statement was likely to prevent authors from wrapping a literal path in quote marks (which is now necessary because expression syntax is used), it is still relevant for paths contained by variables or read from an external source and passed to various other functions (or FileInstall if it accepts variables). However, it isn't mentioned for other functions, and probably isn't helpful here.

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a132] FileInstall generates an error

Post by lexikos » 23 Apr 2021, 22:08

It might be sufficient to permit and ignore FileInstall(word, ...)
I'll add that this could be potentially useful even when calling FileInstall, such as to extract files within a loop (where the file was added by a separate instance of FileInstall() or ;@Ahk2Exe-AddResource). I suppose that a v2 script can actually already do this by making an alias of FileInstall (FileInstallVar := FileInstall) or just not putting it at the start of a line. However, I'd probably end up using the resource API directly to avoid having to list the filenames twice.

The only reasonable use case I've thought of would be superseded by support for wildcards, which is something users have asked about (but I've never cared about). On the compiled side, wildcard support would require enumerating resources to find those matching the pattern, instead of extracting a single resource by exact name. FileInstall in uncompiled scripts could just basically delegate to FileCopy.

Technically, FileInstall for compiled scripts could be implemented entirely as a script function, which could be added by Ahk2Exe; although in that case, the script wouldn't be able to redefine it unless Ahk2Exe specifically allows for that.

Edit: I suppose that permitting FileInstall(word but not other expressions would confuse matters, and having Ahk2Exe silently ignore FileInstall with expressions might be bad, so feel free to ignore any of theses ideas.

lexikos
Posts: 9494
Joined: 30 Sep 2013, 04:07
Contact:

Re: [a132] FileInstall generates an error

Post by lexikos » 26 Apr 2021, 23:44

v2.0-a133 changes FileInstall (uncompiled) to do nothing when source = dest.

I figured that both v1 and v2 could be changed to allow omitting the destination.

I also noticed that if "allow overwrite" is false or omitted, an exception is explicitly thrown for compiled scripts if the file exists. I'm not sure that this is best, as I had thought of it as a choice between overwriting and updating the file every time, or extracting only if it doesn't exist (either because there's no need to extract if it already exists, or to retain user customizations). On the other hand, there's Try FileInstall.

Post Reply

Return to “Bug Reports”