I created a GIST with my FileApiRemove() that can be used to replace calls to the RTL REMOVE(String) function. It calls the API DeleteFile(). It sets the RTL ErrorCode() and Error() so no other code changes are required. This is faster and safer.
MODULE('ClaApi')
!These Error functions have been in the RTL forever and appear in LibSrc but are not documented
SetError(LONG ErrNumberToSet),NAME('Cla$SetError'),DLL(DLL_Mode)
ClearError(),NAME('Cla$ClearError'),DLL(DLL_Mode)
END
FileApiRemove FUNCTION(STRING Fn2Delete),LONG,PROC !API Replacement 0=OK else GetLastError(). Can ignore sets RTL ErrorCode()
!===================================================================================================
! FileApiRemove() replacement for Clarion REMOVE() in that it sets the ErrorCode() and Error().
! This also returns the API GetLastError() or Zero for Success
!===================================================================================================
FileApiRemove FUNCTION (STRING Fn2Delete)!,LONG,PROC !0=ok, else returns Error code, also sets RTL ERRORCODE() ERROR()
cFN CSTRING(261),AUTO
ApiError LONG !GetLastError() when DeleteFile() fails
ClarionErr LONG !Api Error converted to matching Clarion Error number
CODE
cFN=clip(Fn2Delete)
IF 0=DeleteFile(cFn) THEN !Return 0 = Failed to DeleteFile() see GetLastError() for why
ApiError=GetlastError()
IF ~ApiError THEN ApiError=1. !Return says Failed, but no error ... so set something, should never happen
ClarionErr = ApiError !Most Clarion Error Numbers are the same as API Error Number
CASE ApiError !Translate some unusual GLE to errors to Clarion
OF 32 ; ClarionErr = 52 !API ERROR_SHARING_VIOLATION 32 (0x20) The process cannot access the file because it is being used by another process.
! Clarion Help says Error 52 = File Already Open - An attempt to OPEN a file that has already been opened by this user.
END
SetError(ClarionErr) !Set Error in RTL so caller can use ERRORCODE() just like if used RTL REMOVE()
ELSE !non-zero return from DeleteFile() means it worked and file was deleted
ClearError() !Delete worked set Error to Zero (close) in RTL so caller can use ERRORCODE()
END
RETURN ApiError !Return is Optional (PROC) so caller can check API Error Code if desired
!--------------------------------------------
!Possible enhancement, if fails could Sleep(100) and retry 5 times, file may have
!just been closed and Virus scanner is looking at it, or OS is catchng up to commit delete
!
!SQLite has notes about exactly this problem.
! #define MX_DELETION_ATTEMPTS 5
! do{
! DeleteFileA(zConverted);
! }while( ( ((rc = GetFileAttributesA(zConverted)) != INVALID_FILE_ATTRIBUTES)
! || ((error = GetLastError()) == ERROR_ACCESS_DENIED))
! && (++cnt < MX_DELETION_ATTEMPTS)
! && (Sleep(100), 1) );
!---------------------------------------------