3

我有一个 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”的指针是关键,同时知道我仍然可以使用另一个打开的句柄写入文件,但重命名会失败。感谢大家的贡献。

4

5 回答 5

4

在我看来,问题不在于目标文件,而在于源文件......确保源文件上的句柄已关闭,这就是您的问题所在。

于 2011-08-19T05:40:16.570 回答
4

调试此类问题的一种有用方法(无论如何对我来说)是使用 Process Explorer 的“查找/查找句柄或 DLL”功能搜索文件名。如果特定文件名是开放且独占的,它将显示哪个程序正在保存它。如果是您的,您可以检查手柄是否已关闭。如果不是您的,您可能只需要编写一个小等待(Windows 有时会花时间处理事情),或者强制解锁文件(我这里有一个小程序可以使用 EXPLORER.EXE 执行此操作,因为它会当我使用它时,经常锁定文件)。

HTH。

于 2011-08-19T07:36:23.910 回答
1

我敢打赌,您对 GetLastError 的调用将返回与此例程无关的早期 API 调用的错误代码。据我所知(我手头没有来源) FileExists 没有设置错误代码。但是,如果对 FileExists 的第一次调用失败,那么您继续调用 GetLastError。

于 2011-08-19T08:37:34.160 回答
0

值得一提的是,.DAT 文件会被一些防病毒工具扫描。因此,您可能会发现您关闭了文件,然后 AV 打开它进行扫描,当它仍然打开时,您正在尝试对其进行操作。当然你不能因为 AV 已经打开它。

于 2011-08-19T08:22:22.777 回答
0

如果您在一秒钟左右后重试重命名会有帮助吗?也许 Windows 太慢了,无法赶上。

于 2011-08-19T07:31:08.717 回答