需要释放 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 设计者不希望您显式调用 AddRef
和 Release
,因此他们命名为 _AddRef
和 _Release
,以便不鼓励您直接调用这些方法。
我很困惑。我想使用 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 设计者不希望您显式调用 AddRef
和 Release
,因此他们命名为 _AddRef
和 _Release
,以便不鼓励您直接调用这些方法。