32 ビット サーバーの共有フォルダーにあるファイルを 64 ビット Windows 7 マシンから開いた場合、そのファイルを読み取り、ロックしてから再度開くことがわかりました。開いているすべてのハンドルを閉じると、ファイルは実際には開いたままになります。
正確な手順は次のとおりです。
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;
ファイルを 2 回目に開くときに FILE_FLAG_NO_BUFFERING フラグを使用する場合、またはファイルをロックする前に読み取らない場合、問題は発生しません。
FILE_FLAG_NO_BUFFERING を使用せずに、これに気づいた人や解決方法を知っている人はいますか? これは、64 ビット Windows クライアントが 32 ビット Windows マシンでこの方法でファイルを開く場合にのみ発生することに注意してください。32 ビットからビットまたは 64t から 64 では発生しません。