gpt4 book ai didi

delphi - 从 IShellLibrary 添加、删除文件夹

转载 作者:行者123 更新时间:2023-12-03 15:09:13 29 4
gpt4 key购买 nike

我正在尝试编写两个函数,用于在 IShellLibrary 中添加和删除文件夹。我从这个开始,但该函数在 System._IntfClear 中产生异常:

First chance exception at $000007FEFE 168BC4. Exception class $C0000005 with Message 'c0000005 ACCESS_VIOLATION'.

SHAddFolderPathToLibrary 是导致异常的行。

我想我需要将库名称添加到函数中?

function AddFolderToLibrary(AFolder: string): HRESULT;
{ Add AFolder to Windows 7 library. }
var
plib: IShellLibrary;
begin
Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER,
IID_IShellLibrary, plib);
if SUCCEEDED(Result) then
begin
Result := SHAddFolderPathToLibrary(plib, PWideChar(AFolder));
end;
end;

function RemoveFolderFromLibrary(AFolder: string): HRESULT;
{ Remove AFolder from Windows 7 library. }
var
plib: IShellLibrary;
begin
Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER,
IID_IShellLibrary, plib);
if SUCCEEDED(Result) then
begin
Result := SHRemoveFolderPathFromLibrary(plib, PWideChar(AFolder));
end;
end;

最佳答案

这里的问题是,翻译 SHAddFolderPathToLibrary 的 Embarcadero 工程师不了解 COM 引用计数,以及不同编译器如何处理它。

以下是如何在 C++ 头文件 Shobjidl.h 中实现 SHAddFolderPathToLibrary。它实际上是其他核心 API 调用的内联包装器:

__inline HRESULT SHAddFolderPathToLibrary(_In_ IShellLibrary *plib, 
_In_ PCWSTR pszFolderPath)
{
IShellItem *psiFolder;
HRESULT hr = SHCreateItemFromParsingName(pszFolderPath, NULL,
IID_PPV_ARGS(&psiFolder));
if (SUCCEEDED(hr))
{
hr = plib->AddFolder(psiFolder);
psiFolder->Release();
}
return hr;
}

而且Delphi的翻译非常忠实,确实太忠实了:

function SHAddFolderPathToLibrary(const plib: IShellLibrary;
pszFolderPath: LPCWSTR): HResult;
var
psiFolder: IShellItem;
begin
Result := SHCreateItemFromParsingName(pszFolderPath, nil, IID_IShellItem,
psiFolder);
if Succeeded(Result) then
begin
Result := plib.AddFolder(psiFolder);
psiFolder._Release();
end;
end;

问题出在对 _Release 的调用上。 Delphi 编译器管理引用计数,因此对 _Release 的显式调用是伪造的,不应该存在。由于编译器将安排对 _Release 的调用,因此这一额外的调用只会使引用计数失衡。 _AddRef_Release 之所以带有 _ 前缀,是为了提醒人们不要调用它们,而让编译器来调用它们。

C++ 版本中对 Release 的调用是准确的,因为除非您将接口(interface)包装在 COM 智能指针中,否则 C++ 编译器不会自动为您调用 Release。但内河码头工程师盲目地复制了它,后果自负。显然,Embarcadero 工程师从未执行过这段代码。

您需要提供您自己的此函数的更正实现。还有任何其他错误翻译的函数。在 ShlObj 单元中搜索 _Release,并在更正的版本中将其删除。翻译中还有其他错误,请注意。例如,SHLoadLibraryFromItem(和其他)声明局部变量plib: ^IShellLibrary,它应该是plib: IShellLibrary

我提交了一份QC报告:QC#117351 .

关于delphi - 从 IShellLibrary 添加、删除文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17812551/

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