Announcement

Collapse
No announcement yet.

RmDir getting Error 70

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • RmDir getting Error 70

    I am working with the following block of code, and I keep getting an Error 70 at the point where the program is trying to remove the directory that it created. This code should be fairly straight forward, but I must be missing something simple. I first thought it was the direct calls to "If Len(Dir$(FilesStr)) Then..." so I changed it to use a long integer. This seemed to work for a short time, but now it is once again failing.

    I can easily remove the folder from the DOS prompt or Windows Explorer once the program creates it. The file gets deleted just fine, but the folder does not get removed. I am running this on Windows XP SP2.

    Code:
    #Compile Exe
    #Dim All
     
    $WorkDir           =  "\RMVTEST\"
    $BaseFileName      =  "MyBase_"
    $FileExtension     =  ".dat"
    %Buf512K           = 524288
     
    %USEMACROS = 1
    #Include "win32api.inc"
    #Include "CommCtrl.inc"
     
    Global hDlg As Dword
     
    Sub CheckDrive
       
       Local drive     As String
       Local FilesStr  As String
       Local rslt      As Long
     
       drive = "C:"
     
       FilesStr = drive & $WorkDir & $BaseFileName & "*" & $FileExtension
     
       MkDir drive & $WorkDir
       If ErrClear Then MsgBox "Error Making Directory"
       Open drive & $WorkDir & $BaseFileName & "01234" & $FileExtension For Output As 1
       Print# 1, "This is a test file for this routine!"
       Close 1
       If ErrClear Then MsgBox "Error Making File"
     
       rslt = Len(Dir$(drive & $WorkDir & "NUL"))
     
       If rslt Then  ' scrub folder exists!  See if there are files in it
          rslt = Len(Dir$(FilesStr))
          If rslt Then
             If MessageBox(hDlg, "Folder w/ File Exists, Remove it?", _
                           "Drive " & drive, %mb_yesno Or %mb_iconquestion) = %idyes Then
                ErrClear
                Kill FilesStr       ' Delete any files we created
                ErrClear
                RmDir drive & $WorkDir
                If Err Then
                   MessageBox hDlg, "Error " & Format$(Err) & " attempting to remove folder!", "Could Not Remove", 16
                   ErrClear
                End If
             End If
          End If
       End If
     
    End Sub
     
    Function PBMain () As Long
     
        CheckDrive
     
    End Function
    Scott Slater
    Summit Computer Networks, Inc.
    www.summitcn.com

  • #2
    Running Vista Home Premium, your code runs fine here.
    Rod
    In some future era, dark matter and dark energy will only be found in Astronomy's Dark Ages.

    Comment


    • #3
      Try using DIR$ CLOSE after testing for the presence of files, before doing removes.

      You may still have an open search handle on that directory which prevents the rmdir.

      (why that would not work the same on Vista Home Premium the same way would be a question worth asking!)
      Michael Mattias
      Tal Systems (retired)
      Port Washington WI USA
      [email protected]
      http://www.talsystems.com

      Comment


      • #4
        Or.... don't bother creating and removing directory if this is a temporary file anyway.

        Code:
        FUNCTION GetTempWorkFileName (szPrefix AS ASCIIZ * 4, szTempFile AS ASCIIZ * %MAX_PATH) AS LONG
           ' returns: 0 = success, the temp file name is in szTempFile (fully qualified)
           '        other = System error number
           LOCAL szTempPrefix AS ASCIIZ * 4   ' 3 + null
           LOCAL szTempPath   AS ASCIIZ * %MAX_PATH
           LOCAL Stat AS LONG
           szTempPrefix = szPrefix     ' not that I care, but...
           Stat =  GetTempPath(SIZEOF(szTempPath), szTempPath)
           IF ISTRUE Stat THEN    ' GetTempPathSucceeded
               Stat = GetTempFileName (szTempPath, szTempPrefix, 0&, szTempFile)
           END IF
           IF ISTRUE Stat THEN  ' function succeeded, return zero
              FUNCTION = 0
           ELSE
              FUNCTION = GetLastError  ' GetTempFileName returns non-zero on success
           END IF
        END FUNCTION
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Thank you Michael, that did the trick!

          It is strange because the problem seems to be intermittent with XP Pro as well. I even tried it without the virus scanner being running since I was unsure where to look. Dir$ CLOSE did the job though... Thank you!
          Scott Slater
          Summit Computer Networks, Inc.
          www.summitcn.com

          Comment


          • #6
            Well, I guess if you are on that deep, you may as well just create that temp file and have the operating system delete it for you on close...

            Create and use a file which will be deleted on close
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              It will actually be creating a large number of work files, so I will just keep them all in a directory.
              Scott Slater
              Summit Computer Networks, Inc.
              www.summitcn.com

              Comment


              • #8
                Works fine in Vista.
                But random in XP

                I am not 100% yet, but the back of my mind, I seem to remember that creating or deleting files across drives, both physical and virtual (aka a partitioned drive) is a no, no....but I am sure its in the docs somewhere.

                In your case since the drive assumed the root C: this would come into play depending on where the program was run from.

                I was able to replicate (sometimes) your error 70 which by the way according to the docs
                Permission denied - (%ERR_PERMISSIONDENIED) - You tried to write to a write-protected disk. This error can also be generated as a result of network permission errors, such as accessing a locked file, or a locked record. It can also occur when attempting to open a subdirectory as a file.
                Now the squirrely part....XP randomly may create, but not destroy...or vice versa, and Vista seems to work, but only if I specify a drive.

                Give me a bit and I will see if I can catch what is happening.

                For others checking, here is the code I was using for testing...(including my own errorhandler)

                Original code with ErrorHandler added
                Code:
                #COMPILE EXE
                #DIM ALL
                
                $WorkDir           =  "\RMVTEST\"
                $BaseFileName      =  "MyBase_"
                $FileExtension     =  ".dat"
                %Buf512K           = 524288
                
                %USEMACROS = 1
                #INCLUDE "win32api.inc"
                #INCLUDE "ErrorHandling.inc"
                #INCLUDE "CommCtrl.inc"
                
                GLOBAL hDlg AS DWORD
                
                FUNCTION CheckDrive()AS LONG
                   TraceVariables
                   StartTrace
                   LOCAL drive     AS STRING
                   LOCAL FilesStr  AS STRING
                   LOCAL rslt      AS LONG
                
                '   drive = "C:"
                
                   FilesStr = drive & $WorkDir & $BaseFileName & "*" & $FileExtension
                
                   MKDIR drive & $WorkDir
                '   If ErrClear Then MsgBox "Error Making Directory"
                   OPEN drive & $WorkDir & $BaseFileName & "01234" & $FileExtension FOR OUTPUT AS 1
                   PRINT# 1, "This is a test file for this routine!"
                   CLOSE 1
                '   If ErrClear Then MsgBox "Error Making File"
                
                   rslt = LEN(DIR$(drive & $WorkDir & "NUL"))
                
                   IF rslt THEN  ' scrub folder exists!  See if there are files in it
                      rslt = LEN(DIR$(FilesStr))
                      IF rslt THEN
                         IF MessageBox(hDlg, "Folder w/ File Exists, Remove it?", _
                                       "Drive " & drive, %MB_YESNO OR %MB_ICONQUESTION) = %IDYES THEN
                '            ErrClear
                            KILL FilesStr       ' Delete any files we created
                '            ErrClear
                            RMDIR drive & $WorkDir
                '            If Err Then
                '               MessageBox hDlg, "Error " & Format$(Err) & " attempting to remove folder!", "Could Not Remove " + drive & $WorkDir, 16
                '               ErrClear
                '            End If
                         END IF
                      END IF
                   END IF
                    EndTrace
                     TraceUnHandled
                END FUNCTION
                
                FUNCTION PBMAIN () AS LONG
                    CheckDrive
                END FUNCTION
                ErrorHandler.inc
                Code:
                '*** ErrorHandling.inc
                '***      Written by: Cliff Nichols - 08-28-2008
                '***      Modified by: Cliff Nichols - 09-18-2008
                '***      Compiler: 8.04/9.0
                '***      Should work on: 7/8/9
                '***      Tested on: XP-Pro SP3, Vista-Ultimate
                '***      Should work on: 95/98/ME/NT/2K/XP/Vista
                '***      Purpose - Beefed up Error Handling Routines to attempt to "Bullet-Proof" apps
                '*** Usage:
                '***      StartTrace - Create a Trace log file
                '***      TraceVariables - Common Variables for each function
                '***
                '***      TraceUnhandled - Steps for anything that you did not think of when writing and testing your code
                '--------------------------------------------------------------------------------
                '*** Now for the FUN Stuff
                '***      PB has 'On Error' for handling errors on the DDT side
                '***           PB can raise an error just by ERR = some number
                '***      Windows has 'GetLastError' to check any errors via SDK
                '***           Windows has to check for errors and handle them (errors are not raised)
                '***      Windows has "Exceptions" (You've seen them...the default usually shows the typical "*.exe has encountered a problem and needs to close" message)
                '***           Windows "Exceptions" can be raised, but default handler is typically fatal, but you can override that fatality
                '*** I REALLLLLLY want to know how to do the below without visibly inserting numbers but.....
                '***      PB Line numbers (if inserted) can assist in locating where an error occured (larger projects its smarter to contain line numbers to their functions)
                '***      PB FUNCNAME$ in conjunction with the line numbers can nail down what line the error occured on
                '***           Conjunction, junction, whats your function??? :-)
                '*** What makes it all work????
                '*** MACRO's baby, yeah baby yeah...(Finally got this one when larger code all had the same multiple commands and got tedious to type or copy/paste)
                '*** Globals.....Real Men don't need no stinkin Globals :-) (Finally got this one working deep with Windows API...See "Parameter as Reply" discussion)
                '--------------------------------------------------------------------------------
                
                '*** If not already declared in your code, then declare this INC
                #IF NOT %DEF(%ERRORHANDLING)
                     %ERRORHANDLING = 1
                '*** Globals
                '***      NONE
                '***           - Use SetGetDebugTraceRunning to keep value in replacement for a global DebugTraceRunning
                '***           - Use SetGetLastFunction to keep value in replacement for a global LastFunction
                '*** Constants
                     %UNKNOWN_VALUE = -1
                '*** Constants not found in Win32Api.Inc
                     %EXCEPTION_ILLEGAL_INSTRUCTION  = &HC000001D
                     %EXCEPTION_STACK_OVERFLOW       = &HC00000FD
                '*************************************************************************************************************
                '*** Macro's - When Compiled, replace the name of the macro with all the functions and processes in the macro
                '***           As if you had done it yourself in each and every SUB/FUNCTION it was called
                '***           Do not add line numbers to Macro's unless you want to renumber functions that use the macros
                '*************************************************************************************************************
                '*** TraceUnhandled
                '***      Macro to replace code at the end of each function being being debugged
                '***           Code will jump to end ON ERROR or if told to jump to end
                '***           Code relies on TraceVariables to compile
                '*************************************************************************************************************
                     MACRO TraceUnhandled
                          EXIT FUNCTION                                               'Exit to not Execute Function code again
                     ErrHandler:
                          ErrFunc = GetLastError                                      'Get API Last Error
                          TraceLastError FUNCNAME$, ErrFunc, ERR, ERL
                          SetUnhandledExceptionFilter %NULL
                     END MACRO
                '*************************************************************************************************************
                '*** TraceVariables
                '***      Macro to replace code at the begginning of each function being being debugged
                '***           Code sets up variables to jump to end ON ERROR or if told to jump to end
                '***           Code relies on TraceUnhandled to compile
                '*************************************************************************************************************
                     MACRO TraceVariables
                          ON ERROR GOTO ErrHandler                                    'Avoid using error numbers higher than 240, as they are reserved for use in critical error situations which can never be trapped with ON ERROR.
                          LOCAL DebugTraceRunning AS LONG                             'Variable for if debugging
                          LOCAL LastErrorValue AS LONG                                'Variable for GetLastError
                          LOCAL PbErrorValue AS LONG                                  'Variable for PB ERR
                          LOCAL ErrorLineNumber AS LONG                               'Variable for line number where the error occured (or the last checked line)
                          LOCAL ErrFunc AS LONG                                       'Variable for if there was an error in the function
                          LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH                       'Variable for Win32Api Error Description
                          LOCAL WhatToTrace AS STRING                                 'Variable for what to log for an error
                          SetLastError(0)                                             'Ensure the last Windows error is cleared
                          ERRCLEAR                                                    'Ensure the last PB error is cleared
                '          SetUnhandledExceptionFilter %EXCEPTION_EXECUTE_HANDLER      '<--- Use this exception handler if wanting to use windows default (the typical "*.exe has encountered a problem and needs to close" message)
                          SetUnhandledExceptionFilter CODEPTR (TraceExceptionHandler) '<--- Use this exception handler if wanting to make a better crash-proof program
                     END MACRO
                '*************************************************************************************************************
                '*** TraceOn
                '***      Macro to replace code that would be blindly TRACE ON
                '***           Code only turns the trace on if debugging
                '***           Leaving a function will turn TRACE OFF by default (although I like to purposely call it to clean up after myself)
                '*************************************************************************************************************
                     MACRO TraceOn
                          ErrFunc = SetGetDebugTraceRunning(%UNKNOWN_VALUE, DebugTraceRunning, %UNKNOWN_VALUE)      '<---Find out if debugging or not
                          SELECT CASE DebugTraceRunning
                               CASE 0                                                 'Not running a trace
                               CASE ELSE
                                    TRACE ON                                          'Turn on trace if debugging
                          END SELECT
                     END MACRO
                '*************************************************************************************************************
                '*** TraceOff
                '***      Macro to replace code that would be default TRACE OFF
                '***           Code only turns the trace off if debugging
                '***           Leaving a function will turn TRACE OFF by default (although I like to purposely call it to clean up after myself)
                '*************************************************************************************************************
                     MACRO TraceOff                                                   '<--- Not needed if exiting function but I am a stickler
                          ErrFunc = SetGetDebugTraceRunning(%UNKNOWN_VALUE, DebugTraceRunning, %UNKNOWN_VALUE)
                          SELECT CASE DebugTraceRunning
                               CASE 0                                                 'Not running a trace
                               CASE ELSE
                                    TRACE OFF                                         'Turn off trace if debugging
                          END SELECT
                     END MACRO
                '*************************************************************************************************************
                '*** LastErrorCheck
                '***      Macro to replace code that would be multiple lines for Win32Api GetLastError
                '***           Code only traces if debugging
                '***           TraceLastError will decide if a Windows or a PB Error and log accordingly
                '*************************************************************************************************************
                     MACRO LastErrorCheck
                          ErrFunc = GetLastError                                      'Get API Last Error
                          TraceLastError FUNCNAME$, ErrFunc, ERR, ERL                 'Pass all known info to the function for logging
                     END MACRO
                '*************************************************************************************************************
                '*** NOW FOR THE STANDARD INC SETUP
                '*************************************************************************************************************
                '*** Declares:
                     DECLARE FUNCTION SetGetDebugTraceRunning(ValueToSet AS LONG, ValueResults AS LONG, ResetValue AS LONG) AS LONG
                     DECLARE FUNCTION SetGetLastFunction(ValueToSet AS STRING, ValueResults AS STRING, ResetValue AS LONG) AS LONG
                     DECLARE FUNCTION SetGetOverRideError(ValueToSet AS LONG, ValueResults AS LONG, ResetValue AS LONG) AS LONG
                     DECLARE FUNCTION StartTrace() AS LONG
                     DECLARE FUNCTION EndTrace() AS LONG
                     DECLARE FUNCTION TraceProgramName(ParentAppName AS ASCIIZ * %MAX_PATH) AS LONG
                     DECLARE FUNCTION TraceLastError(FunctionName AS STRING, LastErrorValue AS LONG, PbErrorValue AS LONG, ErrorLineNumber AS LONG) AS LONG
                     DECLARE FUNCTION TracePrint(WhatToTrace AS STRING) AS LONG
                     DECLARE FUNCTION TraceExceptionHandler(BYREF lpEP AS EXCEPTION_POINTERS) AS LONG
                '*** Dependant Inc Files:
                '***      None
                '*** Functions:
                '***      SetGetDebugTraceRunning Replaces the need for global variables so that local variables in other functions are easier to read
                     FUNCTION SetGetDebugTraceRunning(ValueToSet AS LONG, ValueResults AS LONG, ResetValue AS LONG) AS LONG
                1         TraceVariables                                              'Macro for Declaring variables for error checking
                2         STATIC FunctionValue AS LONG                                'Static to hold current value
                3         SELECT CASE ResetValue                                      'Decide whether to Set or to Get the current value
                4              CASE %False, %UNKNOWN_VALUE                            'If set to False, or -1 Then Get Current Value
                5                   ValueResults = FunctionValue                      'Return Results as a parameter
                6              CASE = %TRUE                                           'If set to True then Reset the Current Value
                7                   FunctionValue = ValueToSet                        'Reset the value
                8                   ValueResults = FunctionValue                      'Return Results as a parameter
                9         END SELECT
                10        FUNCTION = %False                                           'Return if Function Failed
                11        TraceUnhandled                                              'Exit Function or handle unhandled errors
                     END FUNCTION
                '*** SetGetLastFunction Replaces the need for global variables so that local variables in other functions are easier to read
                     FUNCTION SetGetLastFunction(ValueToSet AS STRING, ValueResults AS STRING, ResetValue AS LONG) AS LONG
                1         TraceVariables                                              'Macro for Declaring variables for error checking
                2         STATIC FunctionValue AS STRING                              'Static to hold current value
                3         SELECT CASE ResetValue                                      'Decide whether to Set or to Get the current value
                4              CASE %False, %UNKNOWN_VALUE                            'If set to False, or -1 Then Get Current Value
                5                   ValueResults = FunctionValue                      'Return Results as a parameter
                6              CASE = %TRUE                                           'If set to True then Reset the Current Value
                7                   FunctionValue = ValueToSet                        'Reset the value
                8                   ValueResults = FunctionValue                      'Return Results as a parameter
                9         END SELECT
                10        FUNCTION = %False                                           'Return if Function Failed
                11        TraceUnhandled                                              'Exit Function or handle unhandled errors
                     END FUNCTION
                '*** SetGetOverRideError Replaces the need for global variables so that local variables in other functions are easier to read
                     FUNCTION SetGetOverRideError(ValueToSet AS LONG, ValueResults AS LONG, ResetValue AS LONG) AS LONG
                1         TraceVariables                                              'Macro for Declaring variables for error checking
                2         STATIC FunctionValue AS LONG                              'Static to hold current value
                3         SELECT CASE ResetValue                                      'Decide whether to Set or to Get the current value
                4              CASE %False, %UNKNOWN_VALUE                            'If set to False, or -1 Then Get Current Value
                5                   ValueResults = FunctionValue                      'Return Results as a parameter
                6              CASE = %TRUE                                           'If set to True then Reset the Current Value
                7                   FunctionValue = ValueToSet                        'Reset the value
                8                   ValueResults = FunctionValue                      'Return Results as a parameter
                9         END SELECT
                10        FUNCTION = %False                                           'Return if Function Failed
                11        TraceUnhandled                                              'Exit Function or handle unhandled errors
                     END FUNCTION
                '*** Start Tracing
                     FUNCTION StartTrace() AS LONG
                1         TraceVariables                                              'Macro for Declaring variables for error checking
                2         LOCAL TraceLogName AS ASCIIZ * %MAX_PATH
                3         ErrFunc = TraceProgramName(TraceLogName)                    'Get a trace log name
                4         SELECT CASE ErrFunc                                         'If no error creating the log
                5              CASE %FALSE
                6                   DebugTraceRunning = %TRUE                         'Set variable for if tracing
                7                   TRACE NEW TraceLogName                            'Create the log
                8              CASE ELSE                                              'Some Error Occurred
                9         END SELECT
                10        ErrFunc = SetGetDebugTraceRunning(%TRUE, DebugTraceRunning, %TRUE)    'Set the flag that we are tracing
                11        TraceUnHandled                                              'Macro for Local Variables and Unhandled Errors
                     END FUNCTION
                '*** End Tracing
                     FUNCTION EndTrace() AS LONG
                1          TraceVariables                                             'Macro for common variables
                2          LOCAL TraceLogName AS ASCIIZ * %MAX_PATH
                3          ErrFunc = TraceProgramName(TraceLogName)                   'Get a trace log name
                4          SELECT CASE ErrFunc                                        'If the trace log name exists (no error) then
                5               CASE %FALSE
                6                    DebugTraceRunning = %FALSE
                7                    TRACE CLOSE                                      'Close Trace File
                8               CASE ELSE                                             'Some Error Occurred
                9          END SELECT
                10          ErrFunc = SetGetDebugTraceRunning(%FALSE, DebugTraceRunning, %TRUE)      'Set the flag for we are no longer tracing
                11          TraceUnHandled                                            'Macro for Local Variables and Unhandled Errors
                     END FUNCTION
                '*** Set up a log file name
                     FUNCTION TraceProgramName(ParentAppName AS ASCIIZ * %MAX_PATH) AS LONG
                1          LOCAL ErrFunc AS LONG
                2          ErrFunc = GetModuleFileName(GetModuleHandle(BYVAL %NULL), ParentAppName, %MAX_PATH)       'Returns current path to owning parent
                3          ParentAppName = MID$(ParentAppName, 1, INSTR(ParentAppName, ".exe") - 1)  'Strip all but the parent '.exe' part
                4          ParentAppName = ParentAppName + " - Error Log.log"          'Append string to show an error log
                5          SELECT CASE ErrFunc
                6               CASE 0                                                 'Function Failed
                7                    FUNCTION = ErrFunc
                8               CASE ELSE                                              'Function Passed
                9                    FUNCTION = %False
                10          END SELECT
                     END FUNCTION
                '*** Trace Last Error (if any)
                     FUNCTION TraceLastError(FunctionName AS STRING, LastErrorValue AS LONG, PbErrorValue AS LONG, ErrorLineNumber AS LONG) AS LONG
                          LOCAL LastError AS LONG
                          LOCAL WhatToTrace AS STRING
                          LOCAL ErrFunc AS LONG
                          LOCAL DebugTraceRunning AS LONG
                          LOCAL ErrorBuff AS ASCIIZ * %MAX_PATH
                
                          ERR = PbErrorValue                                          'PB Clears ERR at the end of functions so to preserve it I reset it
                          SELECT CASE ERR                                             'Is it a PB Error?
                               CASE 0                                                 'Not a PB Error
                                    FormatMessage %FORMAT_MESSAGE_FROM_SYSTEM, BYVAL %NULL, LastErrorValue, %NULL, ErrorBuff, SIZEOF(ErrorBuff), BYVAL %NULL     'Format the message
                                    WhatToTrace = $TAB + "Unhandled WindowsError - " + STR$(LastErrorValue) + " - " + ErrorBuff + $CRLF + $TAB + " Function = " + FunctionName + " at line: " + STR$(ErrorLineNumber)
                               CASE ELSE                                              'PB Error
                                    LastError = ERR
                                    WhatToTrace = WhatToTrace + $CRLF + $TAB + "Unhandled PbError # " + STR$(ERR) + " - " + ERROR$ + $CRLF + $TAB + " Function = " + FunctionName + " at line: " + STR$(ErrorLineNumber)    '<--- ERL not quite working at this time
                                    SELECT CASE LastError
                                         CASE 0, %ERR_NOERROR                         'No Error
                                         CASE 5, %ERR_ILLEGALFUNCTIONCALL             'Illegal function call
                                         CASE 6, %ERR_OVERFLOW                        'Overflow                '<---This error is not currently supported.
                                         CASE 7, %ERR_OUTOFMEMORY                     'Out of Memory
                                         CASE 9, %ERR_SUBSCRIPTPOINTEROUTOFRANGE      'Subscript / Pointer out of range
                                         CASE 11, %ERR_DIVISIONBYZERO                 'Division by zero         '<---This error is not currently supported.
                                         CASE 24, %ERR_DEVICETIMEOUT                  'Device TimeOut for UDP or TCP communications
                                         CASE 51, %ERR_INTERNALERROR                  'Internal Error
                                         CASE 52, %ERR_BADFILENAMEORNUMBER            'Bad File Name or Number '<--- Also used for Serial Port Errors
                                         CASE 53, %ERR_FILENOTFOUND                   'File not found
                                         CASE 54, %ERR_BADFILEMODE                    'Bad File Mode
                                         CASE 55, %ERR_FILEISOPEN                     'File is already open    '<--- Also used for Serial Port Errors
                                         CASE 57, %ERR_DEVICEIOERROR                  'Device I/O Error        'Serial Port, TCP, UDP
                                         CASE 58, %ERR_FILEALREADYEXISTS              'File already exists
                                         CASE 61, %ERR_DISKFULL                       'Disk full
                                         CASE 62, %ERR_INPUTPASTEND                   'Input past end
                                         CASE 63, %ERR_BADRECORDNUMBER                'Bad record number
                                         CASE 64, %ERR_BADFILENAME                    'Bad file name
                                         CASE 67, %ERR_TOOMANYFILES                   'Too many files
                                         CASE 68, %ERR_DEVICEUNAVAILABLE              'Device unavailable
                                         CASE 69, %ERR_COMMERROR                      'COMM Error         '<---Serial Port Error
                                         CASE 70, %ERR_PERMISSIONDENIED               'Permission Denied
                                         CASE 71, %ERR_DISKNOTREADY                   'Disk not ready
                                         CASE 72, %ERR_DISKMEDIAERROR                 'Disk media error
                                         CASE 74, %ERR_RENAMEACROSSDISKS              'Rename across disks
                                         CASE 75, %ERR_PATHFILEACCESSERROR            'Path/File access error
                                         CASE 76, %ERR_PATHNOTFOUND                   'Path not found
                                         CASE 99, %ERR_OBJECTERROR                    'Object error
                                         CASE 241, %ERR_GLOBALMEMORYCORRUPT           'Global Memory Corrupt
                                         CASE 242, %ERR_STRINGSPACECORRUPT            'String space corrupt
                                         CASE ELSE                                    'Either a 'Compile-Time' error (handled by PB) or Unknown what to do so just exit the function
                                    END SELECT
                          END SELECT
                          TraceOn                                                     'If debugging then trace
                          TracePrint WhatToTrace                                      'If debugging then trace what?
                     END FUNCTION
                '*** Print to trace file if debugging
                     FUNCTION TracePrint(WhatToPrint AS STRING) AS LONG
                1         TraceVariables                                              'Macro for common variables
                2         ErrFunc = SetGetDebugTraceRunning(%UNKNOWN_VALUE, DebugTraceRunning, %UNKNOWN_VALUE)      'Check if Debugging
                3         SELECT CASE DebugTraceRunning
                4              CASE 0                                                 'Not running a trace
                5                   FUNCTION = DebugTraceRunning
                6              CASE ELSE
                                    TRACE ON
                7                   TRACE PRINT WhatToPrint + $CRLF                   '<--- Chose string since I do not know what is to be printed + $CRLF for log file
                8                   FUNCTION = %FALSE
                9         END SELECT
                10        TraceUnHandled                                              'Macro for Local Variables and Unhandled Errors
                     END FUNCTION
                '--------------------------------------------------------------------------------
                '*** Now for the DOOZYYYYyyyy....Handling GPF's and other major fatal errors
                '*** Commented fields are ones that I have no value for (yet) but MSDN say they exist
                '--------------------------------------------------------------------------------
                     FUNCTION TraceExceptionHandler(BYREF lpEP AS EXCEPTION_POINTERS) AS LONG
                          STATIC TerminateInProcess AS LONG
                          LOCAL ErrorRecord AS EXCEPTION_RECORD POINTER
                          LOCAL ErrorCode AS LONG POINTER
                          LOCAL WhatToTrace AS STRING
                          LOCAL i AS LONG                                                  'For homing in on where the exception occurred
                          LOCAL CallStackFunctions AS STRING                               'For homing in on where the exception occurred
                          SELECT CASE TerminateInProcess                              'If Unloading due to error let the OS handle it.
                               CASE %TRUE
                                    SetUnhandledExceptionFilter %EXCEPTION_EXECUTE_HANDLER 'Reactivate default Error Handler
                                    RaiseException %NULL, %NULL, %NULL, %NULL              'Force normal Error Handler
                '*** Exit the thread (and application if this is the only thread)
                                    ExitThread 0
                               CASE %FALSE
                                    TerminateInProcess = %TRUE
                                    ErrorRecord = lpEP.pExceptionRecord                    'Detect the actual exception record
                                    DO UNTIL @ErrorRecord.pExceptionRecord = 0             'Gather the exception record(s)
                                         CALL MoveMemory(@ErrorRecord, @ErrorRecord.pExceptionRecord, SIZEOF(ErrorRecord))
                                    LOOP
                                    ErrorCode   = @ErrorRecord.ExceptionCode
                '*** Now we have in ErrorCode the ExceptionCode, that raised the crash, log the info
                                    SELECT CASE ErrorCode
                                         CASE %EXCEPTION_ACCESS_VIOLATION
                                              WhatToTrace =   "ACCESS VIOLATION" + " <---> " + "The thread tried to read from or write to a virtual address for which it does not have the appropriate access"
                                         CASE %EXCEPTION_ARRAY_BOUNDS_EXCEEDED
                                              WhatToTrace =   "ARRAY BOUNDS EXCEEDED" + " <---> " + "The thread tried to access an array element that is out of bounds and the underlying hardware supports bounds checking."
                                         CASE %EXCEPTION_BREAKPOINT
                                              WhatToTrace = "BREAKPOINT" + " <---> " + "A breakpoint was encountered."
                                         CASE %EXCEPTION_DATATYPE_MISALIGNMENT
                                              WhatToTrace =   "DATATYPE MISALIGNMENT" + " <---> " + "The thread tried to read or write data that is misaligned on hardware that does not provide alignment. For example, 16-bit values must be aligned on 2-byte boundaries"
                                         CASE %EXCEPTION_FLT_DENORMAL_OPERAND
                                              WhatToTrace =  "FLOAT DENORMAL OPERAND" + " <---> " + "One of the operands in a floating-point operation is denormal. A denormal value is one that is too small to represent as a standard floating-point value."
                                         CASE %EXCEPTION_FLT_DIVIDE_BY_ZERO
                                              WhatToTrace =  "FLOAT DIVISION BY ZERO" + " <---> " + "The thread tried to divide a floating-point value by a floating-point divisor of zero."
                                         CASE %EXCEPTION_FLT_INEXACT_RESULT
                                              WhatToTrace =  "FLOAT INEXACT RESULT" + " <---> " + "The result of a floating-point operation cannot be represented exactly as a decimal fraction."
                                         CASE %EXCEPTION_FLT_INVALID_OPERATION
                                              WhatToTrace =  "FLOAT INVALID OPERATION" + " <---> " + "This exception represents any floating-point exception not included in this list."
                                         CASE %EXCEPTION_FLT_OVERFLOW
                                              WhatToTrace =  "FLOAT OVERFLOW" + " <---> " + "The exponent of a floating-point operation is greater than the magnitude allowed by the corresponding type."
                                         CASE %EXCEPTION_FLT_STACK_CHECK
                                              WhatToTrace =  "FLOAT STACK CHECK" + " <---> " + "The stack overflowed or underflowed as the result of a floating-point operation."
                                         CASE %EXCEPTION_FLT_UNDERFLOW
                                              WhatToTrace =  "FLOAT UNDERFLOW" + " <---> " + "The exponent of a floating-point operation is less than the magnitude allowed by the corresponding type."
                                         CASE %EXCEPTION_ILLEGAL_INSTRUCTION
                                              WhatToTrace =  "ILLEGAL INSTRUCTION" + " <---> " + "The thread tried to execute an invalid instruction."
                                         CASE %EXCEPTION_IN_PAGE_ERROR
                                              WhatToTrace = "IN PAGE ERROR" + " <---> "
                                              WhatToTrace = WhatToTrace + "The thread tried to access a page that was not present, and the system was unable to load the page."
                                              WhatToTrace = WhatToTrace + "For example, this exception might occur if a network connection is lost while running a program over "
                                              WhatToTrace = WhatToTrace + "the network."
                                         CASE %EXCEPTION_INT_DIVIDE_BY_ZERO
                                              WhatToTrace =   "INTEGER DIVISION BY ZERO" + " <---> " + "The thread tried to divide an integer value by an integer divisor of zero."
                                         CASE %EXCEPTION_INT_OVERFLOW
                                              WhatToTrace =   "INTEGER OVERFLOW" + " <---> " + "The result of an integer operation caused a carry out of the most significant bit of the result."
                '                         CASE %EXCEPTION_INVALID_DISPOSITION
                '                              WhatToTrace =   "INVALID DISPOSITION" + " <---> " + "An exception handler returned an invalid disposition to the exception dispatcher. Programmers using a high-level language such as C should never encounter this exception."
                '                         CASE %EXCEPTION_NONCONTINUABLE_EXCEPTION
                '                              WhatToTrace =   "NONCONTINUABLE EXCEPTION" + " <---> " + "The thread tried to continue execution after a noncontinuable exception occurred."
                                         CASE %EXCEPTION_PRIV_INSTRUCTION
                                              WhatToTrace =   "PRIVATE INSTRUCTION" + " <---> " + "The thread tried to execute an instruction whose operation is not allowed in the current machine mode."
                                         CASE %EXCEPTION_SINGLE_STEP
                                              WhatToTrace =   "SINGLE STEP" + " <---> " + "A trace trap or other single-instruction mechanism signaled that one instruction has been executed."
                                         CASE %EXCEPTION_STACK_OVERFLOW
                                              WhatToTrace =  "STACK OVERFLOW" + " <---> " + "The thread used up its stack."
                                         CASE ELSE
                                              WhatToTrace =  CHR$(0)
                                    END SELECT
                                    FOR i = CALLSTKCOUNT TO CALLSTKCOUNT - 1 STEP -1
                '                    CallStackFunctions = CallStackFunctions + CALLSTK$(i)
                                         CallStackFunctions = CALLSTK$(i)
                                    NEXT i
                '*** Code for writing a crash-log, save opened documents etc...
                                    WhatToTrace = $TAB + "Unhandled WindowsException - " + STR$(@ErrorRecord.ExceptionCode) + " - " + WhatToTrace + $CRLF + $TAB + " Function = " + CallStackFunctions + " at line: " + STR$(ERL)
                                    TracePrint WhatToTrace
                '*** Exit the thread (and application if this is the only thread)
                                    ExitThread 0                  'This will stop the typical "*.exe has encountered a problem and needs to close" error message to send a report to M$
                          END SELECT
                     END FUNCTION
                #ENDIF
                Engineer's Motto: If it aint broke take it apart and fix it

                "If at 1st you don't succeed... call it version 1.0"

                "Half of Programming is coding"....."The other 90% is DEBUGGING"

                "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                Comment


                • #9
                  I have the same issue in my CCSBatch program, I've found I think that changing to the drive helps..


                  Michael - Outstanding piece of code, I've used that API in the past - but on XP it's still a crapshoot whether XP removes it or not, hence if you look in c:\Documents and Settings\{username}\Local Settings\Temp you'll see in a lot of cases they don't get removed....I suspect it's an XP thing (?).

                  I always set TMP and TEMP to C:\TmpFiles but inevitably have to clean it out once in a while...
                  Scott Turchin
                  MCSE, MCP+I
                  http://www.tngbbs.com
                  ----------------------
                  True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                  Comment


                  • #10
                    A very late update.....

                    Encountered exactly the same problem with Error 70 using Windows 7 and PB10.3. The following solutions were tried :

                    a) No effect of using DIR$ CLOSE after the DIR$ function was used to locate and delete files within the directory

                    b) Ensuring that all hidden etc. files and sub-folders were removed from the sub-directory

                    c) Checked and the (empty) directory had the file attribute 16 so definitely was not read only.

                    d) The directory was located in an area on the C Drive that the program is able to modify:
                    C:\Users\<UserName>\AddData\Roaming\<Program_name>\<directory>

                    e) The problem only seemed to arise if the directory had been accessed by an external program prior to the PB10 program trying to delete it (which seems odd but may be something to do with directory ownership).

                    f) The path length was about 60 characters long (so under the 132 size limit mentioned elsewhere)

                    g) No effect of converting the directory name to a short path name.

                    The solution seems to be in my case to run CHDIR to an irrelevant directory immediately before the RMDIR statement. Tested in a few situations and seems to completely eliminate the problem.


                    Last edited by Peter Simmonds; 12 Apr 2017, 07:12 AM. Reason: Forgot to add some information

                    Comment


                    • #11
                      Encountered exactly the same problem with Error 70 using..
                      Code not shown (one of the programs posted this thread?).

                      That said, . PB error 70 can occur for many different reasons, but PB lumps them all together into ERR_:PERMISSIONDENIED. You might try using Win API functions with GetLastError() to pinpoint exactly what problem the O/S may have had deleting the directory.

                      MCM


                      Michael Mattias
                      Tal Systems (retired)
                      Port Washington WI USA
                      [email protected]
                      http://www.talsystems.com

                      Comment


                      • #12
                        Process Monitor will get you OS fail information on any operation to do with the Registry, Files and/or Directories without having to change the code of the app.

                        Comment


                        • #13
                          If the folder is the default data folder for the exe at the time then the exe itself has the folder open so error 70 and it can't delete it. Simply CHDIR to some other folder first.

                          Comment


                          • #14
                            Yepp. Even Windows Explorer falls for that trick/behaviour. If Windows considers some process to have the folder in question to as its "current folder", an Access/Permission Denied error is raised.

                            I've seen this quite a lot, even in this forum, that for whatever reason programmer's CHDIR around. Not sure why this is (still) considered to be necessary at all. Might have been a necessarity back in the DOS days ...

                            Comment

                            Working...
                            X