Delphi中无需交互提取OLE容器内链接文件路径的方法
提取OLE容器中链接文件路径的无交互方法
可以通过OLE标准接口直接获取链接路径,无需依赖DoVerb交互或解析原始二进制明文,以下是两种可行方案:
方案一:通过IOleLink接口直接读取
利用TOleContainer加载容器后,不调用DoVerb,直接查询IOleLink接口获取链接源的显示名称(即文件路径),全程无交互:
uses ComObj, OleCtrls, ActiveX; function GetOLELinkedFilePath(const ContainerPath: string): string; var OleContainer: TOleContainer; OleLink: IOleLink; DisplayName: PWideChar; begin Result := ''; OleContainer := TOleContainer.Create(nil); try OleContainer.Parent := nil; // 无需可视化父控件 OleContainer.LoadFromFile(ContainerPath); // 查询IOleLink接口 if OleContainer.OleObject.QueryInterface(IOleLink, OleLink) = S_OK then begin // 获取链接源的显示名称(文件路径) if OleLink.GetSourceDisplayName(nil, DisplayName) = S_OK then begin Result := DisplayName; CoTaskMemFree(DisplayName); // 释放系统分配的内存 end; end; finally OleContainer.Free; end; end;
方案二:底层OLE存储解析(无TOleContainer依赖)
如果不想依赖TOleContainer,可以直接通过OLE存储API打开容器文件,遍历对象属性获取路径:
uses ActiveX, ComObj; function GetLinkedPathFromOLEStorage(const ContainerPath: string): string; var Storage: IStorage; Stream: IStream; OleLink: IOleLink; DisplayName: PWideChar; begin Result := ''; // 打开OLE存储文件 if StgOpenStorage(PWideChar(ContainerPath), nil, STGM_READ or STGM_SHARE_DENY_WRITE, nil, 0, Storage) = S_OK then begin try // 打开OLE对象的属性流(通常名称为'CONTENTS',部分容器需调整) if Storage.OpenStream('CONTENTS', nil, STGM_READ or STGM_SHARE_DENY_WRITE, 0, Stream) = S_OK then begin try // 从流中加载OLE对象并查询IOleLink接口 if OleLoadFromStream(Stream, IOleLink, OleLink) = S_OK then begin if OleLink.GetSourceDisplayName(nil, DisplayName) = S_OK then begin Result := DisplayName; CoTaskMemFree(DisplayName); end; end; finally Stream := nil; end; end; finally Storage := nil; end; end; end;
注意:部分OLE容器的流名称可能不是CONTENTS,需根据实际容器类型调整;服务启动时需调用CoInitialize(nil)初始化COM环境,结束时调用CoUninitialize()释放资源。
内容的提问来源于stack exchange,提问作者D D
相关产品推荐
相关产品推荐

