Bil*_*ill 5 delphi winapi iunknown delphi-xe4
我正在尝试编写两个添加和删除文件夹的函数IShellLibrary.我从这开始,但该函数在System._IntfClear以下方面产生异常:
$ 000007FEFE 168BC4的首次机会异常.消息'c0000005 ACCESS_VIOLATION'的异常类$ C0000005.
该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;
Run Code Online (Sandbox Code Playgroud)
这里的问题是,翻译的Embarcadero工程师SHAddFolderPathToLibrary不理解COM引用计数,以及不同编译器如何处理它.
以下SHAddFolderPathToLibrary是在C++头文件中实现的方法Shobjidl.h.它实际上是其他核心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;
}
Run Code Online (Sandbox Code Playgroud)
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;
Run Code Online (Sandbox Code Playgroud)
问题是打电话给_Release.Delphi编译器管理引用计数,因此这个显式调用_Release是伪造的,不应该存在.由于编译器将安排调用_Release,这个额外的调用只会使引用计数失去平衡.之所以_AddRef和_Release前缀的原因_是提醒人们不要打电话给他们并让编译器这样做.
Release对C++版本的调用是准确的,因为Release除非将接口包装在COM智能指针中,否则C++编译器不会自动为您调用.但是Embarcadero的工程师盲目地将它复制过来,你将留下后果.显然,这个代码甚至从未被Embarcadero工程师执行过.
您需要提供自己的此功能的更正实现.还有任何其他错误翻译的功能._Release在ShlObj单元中搜索,并在更正的版本中删除它们.翻译中还有其他错误,请注意.例如,SHLoadLibraryFromItem(和其他人)声明plib: ^IShellLibrary应该是的局部变量plib: IShellLibrary.
我提交了质量控制报告:QC#117351.
| 归档时间: |
|
| 查看次数: |
303 次 |
| 最近记录: |