加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – 从IShellLibrary添加,删除文件夹

发布时间:2020-12-15 09:32:20 所属栏目:大数据 来源:网络整理
导读:我正在尝试编写两个函数来添加和删除I ShellLibrary中的文件夹.我从这开始,但该函数在System._IntfClear中产生异常: First chance exception at $000007FEFE 168BC4. Exception class $C0000005 with Message ‘c0000005 ACCESS_VIOLATION’. SHAddFolderPa
我正在尝试编写两个函数来添加和删除I ShellLibrary中的文件夹.我从这开始,但该函数在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,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,IID_IShellItem,psiFolder);
  if Succeeded(Result) then
  begin
    Result := plib.AddFolder(psiFolder);
    psiFolder._Release();
  end;
end;

问题是调用_Release. Delphi编译器管理引用计数,因此对_Release的显式调用是假的,不应该存在.由于编译器将安排对_Release的调用,因此这个额外的调用只会使引用计数失去平衡. _AddRef和_Release的前缀是_的原因是提醒人们不要调用它们并让编译器这样做.

在C版本中对Release的调用是准确的,因为C编译器不会自动为您调用Release,除非您将接口包装在COM智能指针中.但是Embarcadero的工程师盲目地将它复制过来,你将留下后果.显然,这个代码甚至从未被Embarcadero工程师执行过.

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

我提交了质量控制报告:QC#117351.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读