为什么我的Delphi应用程序说文件不存在?

时间:2018-11-27 22:05:01

标签: windows delphi

我有以下32位Delphi项目源代码:

program TestApp;

uses
  SysUtils, Dialogs, Windows;

var
  filename: String = 'C:\Program Files (x86)\Some Application\foo.txt';
  fd: TWIN32FindData;
  h: THandle;

begin
  FillChar(fd, SizeOf(fd), 0);
  h := FindFirstFile(PChar(filename), fd);
  if h = INVALID_HANDLE_VALUE then
    ShowMessage('FindFirstFile=false')
  else
  begin
    ShowMessage('FindFirstFile=true');
    FindClose(h);
  end;

  if FileExists(filename) then
    ShowMessage('FileExists=true')
  else
    ShowMessage('FileExists=false');
end.

当我运行它时,即使该目录中不存在文件 ,Windows API FindFirst调用和FileExists调用都返回True。

为什么它声称一个文件在不存在的地方?

1 个答案:

答案 0 :(得分:3)

该文件位于以下位置的VirtualStore目录中:

C:\Users\{username}\AppData\Local\VirtualStore\Program Files (x86)

这是Windows Vista中首次引入的称为 UAC虚拟化的功能。它允许应用程序写入受限的目录,否则它们将无权访问。当启用了UAC虚拟化的32位应用程序写入真实目录并收到拒绝访问的结果时,Windows会在VirtualStore中创建该文件的副本。

当此应用程序或另一个启用了UAC虚拟化的32位应用程序尝试从文件读取时,它将首先在VirtualStore中检查文件。通过在任务管理器中添加此列,您可以看到已启用UAC虚拟化。

在删除{$R *.res}指令时,这会在Delphi程序中发生。如果更改项目源以将{$R *.res}指令重新添加回

program TestApp;

uses
  SysUtils, Dialogs, Windows;

{$R *.res}

var
  filename: String = 'C:\Program Files (x86)\Some Application\foo.txt';
  fd: TWIN32FindData;
  h: THandle;

begin
  FillChar(fd, SizeOf(fd), 0);
  h := FindFirstFile(PChar(filename), fd);
  if h = INVALID_HANDLE_VALUE then
    ShowMessage('FindFirstFile=false')
  else
  begin
    ShowMessage('FindFirstFile=true');
    FindClose(h);
  end;

  if FileExists(filename) then
    ShowMessage('FileExists=true')
  else
    ShowMessage('FileExists=false');
end.

它将识别您的应用程序已禁用UAC虚拟化(这是大多数应用程序的规范)。您可以在任务管理器中看到这一点,并且文件查找操作的结果将与您期望的一样。

.RES文件遗漏的原因是它包含清单。此清单中的以下行禁用了UAC虚拟化:

<requestedExecutionLevel level="asInvoker" uiAccess="false"/>

如果省略级别,则启用UAC虚拟化。