Sign in to follow this  
Followers 0
John

Would this be a nitpick bug in FileExists?

11 posts in this topic

FileExists returns a false negative if the path string is quoted. Windows sometimes uses these quotes to distinguish between path and argument parts of a path string. Thus a path variable pulled from the registry must have the quotes stripped or FileExists gives a false negative. The dos exist command, comspec and the FileOpenDialog, with the "File Must Exist" flag set, also allows these quotes.

Fixing this could also provide a method of extend the utility of FileExists and FileOpenDialog's "File Must Exist" flag without breaking any existing scripts. If FileExists optionally allowed these quotes, and only validated the string within the first pair of quotes if they exist, then script developers could easily validate a files existance even when it contains arguments quotes. Such as variables defined by path strings pulled from the registry, user supplied, etc.

Of course a script developer can easily provide this functionality themselves by providing a wrapper function for FileExists.

Share this post


Link to post
Share on other sites



It's not an AutoIt issue, it's a Windows issue, see for an explanation and other alternative workarounds.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Yes, I understand how quotes work in and out of AutoIt. The point here it that when quotes are passed (as strings) in AutoIt FileExists fails, but when quotes are passed as strings from AutoIt to windows it is perfectly valid in all cases. Allowing FileExists to be passed string paths containing the quotes (as strings) then has the advantage of added functionality for working with windows and easily validating paths with arguments, which FileExists normally fails on.

Example:

$str = '"C:Program FilesWindows Media Playerwmplayer.exe"'
$test=FileExists($str)

Returns false. However:

$str = '"C:Program FilesWindows Media Playerwmplayer.exe"'
$test=Run($str)

Works fine, as it does in all cases.

This would allow strings like

'"C:Program FilesWindows Media Playerwmplayer.exe" %1'

to be properly validated as a valid path using FileExists

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

BrewManNH,

Yes, the first quotes should always be consumed by AutoIt to indicate a string. The second treated like windows treats them, as valid parameters to a path. Any beyond that is up to the script developer to deal with.

I know this is a nitpick, but also allows extended functionality if handled properly. I have used the following function as a workaround, and it finds valid paths with args even when no quotes are provided. Though after pulling some path strings from the registry it occurred to me that windows standard behavior makes requiring passing the quotes as strings, to separate paths and arguments, far superior to this method.

Func _FileExistEx($f)
$f=StringReplace($f,'"','',0,2)
Local $a=FileGetAttrib($f)
If StringInStr($a,"D",2) Then Return 1
Local $i=StringInStr($f,' ',2,1,StringInStr($f,'.',2))
Local $s=StringLeft($f,$i)
While $i<=StringLen($s)
$s=StringLeft($f,$i-1)
If FileExists($s) And Not StringInStr(FileGetAttrib($s),'D') Then Return 1
If Not StringInStr($f,' ',0,1,$i) Then Return 0
$i=StringInStr($f,' ',0,1,$i+1)
$s=StringLeft($f,$i)
WEnd
Return SetError(1) ; Shouldn't happen
EndFunc
Edited by John

Share this post


Link to post
Share on other sites

Did you even READ the thread I linked to? Because if you did you would see that it is a Windows issue and NOT an AutoIt issue. Strip the quotes before sending the string to FileExists, that is the ONLY way it's going to work. Read the whole thread and all of the discussion within it and you will see you're beating a dead horse.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Yes, I read the thread. In particular relevance is the _WinAPI_PathFileExists() function demonstrating a windows API handling in the same way as as FileExists. There are 2 points that moot this fact. First, AutoIt is not the windows environment, but an scripting language for interacting with the windows environment. Second, and more importantly, windows does not depend solely on this one API for validating paths, just as I am suggesting with the FileExist() function. Here's a demonstration:

FileOpenDialog ( "title", "init dir", "filter" [, options ] )

1 = File Must Exist (if user types a filename)

2 = Path Must Exist (if user types a path, ending with a backslash)

To use more than one option, add the required values together.

FileOpenDialog('Unquoted path:', @ScriptDir, "All (*.*)",3)

Now if you enter:

"C:Program FilesWindows Media Playerwmplayer.exe"

With or without quotes it comes back a valid path.

Windows is not strictly dependent on PathFileExistsW in shlwapi.dll path validation, but itself preprocesses what subset of a string to validate with that API. This is why paths and arguments are separated by individual sets of string quotes in the registry by default, so that PathFileExistsW can be applied to the proper subset of the string in relevant cases. Otherwise certain command lines would simply be too ambiguous for windows to parse.

For AutoIt, or FileExist in particular, to mimic this behavior requires validating single quoted path strings when passed as strings.

Share this post


Link to post
Share on other sites

There's a link to the BugTracker Wiki page where you can make a feature request for that, but I wouldn't hold my breath waiting for it, as there is an easy way to work around the Window's issue and the devs are reluctant to make changes to things that can be worked around if it creates more work for so very little benefit.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

That is understandable, which is why I called it a nitpick bug. I wouldn't waste too much time simply on saving script developers a few lines of code either. It does seem a relatively straightforward and easy change though.

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

I found a description in MSDN where is is explained exactly how the quotes are used by windows and the routine windows falls back on in their absents.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx

If you are using a long file name that contains a space, use quoted strings to indicate where the file name ends and the arguments begin; otherwise, the file name is ambiguous. For example, consider the string "c:program filessub dirprogram name". This string can be interpreted in a number of ways. The system tries to interpret the possibilities in the following order:

