Sign in to follow this  
Followers 0
Andlin

Check for open handles

7 posts in this topic

I have a long script that at the end i want to rename a file to overwrite a file used earlier. however it fails. I am guessing that there is a fileopen handle sitting somewhere associated to the file.

I understand that the FileMove("source", "Destination", 1) will perform the following steps

1. if destination exists then delete it.

2. rename the source to the destination.

however if the destination is open then it will fail on both steps, but once the application exit's the file handles are all then released and step 1 will complete, but step 2 doesnt happen.

I have searched my code for where i may have forgotten to fileclose the destination but am unable to find it.

Is there a way to report back the current handles that are open?

#include<File.au3>
Dim $sFile
Dim $Content
Dim $counter

$sFile = FileOpen("Test.txt",1)
for $counter = 1 to 10
FileWriteLine($sFile, "This should be in test2")
Next
FileClose($sFile)
$sFile = FileOpen("Test2.txt",1)
for $counter = 1 to 10
FileWriteLine($sFile, "This shouldn't be here")
Next
FileClose($sFile)
;Leave file open and try to move while open.
$sFile = FileOpen("Test2.txt",1)
FileMove("test.txt", "test2.txt",1)
MsgBox(0,"Check", "Check if file has moved/renamed")
Exit

in the code above if i remove line 21 then it works as it should but with line 21 in it is an example of a handle left open.

Cheers

Share this post


Link to post
Share on other sites



There are numerous posts about this around the forum...search for "FileInUse". Here is a quick function This will allow you to loop until the file is able to be overwritten, or at least report that the file is open.

Share this post


Link to post
Share on other sites

I know how to tell if a file is in use. However this will not tell me what the filehandle is that has it open so that i can close it.

Thanks for your effort though.

Cheers

Share this post


Link to post
Share on other sites

Have you checked out "handle.exe" from PSTools? The syntax that you would use would be:

handle.exe - "yourfilename.txt"

This would return the PID from your AutoIT Script...however, if you are using a single script, you may do well to:

  • if file is in use, create a temp batch script to do your rename/file move
  • Exit & run your batch script
In your example code, I only saw 20 lines...what line did you remove to make it fail?

Share this post


Link to post
Share on other sites

Thanks. The script as it is above should fail due to line 17.

the handle.exe wont help as it will (as you stated) just give me the pid of the exe that i am working in.

I like your idea of a batch script, although one thing springs to mind, if i put a delay in the batch script to allow main exe to complete, will the main exe run the batch script and exit before checking that the batch is complete. Basically if i have:-

run("temp.bat")

exit

will exit happen while temp.bat is still running, or does it wait until temp.bat is complete before it moves to the next line which is to exit the exe?

of course i can write a quick script to check this, but thought i would be lazy and ask :D

Cheers

Share this post


Link to post
Share on other sites

FWIW i just tested it with the following script replacing the section above and it does start the batch file then exit the app prior to the batch file compleing.

;Leave file open and try to move while open.
$sFile = FileOpen("Test2.txt",1)
FileDelete("rename.bat")
$sFile2 = FileOpen("rename.bat",1)
FileWriteLine($sFile2,"ECHO Off")
FileWriteLine($sFile2,"ping 127.0.0.2") ;This is simply creating some time to allow the current exe to exit before the batch tries to rename the file.
FileWriteLine($sFile2,"del test2.txt")
FileWriteLine($sFile2,"rename test.txt test2.txt")
;~ FileWriteLine($sFile2,"Pause")
FileClose($sFile2)
run("rename.bat", "", @SW_HIDE)
Exit

Cheers

Share this post


Link to post
Share on other sites

You can call the Exit Function with "Run("Some Program") as it's parameters:

Exit 1  ;Exit with Code 1

OR

Exit Run('calc.exe')  ;Exit with Code "Run Calc.exe"

