我有以下 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,即使该目录中不存在该文件。
为什么它声称文件存在而实际上不存在?
最佳答案
该文件存在于 VirtualStore 目录中
C:\Users\{username}\AppData\Local\VirtualStore\Program Files (x86)
这是一项称为UAC 虚拟化的功能,首次在Windows Vista 中引入。它允许应用程序写入它们无权访问的受限目录。当启用了 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 文件会导致此问题的原因是它包含 list 。此 list 中的以下行禁用 UAC 虚拟化:
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
当省略 level 时,UAC 虚拟化已启用。
关于windows - 为什么我的 Delphi 应用程序说存在一个不存在的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53508928/