我有一个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”的指针是关键,以及我仍然可以用另一个打开的句柄写入文件的知识,但重命名会失败。感谢大家的贡献。
答案 0 :(得分:4)
在我看来,问题不是目标文件,而是源文件......确保源文件上的句柄已关闭,这就是问题所在。
答案 1 :(得分:4)
调试此类问题的有用方法(无论如何)是使用Process Explorer的“查找/查找句柄或DLL”功能搜索文件名。如果特定文件名是打开的&独家它将揭示哪个程序持有它。如果是你的,你可以检查手柄是否关闭。如果不是你的,你可能要么只是编写一个小的等待(Windows有时会花时间去处理事情),或者强行解锁文件(我在这里有一个小程序用EXPLORER.EXE来做,因为它会当我使用它时,对文件进行了大量的锁定。)
HTH。
答案 2 :(得分:1)
我敢打赌,你对GetLastError的调用正在返回与此例程无关的早期API调用的错误代码。据我所知(我没有手头的资料)FileExists没有设置错误代码。但是如果第一次调用FileExists失败,那么你继续调用GetLastError。
答案 3 :(得分:0)
如果你在一秒左右后重试重命名会有帮助吗?也许Windows太慢而无法赶上。
答案 4 :(得分:0)
值得一提的是.DAT文件是由一些防病毒工具扫描的。因此,您可能会发现关闭文件,然后AV打开它进行扫描,当它仍然打开时,您正在尝试对其进行操作。当然你不能因为AV打开它。