我有一个 Delphi 2006 应用程序,它写入一个文件,然后定期将其重命名为一个有序的名称,并创建一个新的,即
open file.dat
write a record to file.dat
close file.dat
...
open file.dat
write a record to file.dat
close file.dat
rename file.dat to file20110818123456.dat
create file.dat
open file.dat
write a record to file.dat
close file.dat
...
问题是有时重命名会失败并显示Error 32 - The process cannot access the file because it is being used by another process
. 我正在检查重命名的目的地是否不存在。就好像写入记录后文件的关闭不会立即发生。我在重命名过程中添加了一个循环来休眠一会儿,然后再试 10 次,但这没有帮助。
function RenameFileAtAllCosts (const OldFileID : TFilename ;
const NewFileID : TFilename ;
out ErrorCode : Integer) : boolean ;
const
MaxRenameAttempts = 10 ;
var
RenameAttempts : integer ;
begin
Result := FileExists (OldFileID) ;
if (Result = true) then
begin
if FileExists (NewFileID) then
begin
Result := DeleteFile (PChar (NewFileID)) ;
end ;
if (Result = true) then
begin
Result := (not FileExists (NewFileID)) ;
end ;
if (Result = true) then
begin
RenameAttempts := 0 ;
repeat
SysUtils.Sleep (50) ;
Result := RenameFile (OldFileID, NewFileID) ;
inc (RenameAttempts)
until (Result or (RenameAttempts >= MaxRenameAttempts)) ;
end ;
end ;
if (not Result) then
begin
ErrorCode := GetLastError ;
end ;
end ;
* 附加信息 *
这是相关磁盘 I/O 的 ProcMon 日志,每个块之前都有相关的 Pascal 源或伪代码
open file.dat
write a record to file.dat
close file.dat
5:45:27.1718325 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
5:45:27.1719739 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,208, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:27.1720475 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,208, Length: 28, Priority: Normal
5:45:27.1721403 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
if FileExists (NewFileID) then // before call to RenameFileAtAllCosts
begin
5:45:27.8630005 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
if DeleteFile (NewFileID) then // before call to RenameFileAtAllCosts
begin
5:45:27.8634050 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Delete, Disposition: Open, Options: Non-Directory File, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
Result := FileExists (OldFileID) ;
5:45:27.8640878 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, OpenResult: Opened
5:45:27.8641684 PM APP.exe 1276 QueryBasicInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS CreationTime: 2/08/2011 7:45:59 PM, LastAccessTime: 19/08/2011 4:25:33 PM, LastWriteTime: 19/08/2011 5:45:27 PM, ChangeTime: 19/08/2011 5:45:27 PM, FileAttributes: A
5:45:27.8641902 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
if FileExists (NewFileID) then
begin
5:45:27.8648698 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
if (Result = true) then
begin
Result := (not FileExists (NewFileID)) ;
end ;
5:45:27.8656780 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP20110819054527.DAT NAME NOT FOUND Desired Access: Read Attributes, Disposition: Open, Options: Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
RenameAttempts := 0 ;
repeat
SysUtils.Sleep (50) ;
Result := RenameFile (OldFileID, NewFileID) ;
inc (RenameAttempts)
until (Result or (RenameAttempts >= MaxRenameAttempts)) ;
5:45:27.9211195 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:27.9834427 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.0459285 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.1084086 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.1710646 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.2335139 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.2959037 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.3584062 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.4209304 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
5:45:28.4834629 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SHARING VIOLATION Desired Access: Read Attributes, Delete, Synchronize, Disposition: Open, Options: Synchronous IO Non-Alert, Open Reparse Point, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a
open file.dat
write several records to file.dat
close file.dat
5:45:28.4899722 PM APP.exe 1276 CreateFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Desired Access: Generic Read/Write, Disposition: Open, Options: Synchronous IO Non-Alert, Non-Directory File, Attributes: N, ShareMode: Read, Write, AllocationSize: n/a, OpenResult: Opened
5:45:28.4901002 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,236, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4901636 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,236, Length: 28, Priority: Normal
5:45:28.4902365 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,264, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4903031 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,264, Length: 28, Priority: Normal
5:45:28.4903517 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,292, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4905200 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,292, Length: 28, Priority: Normal
5:45:28.4905917 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,320, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4906633 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,320, Length: 28, Priority: Normal
5:45:28.4907120 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,348, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4907747 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,348, Length: 28, Priority: Normal
5:45:28.4908214 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,376, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4908841 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,376, Length: 28, Priority: Normal
5:45:28.4909308 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,404, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4909929 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,404, Length: 28, Priority: Normal
5:45:28.4910396 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,432, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4911023 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,432, Length: 28, Priority: Normal
5:45:28.4911491 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,460, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4912118 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,460, Length: 28, Priority: Normal
5:45:28.4912578 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,488, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4913206 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,488, Length: 28, Priority: Normal
5:45:28.4913673 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,516, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4914300 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,516, Length: 28, Priority: Normal
5:45:28.4914761 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,544, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4915388 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,544, Length: 28, Priority: Normal
5:45:28.4915855 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,572, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4916482 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,572, Length: 28, Priority: Normal
5:45:28.4916936 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,600, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4917570 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,600, Length: 28, Priority: Normal
5:45:28.4918043 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,628, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4919003 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,628, Length: 28, Priority: Normal
5:45:28.4919483 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,656, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4920110 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,656, Length: 28, Priority: Normal
5:45:28.4920577 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,684, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4921205 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,684, Length: 28, Priority: Normal
5:45:28.4921672 PM APP.exe 1276 QueryStandardInformationFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS AllocationSize: 57,344, EndOfFile: 54,712, NumberOfLinks: 1, DeletePending: False, Directory: False
5:45:28.4922299 PM APP.exe 1276 WriteFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS Offset: 54,712, Length: 28, Priority: Normal
5:45:28.4922843 PM APP.exe 1276 CloseFile C:\Users\Public\Documents\APP\Datafile\APP.DAT SUCCESS
* 更新 *
我想我已经搞定了。我下载了handle.exe并运行了它。进程资源管理器始终显示没有与 APP.DAT 匹配的句柄,但 handle.exe 实用程序显示了 PID 4(系统)拥有的句柄列表,其中 APP.DAT 作为文件名。我在我的 OP 中没有提到的是,同一个应用程序在另一台网络机器上以辅助“监视器”模式运行,它不写入 APP*.DAT 文件,而只读取它们。“啊哈!” 那一刻我意识到问题只发生在监视器应用程序也在运行时,并且句柄泄漏显示为属于“系统”进程 - 大概是从网络机器打开文件时创建的句柄。
有时,监视器应用程序被拒绝访问文件(总是出现错误 998 - 对内存位置的无效访问 - 由于某种原因)并且错误路径没有关闭句柄。从那时起,应用程序的主实例仍然能够读取和写入文件 APP.DAT,但重命名失败。确保文件已关闭错误似乎已修复它。
指向“handle.exe”的指针是关键,同时知道我仍然可以使用另一个打开的句柄写入文件,但重命名会失败。感谢大家的贡献。