Fopen() 2.0.0.5

This forum is meant for questions and discussions about the X# language and tools
Post Reply
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Fopen() 2.0.0.5

Post by robert »

Karl Heinz,
Which errorcode do you mean ?

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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 )
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Fopen() 2.0.0.5

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Fopen() 2.0.0.5

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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
User avatar
robert
Posts: 4225
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Fopen() 2.0.0.5

Post 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
XSharp Development Team
The Netherlands
robert@xsharp.eu
Karl-Heinz
Posts: 774
Joined: Wed May 17, 2017 8:50 am

Fopen() 2.0.0.5

Post 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
Post Reply