首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么AssocQueryString找不到与图像扩展相关的可执行文件?

为什么AssocQueryString找不到与图像扩展相关的可执行文件?
EN

Stack Overflow用户
提问于 2016-09-07 10:32:28
回答 1查看 3.4K关注 0票数 3

我使用AssocQueryString来获取与某些扩展相关联的可执行文件。

它对像.pdf.txt这样的扩展很好。但是我注意到它并没有为我尝试过的所有图像扩展(.bmp.png.jpg.ico)返回任何内容。

代码语言:javascript
复制
uses
  ShLwApi, Windows, Dialogs;

const
    // ASSOCF enumerated values mapped to integer constants
    ASSOCF_INIT_NOREMAPCLSID = $00000001;
    ASSOCF_INIT_BYEXENAME = $00000002;
    ASSOCF_OPEN_BYEXENAME = $00000002;
    ASSOCF_INIT_DEFAULTTOSTAR = $00000004;
    ASSOCF_INIT_DEFAULTTOFOLDER = $00000008;
    ASSOCF_NOUSERSETTINGS = $00000010;
    ASSOCF_NOTRUNCATE = $00000020;
    ASSOCF_VERIFY = $00000040;
    ASSOCF_REMAPRUNDLL = $00000080;
    ASSOCF_NOFIXUPS = $00000100;
    ASSOCF_IGNOREBASECLASS = $00000200;
    
var
   Buffer: array [0..1024] of char;
   BufSize: DWord;
begin
   BufSize := Sizeof(Buffer);
   Buffer[0] := #0;
   AssocQueryString(
         ASSOCF_NOTRUNCATE,
         ASSOCSTR_EXECUTABLE,
         '.bmp',
         'open',
         Buffer,
         @BufSize
   );
   ShowMessage(Buffer);
end;

的进一步信息:

它也适用于图像扩展,但只有在请求与“编辑”相关的可执行文件而不是“打开”的情况下才能工作。

双击.bmp文件将导致使用默认的Windows 10照片查看器打开该文件。

更新

目前,我的代码是:

代码语言:javascript
复制
var
  Buffer: array [0..1024] of Char;
  BufSize: DWord;
  Res: HResult;
begin
  BufSize := Length(Buffer);
  Res := AssocQueryString(
    ASSOCF_REMAPRUNDLL or ASSOCF_NOTRUNCATE,
    (*ASSOCSTR_DELEGATEEXECUTE missing on Delphi 2007*) 18,
    '.bmp',
    nil,
    Buffer,
    @BufSize
  );
  If Res = S_OK then
    ShowMessage(Buffer)
  else
    ShowMessage('Error ' + IntToStr(Res) + sLineBreak + SysErrorMessage(Res));

"{4ED3A719-CEA8-4BD9-910D-E252F997AFC2}“。如何在Windows 7上看到相同的结果?( dll或可执行文件名)

此外,我注意到在将.bmp转换为不存在的(如'.abcde')之后,返回类似的结果。为此,我甚至不知道是否有相关的程序。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-07 15:48:58

正如注释中所述,您的机器注册图像文件扩展名并不是使用应用程序来打开文件,而是使用由Rundll32调用的DLL。

根据ASSOCSTR文档:

ASSOCSTR_EXECUTABLE 来自Shell谓词命令字符串的可执行文件。例如,此字符串作为子项(如HKEY_CLASSES_ROOT\ApplicationName\shell\Open\command )的(默认值)值。如果命令使用Rundll.exe,则在IQueryAssociation::GetString的标志参数中设置ASSOCF_REMAPRUNDLL标志以检索目标可执行文件。 注意事项 并不是所有的应用程序关联都有可执行文件。不要假设可执行文件总是存在于中。

根据ASSOCF文档:

ASSOCF_REMAPRUNDLL 指示IQueryAssociations方法忽略并返回有关目标的信息。通常,IQueryAssociations方法返回有关命令字符串中的第一个.exe.dll的信息。如果命令使用Rundll.exe,设置此标志将告诉方法忽略Rundll.exe并返回有关其目标的信息。

此外,在调用AssocQueryString()时,尝试将pszExtra参数设置为NULL,而不是特定的谓词。

另外,请注意AssocQueryString()的最后一个参数的文档

cchOut入,出 类型: DWORD* 指向一个值的指针,即调用函数时的,设置为pszOut缓冲区中的字符数。当函数成功返回时,该值将被设置为实际放置在缓冲区中的字符数。

您将BufSize变量设置为字节计数,而不是字符计数。您的代码假设Sizeof(Char)为1,但这仅在Delphi2007和更早版本中是正确的。在Delphi2009及以后版本中,Sizeof(Char)是2。

并始终检查返回值是否有错误。

试试这个:

代码语言:javascript
复制
var
  Buffer: array [0..1024] of Char;
  BufSize: DWord;
  Res: HResult;
begin
  BufSize := Length(Buffer);
  Res := AssocQueryString(
    ASSOCF_REMAPRUNDLL or ASSOCF_NOTRUNCATE,
    ASSOCSTR_EXECUTABLE,
    '.bmp',
    nil,
    Buffer,
    @BufSize
  );
  If Res = S_OK then
    ShowMessage(Buffer)
  else
    ShowMessage('Error ' + IntToStr(Res));
end;

另一种选择是:

代码语言:javascript
复制
var
  Buffer: string;
  BufSize: DWord;
  Res: HResult;
begin
  BufSize := 0;
  Res := AssocQueryString(
    ASSOCF_REMAPRUNDLL or ASSOCF_NOTRUNCATE,
    ASSOCSTR_EXECUTABLE,
    '.bmp',
    nil,
    nil,
    @BufSize
  );
  if Res = S_FALSE then
  begin
    SetLength(Buffer, BufSize-1);
    Res := AssocQueryString(
      ASSOCF_REMAPRUNDLL or ASSOCF_NOTRUNCATE,
      ASSOCSTR_EXECUTABLE,
      '.bmp',
      nil,
      PChar(Buffer),
      @BufSize
    );
  end;
  If Res = S_OK then
    ShowMessage(Buffer)
  else
    ShowMessage('Error ' + IntToStr(Res));
end;
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39367503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档