c:program.exe filessub dirprogram name

c:program filessub.exe dirprogram name

c:program filessub dirprogram.exe name

c:program filessub dirprogram name.exe

In effect by AutoIt not accepting these quotes passed as strings as valid it forces windows to fall back into a search routine if this same sting is passed to windows by AutoIt. This can lead to an execution of the wrong program. If you have a path like:

c:program filessub dirprogram name

and a different program path exist like:

c:program filessub dir.exe

Then 'sub dir.exe' get executed in place of 'program name.exe'

This doesn't create a name collision because a 'sub dir' folder, 'sub dir.exe', and 'sub dir.bat' file can all simultaneously exist in the same folder, as well as other executable file types. 'sub.exe dir' is also a valid folder name. So windows does officially support and document the use of quotes passed as path strings. Even without any errors having these quote stings makes windows faster and more efficient without falling back on a search routine. Including the .exe doesn't in itself bypass the search routine since 'name.exe' is a perfectly valid folder name.

Edited by John

Share this post


Link to post
Share on other sites

Hmmm, the more I think about it, the more I agree with John. AutoIt could strip the extra quotes to avoid false negatives and emulate windows functions.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • lrstndm
      By lrstndm
      Hi all,
      I want to check if a file exists under the System32 folder: C:\Windows\System32\inetsrv\rewrite.dll
      The following code always worked for me:
      $string = @SystemDir & "\inetsrv\rewrite.dll" ConsoleWrite(FileExists($string)) But yesterday I updated my Windows 10 with the last "big" update and now my @SystemDir returns the following string:
      C:\Windows\SysWOW64
      And before it was:
      C:\Windows\System32
      So I thought I change my code to:
      $string = @WindowsDir & "\System32\inetsrv\rewrite.dll" ConsoleWrite(FileExists($string)) But this code also does not work. I tried to run it as administrator but this also didn't work.
      What am I doing wrong?
      Regards,
      lrstndm
    • chipmonger
      By chipmonger
      Have the following code snippet:
      If not FileExists($ExchangeDir & $StockCSV) Then _FileWriteFromArray($ExchangeDir & $StockCSV, $YahooStockEntries) Else When trying to do a check against the non-existent file 'PRN.csv', FileExists is evaluating as True.  This is not happening with other file names, directory structure is correct.
      Any ideas?
      Thanks
      Chip
    • Gibbo
      By Gibbo
      Hi All, 
      I went searching for something to speed up checking for files on the network (UNC Paths)
      Most examples were rather complicated but someones multi-threaded solution gave me an idea.
      Hope it is useful to someone.
      Seems to work well so far. 
       
      Func _FileExistsTimeout($sPath, $iTimeout = 1000) Local $hTimer = TimerInit() ; Begin the timer and store the handle in a variable. Local $iPID = Run(@AutoItExe & ' /AutoIt3ExecuteLine "ConsoleWriteError(FileExists(""' & $sPath & '""))"', @ScriptDir, @SW_HIDE, $STDERR_CHILD) Local $sOutput = "" Local $iDiff = 0 While $iDiff < $iTimeout $iDiff = TimerDiff($hTimer) $sOutput &= StderrRead($iPID) If @error Then ; Exit the loop if the process closes or StderrRead returns an error. ExitLoop EndIf WEnd ProcessClose($iPID) Switch StringStripWS($sOutput, 8) Case 1 Return True Case Else Return False EndSwitch EndFunc ;==>_FileExistsTimeout
    • poila
      By poila
      Prior to posting this question, I have experimented with using FileExists, InetGetInfo and InetGet/InetClose functions to test downloading files into my application folder, in case if my file did not already exist.
      In my case, I was able to pinpoint to a very specific web address, eg.) https://dropbox.com, etc. and then check/download the file.
      Now my question is, instead of checking from a hardcoded URL, is it possible to:
      1. Do a check against the IP address of a remote computer, eg.) my friend's or colleague's desktop computer
      2. After checking the IP address if valid and can be connected to, access the computer's hard drive location, eg.) that machine's C:specifiedFolderspecifiedFile.txt
      3. Download a copy of that file into a local computer
      I did read ('?do=embed' frameborder='0' data-embedContent>>) but that was what I accomplished earlier, so now I am not sure if I were to change the method of file retrieval, what changes are necessary?
    • BrewManNH
      By BrewManNH
      Why is it that if you send the function FileExists with a path that has quotes around it, for example see below, it tells you that the file/path doesn't exist?


      $drive = """C:""" ;$drive = "C:" Doesn't work ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $drive = ' & $drive & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If FileExists($drive) Then MsgBox(4096, $drive & " Dir ", "Exists") Else MsgBox(4096, $drive & " Dir ", "Does NOT exists") EndIf $drive1 = "C:" ; $drive1 = C: Works ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $drive1 = ' & $drive1 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console If FileExists($drive1) Then MsgBox(4096, "C: Dir ", "Exists") Else MsgBox(4096, "C: Dir", "Does NOT exists") EndIf If you're using FileExists with path names that you've put quotes around to work with other functions, you either have to check for the file before putting the quotes, or stripping them off before checking, which seems a little backwards. Not sure if I should report this as a bug, or something to add to the help file.