Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 递归删除文件并跳过正在使用的文件?_Delphi_Winapi_Shfileoperation - Fatal编程技术网

Delphi 递归删除文件并跳过正在使用的文件?

Delphi 递归删除文件并跳过正在使用的文件?,delphi,winapi,shfileoperation,Delphi,Winapi,Shfileoperation,我正在使用Windows API递归删除许多文件和文件夹。我在没有UI的情况下使用它并抑制错误。问题是,如果其中一个文件正在使用,它将完全失败。我期待这种可能性,并希望这种情况继续下去,跳过任何这样的情况。失败的一个文件实际上是调用此删除命令的同一个EXE(无论如何,在所有操作完成后将删除该命令) 以下是我现在正在做的: procedure DeleteDirectory(const DirName: string); var FileOp: TSHFileOpStruct; begin

我正在使用Windows API递归删除许多文件和文件夹。我在没有UI的情况下使用它并抑制错误。问题是,如果其中一个文件正在使用,它将完全失败。我期待这种可能性,并希望这种情况继续下去,跳过任何这样的情况。失败的一个文件实际上是调用此删除命令的同一个EXE(无论如何,在所有操作完成后将删除该命令)

以下是我现在正在做的:

procedure DeleteDirectory(const DirName: string);
var
  FileOp: TSHFileOpStruct;
begin
  FillChar(FileOp, SizeOf(FileOp), 0);
  FileOp.wFunc := FO_DELETE;
  FileOp.pFrom := PChar(DirName+#0);//double zero-terminated
  FileOp.fFlags := FOF_SILENT or FOF_NOERRORUI or FOF_NOCONFIRMATION;
  SHFileOperation(FileOp);
end;

如何使其跳过文件正在使用的任何事件?我查看了,但找不到任何可以做到这一点的方法。

以下是您可以在函数中实现的一个想法,以验证是否有任何文件正在使用:

function IsFileInUse(FileName: TFileName): Boolean;
var
  HFileRes: HFILE;
begin
  Result := False;
  if not FileExists(FileName) then
    Exit;

  HFileRes := CreateFile(PChar(FileName),
                         GENERIC_READ or GENERIC_WRITE,
                         0,
                         nil,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         0);
  Result := (HFileRes = INVALID_HANDLE_VALUE);

  if not Result then
    CloseHandle(HFileRes);
end;

也许它可以帮助你。

你为什么不试试这个:

procedure DeleteFiles(const DirName: String);
var
  SR: TSearchRec;
  i: Integer;
begin
  //get all files in directory
  i := FindFirst(DirName +'\*.*', faAnyFile, SR);

  while i = 0 do
  begin
    if (SR.Attr and faDirectory) <> faDirectory then
      DeleteFile(DirName +'\'+ SR.Name);

    i := FindNext(SR);
  end;

  FindClose(SR);
end;
过程删除文件(const DirName:String);
变量
SR:TSearchRec;
i:整数;
开始
//获取目录中的所有文件
i:=FindFirst(DirName+'\*.*',faAnyFile,SR);
当i=0时
开始
如果(高级属性和faDirectory)faDirectory,则
删除文件(DirName+'\'+SR.Name);
i:=FindNext(SR);
结束;
FindClose(SR);
结束;

这是另一种方法。

如果操作
可以处理这个问题。你可能需要使用它,或者使用递归FindFirst,FindNext方法自己遍历目录。你应该发布显示问题的代码…而不是有效的代码!!@Jochenkambach你读了我的问题吗?@Jerry我回答中的第二个代码示例将做您需要的事情:我认为这是IFileOperation或手动树漫游这将如何与调用
SHFileOperation
交互?我以不同的方式使用它。我在目录中的所有文件中使用循环,然后在删除它之前检查当前文件是否正在使用。正如我所说的,这只是一个想法。在这种情况下,您只需调用
D即可eleteFile
并忽略返回值。如果无法删除该文件,则不会删除该文件,并且
DeleteFile
将返回true。像这样进行二次猜测是毫无意义的。是的,调用
DeleteFile
是正确的方法。调用
CreateFile
也将修改上次访问时间,这不是预期的…并且即使
CreateFile
成功,它也可能在
DeleteFile
中失败。No-1,但这并不能解决我正在做的事情。最后,没有必要进行此检查,因为Windows会自动失败。问题是,使用我的方法,我无法想出如何让它继续自动删除所有其他内容并跳过所有正在使用的东西。因为它不是递归的。令人惊讶的是,
*.
仍然存在。只要
*
就足够了。