Jim S
Jim S

Reputation: 427

Delphi: File access and compatibility files (windows 7)

Let's suppose my app in named mysoft and the file I want to READ is afile.bin. mysoft is in the program file folder. Let's also suppose that mysoft is not executed with admin privileges.

procedure TForm1.Button1Click(Sender: TObject);
var 
  afile: File of Byte;
begin
  AssignFile(Infile, 'C:\Program Files\mysoft\afile.bin');
  Reset(afile);
  CloseFile(afile);
end;

The simple code above will create a copy of afile.bin in the compatibility files folder.

My questions are:

  1. Why ? I only read the damn file, I don't want to modify it.
  2. How to prevent this other than moving the file in another folder ?

Again I only read the data file, I don't get it.

Upvotes: 4

Views: 1315

Answers (3)

David Heffernan
David Heffernan

Reputation: 613511

The call to Reset results in the file being opened for writing. That's because the default value of System.FileMode is fmOpenReadWrite. Since your app runs virtualized, and since your user token does not have admin rights, the virtualization layer kicks in and creates a copy of the file in the virtual store.

The solution that is available using legacy Pascal I/O is to set FileMode to fmOpenRead. Then Reset will open the file for reading and the virtualization layer will not be invoked.

Remember that FileMode is a global variable that affects all legacy Pascal I/O. Woe betide you if you have threads, or forget to set FileMode back to fmOpenReadWrite when you need to write a file. Revolting isn't it? Process wide global flags to control file access mode! Well, this stuff was invented long before applications had threads. And long before OOP was invented. So I can understand why it is so.

The lesson to take away from this is that it is time to switch to one of the modern forms of file access. For example, TFileStream.

Indeed, it's also time that you disabled virtualization in your application. Virtualization was introduced in Vista, nearly 6 years ago. It was meant as a help for old programs that had not yet been re-compiled for Vista. Your application should not be using it still.

Upvotes: 5

opc0de
opc0de

Reputation: 11768

If you have a version of Delphi that supports the TStreamReader class and your file is text you can use this code :

procedure TForm1.btn1Click(Sender: TObject);
var
  SR : TStreamReader;
  line : string;
begin
  SR := TStreamReader.Create('C:\Program Files\mysoft\afile.bin');
  try
  while not SR.EndOfStream do
  begin
    line := SR.ReadLine;
  end;
  finally
  SR.Free;
  end;
end;

If not I suggest a more classical approach that works on any file :

procedure TForm1.btn2Click(Sender: TObject);
var
  FS : TFileStream;
  mem : array of byte;
begin
  FS := TFileStream.Create('C:\Program Files\mysoft\afile.bin',fmOpenRead or fmShareDenyNone);
  try
  SetLength(mem,FS.Size);
  FS.Read(mem[0],FS.Size);
  finally
  FS.Free;
  end;
end;

Upvotes: 2

sybond
sybond

Reputation: 167

I believe this is because the Windows 7 "new feature", which is disallow you to do directly access a file in file system area (%programfiles%, %systemroot%, %systemdrive%, or %programdata%).

Try to change your code to open file using TFileStream, and set Mode to fmOpenRead.

I hope it works. I don't have 7 to try it :)

Upvotes: 0

Related Questions