Here is an example of creating a pseudo-dynamic batch file that will wait for your script to end before continuing. In this script, the batch file sits around and waits for the PID that is passed to it to no longer exist...Then it renames the Sciptfile that spawned it (impossible to do while the script is running), then renames is back to its' original name. This is just one of those other ways to get around your problem.

Local $iCounter = 0
Local $iPID = @AutoItPID, $ScriptName = @ScriptFullPath, $NewName = @ScriptDir & 'NewName.' & StringRegExpReplace(@ScriptName, '^.+.', '')
Local $sWidth = @DesktopWidth / 4
Local $sHeight = 25
Local $sX = (@DesktopWidth / 2) - ($sWidth / 2)
Local $sY = (@DesktopHeight / 2) - ($sHeight / 2)
;Splash to let you know that the Scipt is Still running
$iSplash = SplashTextOn('', @ScriptName & ' is now running', $sWidth, $sHeight, $sX, $sY, 49, '', 14)
While 1
If Not $iCounter Then
  ;Sent paramters: This Scripts' PID, Then FQN Of This Script, The FQN of the New Filename
  _SelfRenameBatch($iPID & ' "' & $ScriptName & '" "' & $NewName & '"')
EndIf
If $iCounter >= 6 Then ExitLoop
Sleep(1000)
;Update The Splash Text When inside the Loop
ControlSetText($iSplash, '', 'Static1', 'Now in Loop # ' & $iCounter)
$iCounter += 1
WEnd
ControlSetText($iSplash, '', 'Static1', 'Script Is Now Exiting!!')
Sleep(1500)
Exit
Func _SelfRenameBatch($iParameters = '')
Local $wString, $hFile, $sTempFile = @TempDir & 'TempBatch.cmd'
$wString &= '@ECHO OFF' & @LF
$wString &= '' & @LF
$wString &= 'SET /a COUNTER = 1' & @LF
$wString &= ':STARTLOOP' & @LF
$wString &= 'TASKLIST > "C:UsersADMINI~1AppDataLocalTempTEMPFILE.LOG"' & @LF
$wString &= 'FIND /C "%1" "%TEMP%TEMPFILE.LOG"' & @LF
$wString &= 'IF %ERRORLEVEL% NEQ 0 (' & @LF
$wString &= 'GOTO EXITLOOP' & @LF
$wString &= ')' & @LF
$wString &= ') ELSE (' & @LF
$wString &= 'ECHO WAITING...LOOP #%COUNTER%' & @LF
$wString &= 'PING 127.0.0.1 -n 1 -w 500 >NUL' & @LF
$wString &= 'SET /a COUNTER += 1' & @LF
$wString &= 'GOTO STARTLOOP' & @LF
$wString &= '' & @LF
$wString &= ':EXITLOOP' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO %2 HAS EXITED...' & @LF
$wString &= '@ECHO RENAMING %2 TO "%~nx3"' & @LF
$wString &= 'PING 127.0.0.1 -n 1 -w 1000 >NUL' & @LF
$wString &= 'REN %2 "%~nx3"' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO CHECK TO SEE IF FILE HAS BEEN RENAMED' & @LF
$wString &= 'PAUSE' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO RENAMING %3 TO "%~nx2"' & @LF
$wString &= 'PING 127.0.0.1 -n 1 -w 1000 >NUL' & @LF
$wString &= 'REN %3 "%~nx2"' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO CHECK TO SEE IF FILE HAS BEEN RENAMED' & @LF
$wString &= 'PAUSE' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO...' & @LF
$wString &= '@ECHO EXITING BATCH SCRIPT' & @LF
$wString &= 'DEL /Q "C:UsersADMINI~1AppDataLocalTempTEMPFILE.LOG"' & @LF
$wString &= 'PAUSE' & @LF
$wString &= 'DEL /Q %0'
$hFile = FileOpen($sTempFile, 2)
FileWrite($hFile, $wString)
FileClose($hFile)
ShellExecute($sTempFile, $iParameters)
EndFunc   ;==>_SelfRenameBatch

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