Gigglestick Posted May 5, 2011 Share Posted May 5, 2011 (edited) I did a quick search for it on the forums, but maybe I missed it, so I made my own.It searches the PATH environment variableExample:ConsoleWrite(_FileInPath("robocopy.exe") & @CRLF)UDF:expandcollapse popup; #FUNCTION# ==================================================================================================================== ; Name...........: _FileInPath ; Description ...: Returns the location in the PATH environment variable containing a file ; Syntax.........: _FileInPath( $sFilename ) ; Parameters ....: $sFilename - The file to search for (filename only, no folders) ; Return values .: Success - Returns the path to the file and set @error=0 (@extended=1 a specified path and the file is there) ; Failure - Returns "" and sets @error: ; |1 - File not found in @WorkingDir or the PATH (@extended=1 if PATH is blank) ; |2 - Could not StringSplit the PATH ; Author ........: Gigglestick (c0deWorm) ; Modified.......: Comments added and logic modified ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== Func _FileInPath($asFilename) If StringInStr($asFilename, "\") Then If FileExists($asFilename) Then ; if a full or relative path was specified and the file exists then return the path Return SetError(0, 1, $asFilename) Else ; if a path was specified and the file does not exist then return "file not found" error Return SetError(1, 0, "") EndIf EndIf ; if the file is found in the current working directory then return the absolute file path If FileExists(@WorkingDir & "\" & $asFilename) Then Return SetError(0, 0, @WorkingDir & "\" & $asFilename) Local $i, $lasPath, $lsPath = EnvGet("PATH") ; if variable containing PATH is empty then return "file not found" error and @extended=2 If StringLen($lsPath) = 0 Then Return SetError(1, 1, "") ; if PATH is set but only has one entry then check it If StringLen($lsPath) > 0 And Not StringInStr($lsPath, ";") Then If FileExists($lsPath & "\" & $asFilename) Then ; if the filename is found in the single PATH entry then return the file path Return SetError(0, 0, $lsPath & "\" & $asFilename) Else ; if PATH is a single entry and does not contain the filename then return "file not found" error Return SetError(1, 0, "") EndIf EndIf ; remove any blank entries (double semicolons) While StringInStr($lsPath, ";;") $lsPath = StringReplace($lsPath, ";;", ";") WEnd ; split variable containing PATH into an array of single paths $lasPath = StringSplit($lsPath, ";") ; if ";" not found in split then return error If @error Then Return SetError(2, 0, "") ; loop through array of single paths, searching for absolute file path and return absolute file path if found For $i = 1 To $lasPath[0] If FileExists($lasPath[$i] & "\" & $asFilename) Then Return SetError(0, 0, $lasPath[$i] & "\" & $asFilename) Next ; unable to find filename in current working directory or PATH so return error Return SetError(1, 0, "") EndFunc ;==>_FileInPathEdit - May 10: Evaluated MHz's comments and revised the code. It should work much better now.If a full or relative path is specified and the file exists there then return that path, or @error=1 (file not found)If the file exists in the @WorkingDir then return that pathIf the PATH is empty then return @error=1 and @extended=1If the PATH contains only a single entry, and it contains the file then return that path, or @error=1 (file not found)Clear blank entries (consecutive semicolons) from the PATHSplit the path and check each entry for the file, returning the path if foundIf none of the above works then @error=1 (file not found) Edited May 10, 2011 by Gigglestick stealthmsgr 1 My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
JohnOne Posted May 7, 2011 Share Posted May 7, 2011 Forgive me if I'm wrong but should this line... If FileExists($asFilename) Then Return SetError(0, 0, @WorkingDir & "\" & $asFilename) ...be @ScriptDir rather than @WorkingDir AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
wakillon Posted May 7, 2011 Share Posted May 7, 2011 @JohnOne if you don't use FileChangeDir, @WorkingDir = @ScriptDir AutoIt 3.3.14.2 X86 - SciTE 3.6.0 - WIN 8.1 X64 - Other Example Scripts Link to comment Share on other sites More sharing options...
MHz Posted May 8, 2011 Share Posted May 8, 2011 (edited) Regarding @WorkingDir = @ScriptDir can be false to presume. FileChangeDir can change @WorkingDir which I agree with. Inheritance of a working directory on initial execution can make @WorkingDir other then @ScriptDir. If I start a executable from a command prompt. Note the working directory of the prompt is shown as C:\ C:\> C:\temp\script.exe The inherited working directory would be C:\ and not C:\temp. Also using the Start command allows change of working directory for the executable to inherit. Using the Run box can set the working directory to your user profile, the last time I checked. Using the registry can set the working directory to the system drive, the last time I checked. Group Policy and other means of execution may affect the inheritance of working directory so you should not presume that @WorkingDir will equal @ScriptDir at the time of initial execution. Edit: @JohnOne The test of FileExists on $asFilename can return true if $asFilename does exist in @workingDir and not exist not in @ScriptDir. @ScriptDir is an absolute folder path which can be an issue when you use a relative path (just a filename) such as $asFilename uses. Edited May 8, 2011 by MHz Link to comment Share on other sites More sharing options...
JohnOne Posted May 8, 2011 Share Posted May 8, 2011 Thanks for the explanaition, I was under the impression that FileExists() only checked the folder which the process ran from if no path is given, and in the case of "file.ext" would only be @ScriptDir. If I'm honest, I dont understand what @WorkingDir even means. AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
MHz Posted May 8, 2011 Share Posted May 8, 2011 You may need to understand a working directory to make good use of Gigglesticks fine UDF. You use working directories all the time without knowing it. So perhaps you may understand the explanation below. You execute a file and it becomes a process in ram memory. The process gets to inherit a working directory to focus on. The working directory is the view, or what directory that the process can see. Now try to imagine that you are a process, not in ram memory but as an external process working with files in Explorer. Have an Explorer window open in front of you and set the view pane of Explorer to C:\. You as an imaginary process can now see files in the directory of C:\. You can work with those files in C:\ but you cannot see files in other directories because Explorer can only show one directory at a time in the view pane. Now change the working directory of Explorer by setting the view pane to C:\Windows. You as an imaginary process can now see files in the directory of C:\Windows. You can work with those files in C:\Windows but you cannot see files in other directories because Explorer can only show one directory at a time in the view pane. You can keep changing directories in Explorer as you like and note that you are basically changing the working directory each time you set a new path in Explorer and you also get a view that is the same as the working directory. The description above is similar to how a process in ram memory works. The working directory can change and thus the view of the files that the process sees is relative to the working directory. If the working directory is @ScriptDir, then the process can see the physical form of itself and other files in the @ScriptDir. If the working directory alias @WorkingDir is some other directory then it can see the files in that directory and not its physical form of itself and other files in the @ScriptDir. Link to comment Share on other sites More sharing options...
JohnOne Posted May 8, 2011 Share Posted May 8, 2011 So if the working Dir can be different from that which the process is ran from, could not the function above falsely return true when the given file is in @ScriptDir and not "PATH", but @WorkingDir is in "PATH" ? AutoIt Absolute Beginners  Require a serial  Pause Script  Video Tutorials by Morthawt  ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
MHz Posted May 9, 2011 Share Posted May 9, 2011 JohnOne,I can not see how it would be possible for the UDF to return a file path if it does not exist in @WorkingDir or PATH. You mentioned previous in post #2 about a concern about the line below.If FileExists($asFilename) Then Return SetError(0, 0, @WorkingDir & "\" & $asFilename)Using FileExists on a just a filename looks for the filename in @WorkingDir. So the return of @WorkingDir & "\" & $asFilename would be correct. Use of for example FileExists($asFilename) and FileExists(@WorkingDir & "\" & $asFilename) should be either both True or both false with the same conditions as they both reference the file in @workingDir. Returning @ScriptDir & "\" & $asFilename as you suggested would be incorrect if @WorkingDir is different to @ScriptDir.This is an test script and I commented the UDF code for the review.expandcollapse popup; *** test _FileInPath() *** ; look for @ScriptName in @ScriptDir FileChangeDir(@ScriptDir) $absolute_filepath = _FileInPath(@ScriptName) _GetError(@error, @extended, $absolute_filepath, 'Find ' & @ScriptName) ; look for @ScriptName in @WindowsDir FileChangeDir(@WindowsDir) $absolute_filepath = _FileInPath(@ScriptName) _GetError(@error, @extended, $absolute_filepath, 'Find ' & @ScriptName) ; change PATH to show issue with missing ";" EnvSet('PATH', @WindowsDir) FileChangeDir(@WindowsDir) $absolute_filepath = _FileInPath(@ScriptName) _GetError(@error, @extended, $absolute_filepath, 'Find ' & @ScriptName & ' with missing ";" in PATH') ; change PATH to show issue empty path while working directory is valid EnvSet('PATH', '') FileChangeDir(@ScriptDir) $absolute_filepath = _FileInPath(@ScriptName) _GetError(@error, @extended, $absolute_filepath, 'Find ' & @ScriptName & ' with empty PATH') ; *** UDF by Gigglestick (c0deWorm) showing possible issues to consider *** ; working directory could be seached before returning error on an empty variable containing PATH ; i.e. PATH is secondary compared to the working directory I usually notice ; should a variable containing PATH be be regarded as an error if ";" is not found? ; i.e. a single path without a ";" would IMO be considered valid but would return error in the UDF ; ; *** UDF by Gigglestick (c0deWorm) with added comments *** ; #FUNCTION# ==================================================================================================================== ; Name...........: _FileInPath ; Description ...: Returns the location in the PATH environment variable containing a file ; Syntax.........: _FileInPath( $sFilename ) ; Parameters ....: $sFilename - The file to search for (filename only, no folders) ; Return values .: Success - Returns the path to the file and @error=0 ; Failure - Returns "" and sets @error: ; |1 - File not found anywhere in the PATH ; |2 - Cannot read the PATH environment variable ; |3 - Filename contains a backslash ; |4 - The PATH environment variable could not be StringSplit ; Author ........: Gigglestick (c0deWorm) ; Modified.......: Comments added ; Remarks .......: ; Related .......: ; Link ..........: ; Example .......: ; =============================================================================================================================== Func _FileInPath($asFilename) Local $i, $lasPath, $lsPath = EnvGet("PATH") ; if variable containing PATH is empty, then return error If $lsPath = "" Then Return SetError(2, 0, "") ; if the filename given contains a backslash then return error If StringInStr($asFilename, "\") Then Return SetError(3, 0, "") ; if the file is found in the current working directory, then return the absolute file path If FileExists($asFilename) Then Return SetError(0, 0, @WorkingDir & "\" & $asFilename) ; split variable containing PATH into an array of single paths $lasPath = StringSplit($lsPath, ";") ; if ";" no found in split then return error If @error Then Return SetError(4, 0, "") ; loop through array of single paths, searching for absolute file path and return absolute file path if found For $i = 1 To $lasPath[0] If FileExists($lasPath[$i] & "\" & $asFilename) Then Return SetError(0, 0, $lasPath[$i] & "\" & $asFilename) Next ; unable to find filename in current working directory or PATH so return error Return SetError(1, 0, "") EndFunc ;==>_FileInPath Func _GetError($code, $extended, $return_value, $comment = '') ; show various conditions and results MsgBox(0x40000, '_GetError()', _ 'Comment: ' & $comment & @CRLF & _ '@error: ' & $code & @CRLF & _ '@extended: ' & $extended & @CRLF & _ 'Return: ' & $return_value & @CRLF & _ '@WorkingDir: ' & @WorkingDir & @CRLF & _ '@ScriptDir: ' & @ScriptDir & @CRLF & _ '@WorkingDir = @ScriptDir: ' & (@WorkingDir = @ScriptDir) ) EndFuncGigglestick,I list below some possible issues I found with the UDF.Working directory could be seached before returning error on an empty variable containing PATH i.e. PATH is secondary compared to the working directory I usually noticeShould a variable containing PATH be be regarded as an error if ";" is not found? i.e. a single path without a ";" would IMO be considered valid but would return error in the UDFThe test script above shows the possible issues in the last 2 calls to the UDF. Something for you to review. Link to comment Share on other sites More sharing options...
Gigglestick Posted May 10, 2011 Author Share Posted May 10, 2011 (edited) @MHz - Thanks for testing those scenarios. I clearly hadn't checked all the logic. I think it'll work much better now. The original post has been updated. @JohnOne Maybe this will help: Script: C:\Myfiles\Scripts\MyScript.exe File: C:\Myfiles\Scripts\Data.txt PATH: c:\windows\system32;c:\windows @WorkingDir when the script starts is C:\Myfiles\Scripts, so if we _FileInPath("Data.txt") it'll check C:\Myfiles\Scripts and find the file. If you FileChangeDir("C:\") then _FileInPath("Data.txt") again, it'll check C:\ (@WorkingDir, not found), c:\windows\system32 (not found), and c:\windows (not found). So even though the file is in @ScriptDir, we're only looking in the "current" folder and the PATH. This is how other things in Windows work. If you hit Start and Run, and type "cmd" it's looking in the working directory, which is your HOMEPATH (another environment variable), then it'll check each directory listed in the PATH. Unless you have changed it, C:\Windows\System32 is in the PATH by default, so it finds cmd.exe there and runs it. When it starts cmd.exe, it starts it in your HOMEPATH instead of the System32 directory because it's more likely that things relevant to you will be on your home drive than under the System32 directory. From cmd.exe's perspective its own @ScripDir is C:\Windows\System32, but its @WorkingDir is your HOMEPATH. Edited May 10, 2011 by Gigglestick My UDFs: ExitCodes Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now