user8643548
user8643548

Reputation:

AssignFile(): File access denied

I want to create a .txt file and write to it at any moment at run-time. To do this, I'm using the AssignFile() function. But I am having trouble in instances where my file already exists. I get an error that says: File access denied.

To better explain, see these two examples:

Ex1: if I call AssignFile() the first time when the file does not exist, OK! But, if the file exists, this does not work.

Ex2: if I call AssignFile() the second time (when AssignFile() was successful the first time), this also does not work.

Is this a bug in the AssignFile() function?

var
  myfile: TextFile;

  Procedure WriteFileContent(const MyTxtFile: string; MyNumber: DWORD);
  var
    F: TextFile;
  Begin
    If FileExists(MyTxtFile) Then
    Begin
      AssignFile(F, MyTxtFile);
      Rewrite(F);
      Writeln(F, '0x' + IntToHex(MyNumber,8));
      CloseFile(F);
    End;
  End;

begin
  try

    // Calling AssignFile() by first time
    AssignFile(myfile, 'myfile.txt');
    Rewrite(myfile);
    CloseFile(myfile);
    setfileattributes('myfile.txt', FILE_ATTRIBUTE_HIDDEN);

    Sleep(5000);

    // Calling AssignFile() by second time
    WriteFileContent('myfile.txt', 123456789);

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

Upvotes: 4

Views: 4675

Answers (1)

Tom Brunberg
Tom Brunberg

Reputation: 21033

It is not AssignFile() that fails, but your call to Rewrite() on a file with the Hidden attribute set. Following explains it:

Typically you call Rewrite(F) in order to erase the file and write new data to it with subsequent Write(F, ...) or WriteLn(F, ...) calls.

From docs (System.Rewrite):

If an external file with the same name already exists, it is deleted and a new empty file is created in its place.

There is no problem opening the file for writing with the Append() command.

(Based on above I drew the conclusion that it is the deletion that fails with the Access denied message. That was cutting the corners too much.)


Beaten by comments I traced through the code and compared actual code with MSDN documentation for CreateFile:

Actual code:

// if mode is fmOutput (as it is for Rewrite)
OpenMode = GENERIC_WRITE
Flags = CREATE_ALWAYS
// ...
Temp := CreateFile(t.Name, OpenMode, FILE_SHARE_READ, nil, Flags, FILE_ATTRIBUTE_NORMAL, 0);

And documentation:

If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile fails and sets the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute.

Calling Rewrite() on a existing file with the hidden attribute fails always.

Upvotes: 7

Related Questions