需要释放 SHGetDesktopFolder 返回的 IShellFolder 接口?如何?

It is required to free the IShellFolder interface returned by SHGetDesktopFolder ? and how?

我很困惑。我想使用 Jedi JCL 中的函数 PathToPidlBind,我发现他们在使用后没有释放 SHGetDesktopFolder 返回的 IShellFolder 接口。 Microsoft 文档说:"The calling application is responsible for eventually freeing the interface by calling its IUnknown::Release method."。我尝试使用 DesktopFolder._Release 但我遇到了访问冲突。我不确定这是 Microsoft 所指的。那么如何正确完成这项工作?

来自 Jedi JCL:

function PathToPidlBind(const FileName:String; out Folder:IShellFolder): PItemIdList;
var
  Attr, Eaten: ULONG;
  PathIdList: PItemIdList;
  DesktopFolder: IShellFolder;
  Path, ItemName: PWideChar;
begin
  Result:=nil;
  Path:=PWideChar(ExtractFilePath(FileName));
  ItemName:=PWideChar(ExtractFileName(FileName));
  if Succeeded(SHGetDesktopFolder(DesktopFolder)) then begin
    Attr:=0;
    if Succeeded(DesktopFolder.ParseDisplayName(0, nil, Path, Eaten, PathIdList, Attr)) then begin
      if Succeeded(DesktopFolder.BindToObject(PathIdList, nil, IID_IShellFolder, Pointer(Folder))) then begin
        if Failed(Folder.ParseDisplayName(0, nil, ItemName, Eaten, Result, Attr)) then begin
          Folder:=nil;
          Result:=DriveToPidlBind(FileName, Folder);
        end;
      end;
      PidlFree(PathIdList);
    end
    else Result:=DriveToPidlBind(FileName, Folder);
  end;
end;

COM 接口是引用计数的,Delphi 编译器生成代码自动为您管理引用计数。每次分配接口变量时,如果变量不为 nil 则调用 Release,如果新值不为 nil 则调用 AddRef。当变量超出范围时,如果不是 nil,则调用 Release

所以按照你的方式手动释放是错误的。你手动释放接口,然后编译器试图自动释放它。您必须让编译器完成工作。

如果您确实希望在超出范围之前释放接口,请将 nil 分配给它:

DesktopFolder := nil;

但是在这个例子中你不需要这样做。

Delphi 设计者不希望您显式调用 AddRefRelease,因此他们命名为 _AddRef_Release,以便不鼓励您直接调用这些方法。