Tfilestream

hi,

the following is an example from a larger project in D3 under WIN98.

i extracted it for there is a crazy error:

in the Tfilestream.create always getlasterror is 87 !!

what is this ??

any ideas ?

thanks
titz

CODE:
on the form is only a timer which every 2 secs calls
the proc "actual".
"init0" is called OnCreate and "can_close" is called on
OnCloseQuery.


{$A+,B-,D-,L-,N+,E+,F-,I-,O+,P-,Q+,R+,S+,T-,V+,X+}

unit apic2U;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    procedure init0(Sender: TObject);
    procedure can_close(Sender: TObject; var CanClose: Boolean);
    procedure actual(Sender: TObject);
  public
   kfont:Tfont;
   procedure done0;
   procedure api_show;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}


const
sperrd='NETSPR2.NET';
spnmax=20;

type
str50=string[50];
sperrtyp=array[0..spnmax] of longint;
 
var
fssperre:Tfilestream;

(* -------------------------------- *)

   procedure api_open(var jf:longint);
   begin
   jf:=getlasterror;
   fssperre:=tfilestream.create(sperrd,fmopenreadwrite or fmsharedenynone);
   jf:=getlasterror;
   end;            
   
   procedure api_close;

   begin
   fssperre.free;
   fssperre:=nil;
   end;
   
(* ----------------------------------- *)
   
procedure TForm1.init0(Sender: TObject);

begin
left:=10;
top:=10;
height:=450;
kfont:=Tfont.create;
kfont.size:=8;
kfont.name:='Courier';
end;

procedure TForm1.done0;
begin
kfont.free;
kfont:=nil;
end;

procedure TForm1.can_close(Sender: TObject; var CanClose: Boolean);
begin
canclose:=true;
done0;
end;

procedure TForm1.api_show;

var
jf:longint;
x0:integer;
z:str50;
                         
begin
rectangle(canvas.handle,0,0,630,470);
selectobject(canvas.handle,kfont.handle);
x0:=45;
api_open(jf);
if jf<>0 then
   begin
   str(jf,z);
   canvas.textout(x0,10,z+'xxxxxxxxxxx');
   end
else
   begin
   api_close;  
   end;
end;

procedure TForm1.actual(Sender: TObject);
begin
api_show;
end;

end.
 
LVL 1
titzAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LischkeCommented:
Hi titz,

I'd say try direct API calls for your file (CreateFile or OpenFile) and see what they return. Don't call GetLastError before you open the file but SetLastError(0) to make sure there's no pending error. From the name of the lock file (Sperr klingt ziemlich Deutsch :-) I assume the file is located on a network drive. This might cause the problem (but I don't know why as I cannot reproduce the problem here).

Try also to open the file only for reading but with exclusive access (deny all other accesses).

Ciao, Mike
0
DrDelphiCommented:
You neglected to take into accouunt that the file might not exist. Try:

   fssperre:=tfilestream.create(sperrd,(Fmcreate or fmopenreadwrite or fmsharedenynone));

This will ALWAYS open the filestream regardless if the named file exists or not... if it does, it opens the disk file, if not it creates it.

0
LischkeCommented:
Yes I thought about it too, but if the file doesn't exist the file stream creation fails already (which is not the problem for titz). I tried out various combination with the stream (including access to our office network) and I could not reproduce the problem, so I'm just guessing here...

Ciao, Mike
0
Build an E-Commerce Site with Angular 5

Learn how to build an E-Commerce site with Angular 5, a JavaScript framework used by developers to build web, desktop, and mobile applications.

DrDelphiCommented:
Mike,
  I think that the problem IS that:
"in the Tfilestream.create always getlasterror is 87 !!".... Error 87 is an invalid parameter. What's more of an invalid parameter than passing a filename that does not exist? <G>

The bottom line is this: I was able to replicate the error 87  every single time with the code supplied. When I make the changes I suggested the error goes away. Just that simple. <G>



0
LischkeCommented:
Interesting, might be a Win9x problem. I'm working under WinNT and that could be the cause for the different results.

Ciao, Mike
0
DrDelphiCommented:
Hmmm.... I wonder if it might not make more sense to do something like this:


if FileExists(sperrd) then
begin
  fssperre:=tfilestream.create(sperrd,fmopenreadwrite or fmsharedenynone));
  yada,
  yada,
  yada,
end
else
  fssperre:=tfilestream.create(sperrd,
 (Fmcreate or fmopenreadwrite or fmsharedenynone));
end;


* forgive my indentation (or lack of), it is IMPOSSIBLE to type anything in this little box! <G>
 
0
titzAuthor Commented:
hi Drdelphi and Lischke,

first: the file exists.
now i tried the suggestions from DrDelphi:
i included fmcreate...:
then i got the errorcode 183 and the file had a new length of 0 !

then i tried another thing:
i added a
fileexists(fsperrd) : this returned with true.

then i changed the Tfilestream.create back(=without fmcreate):
and (!!) added setlasterror(0):
all worked ok.

that was the real reason:
setlasterror(0) (before Tfilestream.create).

   setlasterror(0);
   fssperre:=tfilestream.create(sperrd,fmopenreadwrite or fmsharedenynone);
   jf:=getlasterror;

the error without setlasterror(0) was reproducible.
one question to Lischke: should the "setlasterror" always be done
before any file-operation (with following "getlasterror") ?
therefore Lischke shall have the points.

hi Lischke,
you are right: it is a part of a network-locking program.
i did this because i need a solution which works under WIN95/98 and NT4.0 and will work under WIN2000 (if it will come).

thanks
titz

0
titzAuthor Commented:
by the way: one more question:
there was a function which returns the systemerror-code given from getlasterror to text. but i forget the name... getsystemerrormessages ... or so. do you no the exact name ?

thanks
titz
0
LischkeCommented:
Hi Titz,

aha, it turns out that there went another action wrong before your code came to execution. You don't need to call SetLastError before every file operation, but you should call it in cases where you check the last error afterwards. There are a few actions within the VCL which can fail without harm (according to BoundsChecker), but set the last error to a value <> 0.

The functions you are asking for are:

RaiseLastWin32Error (to raise an exception if GetLastError returns a value <> 0) and SysErrorMessage which takes an error code as parameter and returns a textual description in a string.

Ciao, Mike
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.