我有以下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。
为什么它声称一个文件在不存在的地方?
答案 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虚拟化。