try with TSearchRec.Attr , findFirst(), findNext()...
but I think this is only for get the read-only, hidden attribute or date and time but not sure for the rest.
Main Topics
Browse All TopicsOur programs often write something into some.ini file. The clients may run several our programs simultaneously. Occationally, we have error message, it says unable to write to some.ini. I believe this is because more than one procedures tring to write to some.ini at same time. So I think I should check some.ini file status first, find it is OK(the file is not in write), then write to this file. But what is the file status(attribute), and how to get it?
Peter
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
I've put together a function for you that will do what you need.
//*** Returns true if key/value is successfylly written, false otherwise
//*** -Timeout must be given in seconds and indicates how long you are
//*** willing to wait for the function to complete
//*** function assumes the file exists, raises an exception if not...
function WriteINIFile(fname, key, value: string; Timeout: integer): boolean;
var f: TFileStream;
TimeoutReached: boolean;
StartTime: TDateTime;
bytesWritten: integer;
buf: string;
begin
result:= false;
try
f:= TFileStream.Create(fname, fmOpenWrite, fmShareDenyWrite);
try
StartTime:= now;
while (NOT result) AND (NOT TimeoutReached) do
begin
TimeoutReached:= (Now > (StartTime + Timeout/86400)); //86400 seconds in a day
buf:= #13#10+key+'='+value;
f.Seek(f.Size, soFromBeginning);
bytesWritten:= f.Write(buf[1], Length(buf));
result:= (bytesWritten <> 0);
//result:= (bytesWritten <> SizeOf(buf)); --> would be more precise i.e. would return false if only part of buf is written
end;
except
result:= false;
end;
finally
try f.Free except end;
end;
end;
procedure TForm1.Button1Click(Sender
begin
WriteINIFile('c:\testing.i
end;
Regards
Pierre
Just realised something:
The constructor should fall within the timeout loop because an exception will be raised if the file can not be opened in write mode (i.e. when another instance of your app is writing to the file. Change the function as follows:
//*** Returns true if key/value is successfylly written, false otherwise
//*** -Timeout must be given in seconds and indicates how long you are
//*** willing to wait for the function to complete
//*** function assumes the file exists
function WriteINIFile(fname, key, value: string; Timeout: integer): boolean;
var f: TFileStream;
TimeoutReached: boolean;
StartTime: TDateTime;
bytesWritten: integer;
buf: string;
begin
result:= false;
f:= nil;
try
StartTime:= now;
while (NOT result) AND (NOT TimeoutReached) do
begin
TimeoutReached:= (Now > (StartTime + Timeout/86400)); //86400 seconds in a day
if TimeOutReached then break;
if f = nil then try
f:= TFileStream.Create(fname, fmOpenWrite, fmShareDenyWrite);
buf:= #13#10+key+'='+value;
f.Seek(f.Size, soFromBeginning);
bytesWritten:= f.Write(buf[1], Length(buf));
result:= (bytesWritten <> 0);
//result:= (bytesWritten <> SizeOf(buf)); --> would be more precise i.e. would return false if only part of buf is written
except
result:= false;
end;
end;
finally
try f.Free except end;
end;
end;
NOTE: The fmShareDenyWrite parameter is only for Linux platform, it is ingored on windows platform
Regards
Pierre
Peter,
The problem with "getting file status" is that it may well change from [Available] to [Buzy] between two lines of code anyway. (You will evetually run out of quouta between the test and the actual write operation)
The only way to be sure - as far as I understand - is to really try to perform the op. and try again if it fails.
But sure, a sleep() can do it
{ --------------------------
Function TryToWriteToTheFile : boolean;
var tries : integer;
done : boolean;
Begin
done := false;
tries := 0;
Repeat
Try
[Write To File] // Do the actual write op.
Done := true; // We are still here - no errors - we made it.
except
Inc(tries); // Nope - we got transferred the the exception handler - wait a while
Sleep(200); // Should be enough
end;
Until Done or (Tries > 50); // We have to time out eventually, 10 seconds here...
Result := done;
{-------------------------
Hope this solves it
Br's
/Starkbock
Hi Starkbock
Your code is absolutely working. Thank u.
I just think if add file status check before [Write To File](see below), it will be better. Just don't know how and what file status to check.
Function TryToWriteToTheFile : boolean;
var tries : integer;
done : boolean;
Begin
done := false;
tries := 0;
Repeat
Try
if CheckFileStatusOK then
begin
[Write To File] // Do the actual write op.
Done := true; // We are still here - no errors - we made it.
end;
except
Inc(tries); // Nope - we got transferred the the exception handler - wait a while
Sleep(200); // Should be enough
end;
Until Done or (Tries > 50); // We have to time out eventually, 10 seconds here...
Result := done;
Business Accounts
Answer for Membership
by: StarkbockPosted on 2005-03-01 at 23:25:41ID: 13436855
Regarding file status for INI-files.
I hope I write the answer at the right place now ( all the ads confuses me...)
My immediate solution - idea - would be to have the INI-file update executed by a TTimer.
When it is time to make an update to the INI-file, you simply enable the timer, which runs at - say 1/2 Hz. (No reason to have too high rate)
In the Timer event handler you do a
Try
[write to ini file]
Timer.enabled := false;
except;
end;
So if the write fails - and the "Try..." should mask it - another atempt will be executed two seconds later.
If the write succeeds, the timer will disable itself and everybody lives happily ever after.
In case the user wants to quit your app before the write has completed you'll notice that the Timer is still enabled, and you may hang around for a while before you terminate.
(At some occations I have simply hidden my apps i.s.o terminating them immediately when I have to do some stuff before termination.)
Hope it solves you problem.
Br's
/Starkbock