我发现,如果您从 64 位 Windows 7 机器打开位于共享文件夹中的 32 位服务器上的文件,请读取它,锁定它,然后再次打开它。当您关闭所有打开的句柄时,文件实际上保持打开状态。
具体步骤如下:
将长度在 7000 到 10000 字节之间的文件放在 32 位 Windows 机器上的共享文件夹中,我们使用的是 Windows Server 2003。
为 Win32 编译以下代码,使其在 WOW64 下运行。请注意,为了简单起见,我错过了 try..finally、声明等。
(参见下面的代码片段;当 StackOverflow 错误在列表中时,代码格式不正确)在 64 位 Windows 机器上运行应用程序。该文件必须在 32 位机器上,我们使用 windows server 2003,如果文件在 64 位服务器上,则不会出现该错误。
终止您的应用程序。
如果您现在打开服务器上的计算机管理器(控制面板-> 计算机管理)并查看文件所在的共享文件夹中打开的文件,您会看到您的文件仍处于打开状态。
这是代码:
procedure CauseFileLockBug(FileName: PChar);
var
FileHandle1: LongInt;
FileHandle2: LongInt;
Buffer: Pointer;
BytesRead: Cardinal;
begin
FileHandle1 := CreateFile(
FileName,
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
0);
if FileHandle1 > 0 then
begin
try
GetMem(Buffer, 1);
try
if ReadFile(FileHandle1, Buffer^, 1, BytesRead, nil) then
begin
if LockFile(FileHandle1, 6217, 0, 1, 0) then
begin
try
FileHandle2 := CreateFile(
FileName,
GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_FLAG_RANDOM_ACCESS,
0);
if FileHandle2 > 0 then
begin
CloseHandle(FileHandle2);
end;
finally
UnLockFile(FileHandle1, 6217, 0, 1, 0);
end;
end;
end;
finally
FreeMem(Buffer);
end;
finally
CloseHandle(FileHandle1);
end;
end;
end;
如果您在第二次打开文件时使用 FILE_FLAG_NO_BUFFERING 标志,或者在锁定文件之前未读取文件,则不会出现此问题。
有没有人在不使用 FILE_FLAG_NO_BUFFERING 的情况下之前注意到这一点或知道如何解决它?请注意,仅当 64 位 Windows 客户端在 32 位 Windows 机器上以这种方式打开文件时才会发生这种情况,32 位或 64 位到 64 位不会发生这种情况。