Jump to content

Preventing a crash from an inevitable error


 Share

Recommended Posts

Surely this is possible and many have already dealt with this, but I just couldn't find it. I searched for error+crash+prevent, and didn't find it.

Here's a test script:

$path = @MyDocumentsDir & "\_11_52608_live.asf"
$newname = "newname_002.asf"

Global $fso = ObjCreate ("Scripting.FileSystemObject")

Global $gui = GUICreate ( "test", 200, 200 )
Global $but = GUICtrlCreateButton ("Push me!", 10, 10)
GUISetState()

Func RenameFile()
    SetError(-1,-1)
$f = $fso.GetFile($path)
$f.Name = $newname
EndFunc

Do
    $msg = GUIGetMsg()
    If $msg == $but Then RenameFile()
Until $msg == -3

The file could normally be renamed, but now it in use by another program, so I get an error, and it crashes my program. There HAS to be a way to prevent a crash when an error happens.

Thanks :whistle:

Edited by rush4hire
Link to comment
Share on other sites

#include <IE.au3>
_IEErrorHandlerRegister ("RenameFile")

Ok, I found it. This is wierd. I had the media file open in the media viewer, so it's being used and can't be renamed. When I used the _IEErrorHandlerRegister function, it waited till after I closed the media file, and then renamed it.. hmm...

I guess this works, unless there's something better. It freaked me out that it renamed it later...

---

Sigh.. IE.au3 is almost 4000 lines or 161 kb of code. It adds 25 kb to my .exe, which makes it 223 kb instead of 198 kb.

I just hate to include all this junk that I'm not using. But it's so much trouble to seperate out the things I need just to handle one function that has errors sometimes.

Edited by rush4hire
Link to comment
Share on other sites

Ok, here's all I needed from IE.au3

Global $__IEAU3Debug = False
Global $_IEErrorNotify = True
Global $oIEErrorHandler, $sIEUserErrorHandler
; Error Status Types
Global Enum $_IEStatus_Success = 0, $_IEStatus_GeneralError

Func _IEErrorHandlerRegister($s_functionName = "__IEInternalErrorHandler")
    $sIEUserErrorHandler = $s_functionName
    $oIEErrorHandler = ""
    $oIEErrorHandler = ObjEvent("AutoIt.Error", $s_functionName)
    If IsObj($oIEErrorHandler) Then
        SetError($_IEStatus_Success)
        Return 1
    Else
        __IEErrorNotify("Error", "_IEPropertySet", "$_IEStatus_GeneralError", _
                "Error Handler Not Registered - Check existance of error function")
        SetError($_IEStatus_GeneralError, 1)
        Return 0
    EndIf
EndFunc


Func __IEErrorNotify($s_severity, $s_func, $s_status = "", $s_message = "")
    If $_IEErrorNotify Or $__IEAU3Debug Then
        Local $sStr = "--> IE.au3 " & $s_severity & " from function " & $s_func
        If Not $s_status = "" Then $sStr &= ", " & $s_status
        If Not $s_message = "" Then $sStr &= " (" & $s_message & ")"
        ConsoleWrite($sStr & @CR)
    EndIf
    Return 1
EndFunc   ;==>__IEErrorNotify

_IEErrorHandlerRegister ("RenameFile")

And it works.

Now my compiled .exe is 199 kb, that's only 1 extra kb instead of 25 !!

I'm sure there's an even better way, but my motivation to find it is lacking..

Link to comment
Share on other sites

  • Moderators

pethebee and kjactive were working on 2 seperate pre-processor options I believe at one time to strip the code of non essential functions/variables/constants etc... If I remember correctly, pethebee's was written in C++ in fact for speed.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Ok, that didn't work. My program crashed again last night. I commented out the

_IEErrorHandlerRegister

thing and used

Opt("RunErrorsFatal", 0)

instead.

I just want to rename a file, but sometimes it can't be renamed because it's being used by another program.

Here are my functions.

Func RenameFile2($path, $newname)
$f = $fso.GetFile($path)
$f.Name = $newname
If @error Then
    For $i = 0 to 9
        If $delay_exec_array[$i] == '' Then
            $delay_exec_array[$i] = 'RenameFile2("'& $path &'", "'& $newname &'")'
            ExitLoop
        EndIf
    Next
