Page 1 of 1
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 9:22 am
by Karl-Heinz
Guys,
i´m playing with the 2.0.0.5 Fopen() and noticed that if the func fails the errorcode is always 1008 ?
Is that a known issue, or maybe even fixed in the meantime ?
regards
Karl-Heinz
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 9:27 am
by robert
Karl Heinz,
Which errorcode do you mean ?
Robert
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 10:45 am
by Karl-Heinz
Hi Robert,
The file "D:testFFunction.txt" exists. when i change the dir or filename Fopen() fails, and the errorcodes are always the same.
Code: Select all
IF ( h := Fopen ( "D:testFFunctio.txt" )) != F_ERROR // file doesn´t exist errcode should be 2
// IF ( h := Fopen ( "D:tesFFunction.txt" )) != F_ERROR // dir doesn´t exist errcode should be 3
? "ok"
Fclose ( h )
ELSE
? "Getlasterror()" , getlasterror() // always 1008
? "Ferror()", Ferror() // always 1008
? "GetDosError()" , Getdoserror() // always 1008
? GetSystemMessage ( fError() ) // localized text is shown
ENDIF
To see in x# the errortext i translated the VO func GetSystemMessage( dwID AS DWORD )
Code: Select all
FUNCTION GetSystemMessage( dwID AS DWORD ) AS STRING
RETURN System.ComponentModel.Win32Exception{ (INT) dwID }.Message
FUNCTION GetSystemMessage() AS STRING
RETURN GetSystemMessage ( (DWORD) System.Runtime.InteropServices.Marshal.GetLastWin32Error() )
regards
Karl-Heinz
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 11:03 am
by Karl-Heinz
BTW. The "magic" number 1008 also appears if the file is locked ( errcode 32 should be shown ) or the path or filename contains "bad chars" ( errcode 123 should be shown )
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 12:43 pm
by robert
Karl-Heinz,
The X# runtime does not use the same underlying OS calls when opening a file. It uses managed streams in stead.
The File Handle that is returns is just a unique id that matches the stream in a dictionary in the runtime.
Inside the FileStream constructor the "File Not Found" situation is decoded into a FileNotFoundException. We are capturing this and we are assigning Marshal.GetLastWin32Error() to Ferror().
Apparently at that moment GetLastWin32Error has already received a new value.
I can see in the constructor of FileStream that the __Error.WinIOError() method is called with the GetLastWin32Error and when this error is 2 then the FileNotFoundException is generated.
Maybe we should expose the exception object in a FException() function so you can see which exception occurred ?
Or we should decode the exception type back into the numbers and store these numbers in FError() ?
Robert
Fopen() 2.0.0.5
Posted: Wed Nov 07, 2018 4:25 pm
by Karl-Heinz
Hi Robert,
Since FError() is a vo/x# specific thing, my first thought is to keep using it. It seems that the CreateManagedFileStream() method is responsible for the errorcode.
Code: Select all
private static method createManagedFileStream(cFIle as string , oMode as VOFileMode ) as FileStream
local result as FileStream
//
result := null
try
result := FileStream{cFIle, oMode:FileMode, oMode:FileAccess, oMode:FileShare, 4096}
return result
catch ex as Exception
Trace.WriteLine(ex:Message)
Functions.FError((DWord)Marshal.GetLastWin32Error())
return result
end try
FileStream throws, beside others, 4 exceptions of interest:
Code: Select all
ArgumentException // bad param - illegal chars in pathname or filename detected errorcode 97
( VO gives 123 - shows IMO a better explanation than 97 )
DirectoryNotFound // should show errorcode 3
FileNotFound // should show errorcode 2
IOException // should show errorcode 32 - Access violation
i have a func that returns the errorcode of an exception. Does it make any differences when you fill fError() in this way
Code: Select all
catch ex as Exception
Trace.WriteLine(ex:Message)
Functions.FError( GetErrorCodeFromException ( eX ) )
return result
or does it make any difference to split the exceptions
catch ex as ArgumentException
Trace.WriteLine(ex:Message)
Functions.FError( GetErrorCodeFromException ( eX ) )
return result
catch ex as DirectoryNotFound
Trace.WriteLine(ex:Message)
Functions.FError( GetErrorCodeFromException ( eX ) )
return result
etc.
FUNCTION GetErrorCodeFromException ( o AS Exception ) AS DWORD
RETURN _and ( (DWORD) System.Runtime.InteropServices.Marshal.GetHRForException ( o ) , 0x0000FFFF )
regards
Karl-Heinz
Fopen() 2.0.0.5
Posted: Thu Nov 08, 2018 9:42 am
by robert
Karl-Heinz,
Karl-Heinz wrote:
Code: Select all
FUNCTION GetErrorCodeFromException ( o AS Exception ) AS DWORD
RETURN _and ( (DWORD) System.Runtime.InteropServices.Marshal.GetHRForException ( o ) , 0x0000FFFF )
Thanks for the example. And it works !
Can I use this and add it to the exception handling code in the runtime ?
This is what I like so much about open source. Community driven code !
Robert
Fopen() 2.0.0.5
Posted: Thu Nov 08, 2018 5:00 pm
by Karl-Heinz
Hi Robert,
Great news !
Glad to hear that it works, and of course, you may use the code !!
Compared to what you and your team is doing, this "two Liner" is nothing, it´s just a translation of a c# snippet that i´ve found somewhere.
One question: GetLastWin32Error() still shows 1008, right ?
regards
Karl-Heinz
Fopen() 2.0.0.5
Posted: Thu Nov 08, 2018 5:21 pm
by robert
Karl-Heinz,
If you mean the Marshal.GetLastWin32Error(). We are not touching that. So it keeps on returning 1008. And our DosError() returns the same because it calls that method.
I have changed the code that touches FError() to:
TRY
clearErrorState()
// do something
CATCH e as Exception
setErrorState(e)
END TRY
Inside clearErrorState the last errorcode and last exception are cleared.
Inside setErrorState() the exception is saved and the errorcode is retrieved using the method that you indicated.
Ferror() now returns what you expect.
I have also added FException() that returns the Exception object for more information.
Robert
Robert
Fopen() 2.0.0.5
Posted: Sat Nov 10, 2018 12:09 pm
by Karl-Heinz
Hi Robert,
In Github i see the changes you´ve made. BTW. it´s a very nice feature to be able to jump to the latest sources via the [view source] button in the help file.
regards
Karl-Heinz