gpt4 book ai didi

delphi - 如何在Delphi中正确使用IFileOperation删除文件夹中的文件

转载 作者:行者123 更新时间:2023-12-03 15:47:31 30 4
gpt4 key购买 nike

我正在尝试创建一个使用 IFileOperation 删除文件中的简单示例给定目录,包含在另一个 q 的答案中,以便与其他方法进行比较。

下面是我的MRE的代码。它成功在 C:\Temp 的子目录中创建 1000 个文件,然后尝试删除它们位于 DeleteFiles 方法中。这个看似“简单”的任务失败了,但我不确定正是它脱轨的地方。代码中的注释显示了我的期望和实际结果。有一次,我没有看到异常,而是弹出了一个窗口要求确认删除名称奇怪的项目,该项目显然是一个数组引用 shell 项目的数字,但我尝试使用 Ctrl-C 捕获它失败了;

我相当确定我错过了一两个步骤,滥用了所涉及的接口(interface)或两者。我的问题是,任何人都可以显示对代码的必要更正,以使 IFileOperation.DeleteItems() 删除有问题的文件,因为我完全不了解这些东西?我对使用 shell 接口(interface)或其他方式删除这些文件的替代方法不感兴趣。

procedure TForm2.DeleteFiles;
var
iFileOp: IFileOperation;
iIDList : ItemIDList;
iItemArray : IShellItemArray;
iArray : Array[0..1] of ItemIDList;
Count : DWord;
begin
iFileOp := CreateComObject(CLSID_FileOperation) as IFileOperation;

iIDList := ILCreateFromPath(sPath)^;

// IFileOperation.DeleteItems seems to require am IShellItemArray, so the following attempts
// to create one
// The definition of SHCreateShellItemArrayFromIDLists
// seems to require a a zero-terminated array of ItemIDLists so the next steps
// attempt to create one

ZeroMemory(@iArray, SizeOf(iArray));
iArray[0] := iIDList;
OleCheck(SHCreateShellItemArrayFromIDLists(1, @iArray, iItemArray));

// Next test the number of items in iItemArray, which I'm expecting to be 1000
// seeing as the CreateFiles routine creats that many

OleCheck(iItemArray.GetCount(Count));
Caption := IntToStr(Count); // Duh, this shows Count to be 1, not the expected 1000

OleCheck(iFileOp.DeleteItems(iItemArray));
OleCheck( iFileOp.PerformOperations );
// Returns Exception 'No object for moniker'

end;

procedure TForm2.Button1Click(Sender: TObject);
begin
DeleteFiles;
end;

procedure CreateFiles;
var
i : Integer;
SL : TStringList;
FileName,
FileContent : String;
begin

SL := TStringList.Create;
try
if not (DirectoryExists(sPath)) then
MkDir(sPath);

SL.BeginUpdate;
for i := 0 to 999 do begin
FileName := Format('File%d.Txt', [i]);
FileContent := Format('content of file %s', [FileName]);
SL.Text := FileContent;
SL.SaveToFile(sPath + '\' + FileName);
end;
SL.EndUpdate;
finally
SL.Free;
end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
CreateFiles;
end;

最佳答案

您正在泄漏 ILCreateFromPath() 返回的内存,当您使用完返回的 PItemIDList 后,您需要调用 ILFree() .

此外,您不应该取消引用 PItemIDListSHCreateShellItemArrayFromIDLists() 需要一个 PItemIDList 指针数组,但您给它一个 ItemIDList 实例数组。

试试这个:

procedure TForm2.DeleteFiles;
var
iFileOp: IFileOperation;
iIDList : PItemIDList;
iItemArray : IShellItemArray;
Count : DWord;
begin
iFileOp := CreateComObject(CLSID_FileOperation) as IFileOperation;

iIDList := ILCreateFromPath(sPath);
try
OleCheck(SHCreateShellItemArrayFromIDLists(1, @iIDList, iItemArray));
finally
ILFree(iIDList);
end;

// Next test the number of items in iItemArray, which I'm expecting to be 1000
// seeing as the CreateFiles routine creates that many

OleCheck(iItemArray.GetCount(Count));
Caption := IntToStr(Count); // Duh, this shows Count to be 1, not the expected 1000

OleCheck(iFileOp.DeleteItems(iItemArray));
OleCheck( iFileOp.PerformOperations );
// Returns Exception 'No object for moniker'
end;

话虽如此,即使工作正常,您也不会为各个文件创建包含 1000 个 IShellItemIShellItemArray。您正在为 C:\Temp 子目录本身创建一个 IShellItemArray,其中包含 1 个 IShellItem

如果您的目标是删除整个文件夹,那么这很好。但在这种情况下,我建议改用 SHCreateItemFromIDList()SHCreateItemFromParsingName(),然后将该 IShellItem 传递给 IFileOperation。删除项目()

但是,如果您的目标是删除单个文件而不删除子目录,那么您必须:

  • 获取子目录的 IShellFolder 接口(interface),然后使用 IShellFolder.EnumObjects() 枚举其文件的相对 PIDL,然后将 PIDL 传递到数组到 SHCreateShellItemArray()

  • 获取子目录的 IShellFolder 接口(interface),然后使用 IShellFolder.GetUIObjectOf() 查询其 IDataObject 接口(interface),以及然后使用 SHCreateShellItemArrayFromDataObject(),或者直接将 IDataObject 提供给 IFileOperation.DeleteItems()

  • 获取子目录的 IShellItem 接口(interface),然后使用 IShellItem.BindToHandler() 查询其 IEnumShellItems 接口(interface),然后通过直接到 IFileOperation.DeleteItems()

关于delphi - 如何在Delphi中正确使用IFileOperation删除文件夹中的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58597454/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com