EndIf
EndFunc
oÝ÷ Ù*Á©íyÛhjÛ^m¢·§jg­çâë%j׫w±êjw«®îØ¥jÛ^bh­éÚëayø¥zÇbv}ý¶¯y©Þ®º+jëh×6Func delay_exec()
    For $i = 0 to 9
        If $delay_exec_array[$i] <> "" Then
            Execute( $delay_exec_array[$i] )
            If @error Then
                SetError(0)
            Else
                $delay_exec_array[$i] = ""
            EndIf
        EndIf
    Next
EndFunc

I could have the file renaming handled by another .exe, but if I made the .exe in AutoIt, it will add an extra 200 kb to my installer.

I guess I'll try to do the file renaming all in vbscript somehow.. I saw some vbscript examples in the autoit folder

Link to comment
Share on other sites

  • Moderators

So check to see if it's open first.

Func _IsFileReady($hFile)
    Local $hOpen = FileOpen($hFile, 0)
    If $hOpen = -1 Then Return SetError(-1, 0, 0)
    FileClose($hOpen)
    Return 1
EndFunc

Edit:

Noticed I didn't have the right parameters for FileOpen().

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

why don't you just use the FileMove ( "source", "dest" [, flag] ) to rename a file, and catch the error 0 if that didn't work, then wait a minute and try again. (I believe you will still need to set RunErrorsFatal to not crash on error.)

The help says that since AutoIT lacks a file rename operation, this one needs to be used instead since it does the same...

By the way, your timing function is odd. @MIN is the amount of minutes, this will only be 00 once every hour, not every minute. I think you mean seconds judging from your comment "; once every minute"? They will be 00 once every minute :whistle: Then again, why not just use Sleep(60000) to pause for one minute?

/ edit: on top of that, if you fire a command every second that checks for @MIN to be 00, it will be executed 60 times in succession, but only during the first mionute of every hour... This is probably not what you want it to do :)

/ edit 2: aaaargh, now I realize why you don't use sleep(60000), the program does OTHER things every second too, right?? Ok, then it is a sensible thing to do, only with @SEC and not @MIN :-)

Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Link to comment
Share on other sites

So check to see if it's open first.

Func _IsFileReady($hFile)
    Local $hOpen = FileOpen($hFile)
    If $hOpen = -1 Then Return SetError(-1, 0, 0)
    FileClose($hOpen)
    Return 1
EndFunc
Ok, I'll try _IsFileReady, I didn't know about that. Thanks smoke.

why don't you just use the FileMove ( "source", "dest" [, flag] ) to rename a file, and catch the error 0 if that didn't work, then wait a minute and try again. (I believe you will still need to set RunErrorsFatal to not crash on error.)

I'll try that too.

By the way, your timing function is odd. @MIN is the amount of minutes, this will only be 00 once every hour, not every minute. I think you mean seconds judging from your comment ";

Ya, that was a mistake caused by fatigue.. Thanks for catching it :whistle:
Link to comment
Share on other sites

  • Moderators

Ok, I'll try _IsFileReady, I didn't know about that. Thanks smoke.

:whistle: Probably because I had just written it for you before I posted it :)

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

  • Moderators

Ok..

I've never seen a Return SetError(-1, 0, 0)

But why not just return 0 and act like the error never happened? :whistle:

I'm returning what is returned by FileOpen() if it fails :lol::)

Edit:

I re-read this, and I think I may have mis-interpreted what you asked.

I did an Error return so you don't always have to use it as a boolean if you don't want to.

It would work just as well...

$bCheckFile = _IsFileRead("C:\SomeFile.txt")
If @error Then MsgBox(64, 'Sorry', "You'll have to wait a bit longer")oÝ÷ Øò¢ì׶޵¨§¶¯j[¶­Ì"¶7é°¡yÉW~z-Ê¢é]v®¶­seô4fÆU&VBgV÷C´3¢b3#µ6öÖTfÆRçGBgV÷C²¤bW'&÷"FVâ×6t&÷cBÂb33µ6÷''b33²ÂgV÷Cµ÷Rb33¶ÆÂfRFòvB&BÆöævW"gV÷C²oÝ÷ ØêÈ*.ë-Á©íyÖªº'$r«­¢+Ù%9½Ð}%Í¥±I ÅÕ½ÐíèÀäÈíM½µ¥±¹ÑáÐÅÕ½Ðì¤Q¡¸5Í ½à ØаÌäíM½ÉÉäÌäì°ÅÕ½Ðíe½ÔÌäí±°¡ÙѼݥХб½¹ÈÅÕ½Ðì

Ever since I started doing error checking in my UDFs, I don't think I've written many that didn't have an error return.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Ok..

This project is to record media streams with a media recorder that doesn't have alot of features. So from my experience there are different reasons why the saved files can't be renamed sometimes..

I think sometimes they are still opened by the recorder cause it might be a little buggy.. So I'll have to also restart that program if we get too many files on our list to rename..

So here's what I have.

;~ If this returns 1 then we did all we can to rename the file..
Func RenameFile($path = "", $name = "", $fromarr=0)
If $path == "" Then $path = _StringExtract (ControlGetText ( "SDP Multimedia", "", "TRichEdit1" ), "> SAVE :    ", @CRLF)
If $path == "" Then Return 1
If $name == "" Then $name = $sched[$cshow][3] &' -- '& $sched[$cshow][4]
If Not FileExists($path) Then Return 1
$folder = $fso.GetParentFolderName($path) & "\"
$fil = ""
$ext = ".asf"
$c = 0
While FileExists($folder & $name & $fil & $ext)
    $fil = "("& $c &")"
    $c += 1
WEnd
If FileMove($path, $folder & $name & $fil & $ext) Then Return 1
If Not $fromarr Then $delay_items.Item($path) = $name
EndFunc


Func delay_exec()
    If $delay_items.Count == 0 Then Return
For $path in $delay_items.Keys
    If RenameFile($path, $delay_items.Item($path), 1) Then $delay_items.Remove($path)
Next
EndFunc

Oh, and Opt("RunErrorsFatal", 0) doesn't seem to do anything to prevent a crash..

The only thing that works is _IEErrorHandlerRegister .. and it does keep it from crashing.

Edited by rush4hire
Link to comment
Share on other sites

  • Moderators

Opt("RunErrorsFatal", 0)

Should tell you why that's not helping your "COM/Object" crashing issue.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Maybe I'm not getting something here... But I went ahead with it and wrote a test tool, and cannot find any problems with delayed renaming. Don't even have to use RunErrorsFatal or whatever.

Now what I did: I put a file called x.mp3 in c:\. Started it up in Winamp. Then ran this script. It waited and waited, until 15 seconds later I turned off Winamp and then the messagebox came up with count 15, and the file had been renamed right after Winamp quit. As far as I understand this is exactly what you had in mind.

/edit: Note that it seems that you need not worry about any fatal error or crash whatsoever, because they simply will not arise if the filemove() command fails for something as painless as the file just being in use. (I have however NOT tried to corrupt my file system to see what happened then! :whistle:)

; Rename-a-media test tool
$count = 1   ; it will try at least once
$filesource="c:\x.mp3"
$filetarget="c:\y.mp3"
While FileMove($filesource,$filetarget) = 0
    $count += 1
    Sleep(1000)
WEnd

MsgBox(0,"Rename-a-media test tool","File has been renamed. Attempts: "&$count)
Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Link to comment
Share on other sites

  • Moderators

Maybe I'm not getting something here... But I went ahead with it and wrote a test tool, and cannot find any problems with delayed renaming. Don't even have to use RunErrorsFatal or whatever.

Now what I did: I put a file called x.mp3 in c:\. Started it up in Winamp. Then ran this script. It waited and waited, until 15 seconds later I turned off Winamp and then the messagebox came up with count 15, and the file had been renamed right after Winamp quit. As far as I understand this is exactly what you had in mind.

; Rename-a-media test tool
$count = 0
$filesource="c:\x.mp3"
$filetarget="c:\y.mp3"
While FileMove($filesource,$filetarget) = 0
    $count += 1
    Sleep(1000)
WEnd

MsgBox(0,"Rename-a-media test tool","File has been renamed. Attempts: "&$count)
WinAmp closed the file/handle... doesn't sound like what he's working with, whether he made it himself or not, is closing it.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

WinAmp closed the file/handle... doesn't sound like what he's working with, whether he made it himself or not, is closing it.

Ok, then I wonder what he's working with. As far as I can read from his posts in the beginning, it's some sort of media player. If it is his own, then he should change it to release the file handle itself, instead of letting this function do error juggling. If it is another media player, maybe that gives other perspectives on this case.

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...