delphi - 为什么 AssocQueryString 找不到与图像扩展名关联的可执行文件?

标签 delphi winapi windows-10 file-type file-association

我正在使用 AssocQueryString 为了获取与某些扩展关联的可执行文件。

它适用于 .pdf.txt 等扩展。但我注意到它不会为我尝试过的所有图像扩展名返回任何内容(.bmp.png.jpg.ico)。

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 照片查看器打开该文件。

更新

目前,我的代码是:

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”)后会返回类似的结果。为此我什至不知道是否有关联的程序。

最佳答案

如评论中所述,您的计算机对图像文件扩展名的注册不是使用应用程序来打开文件,而是使用 Rundll32 调用的 DLL。

根据 ASSOCSTR文档:

ASSOCSTR_EXECUTABLE
An executable from a Shell verb command string. For example, this string is found as the (Default) value for a subkey such as HKEY_CLASSES_ROOT\ApplicationName\shell\Open\command. If the command uses Rundll.exe, set the ASSOCF_REMAPRUNDLL flag in the flags parameter of IQueryAssociations::GetString to retrieve the target executable.

Caution
Not all app associations have executables. Do not assume that an executable will always be present.

根据 ASSOCF文档:

ASSOCF_REMAPRUNDLL
Instructs IQueryAssociations methods to ignore Rundll.exe and return information about its target. Typically IQueryAssociations methods return information about the first .exe or .dll in a command string. If a command uses Rundll.exe, setting this flag tells the method to ignore Rundll.exe and return information about its target.

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

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

cchOut [in, out]
Type: DWORD*

A pointer to a value that, when calling the function, is set to the number of characters in the pszOut buffer. When the function returns successfully, the value is set to the number of characters actually placed in the buffer.

您将 BufSize 变量设置为字节数,而不是字符数。您的代码假设 Sizeof(Char) 为 1,但这仅在 Delphi 2007 及更早版本中成立。在 Delphi 2009 及更高版本中,Sizeof(Char) 改为 2。

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

试试这个:

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;

或者:

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;

关于delphi - 为什么 AssocQueryString 找不到与图像扩展名关联的可执行文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39367503/

相关文章:

python - 模块未找到错误 : No module named 'numpy.core._multiarray_umath' (While installing TensorFlow)

delphi - 如何获取CPU一级缓存(主缓存)信息?

delphi - 如何在delphi 10中的任务线程内使用for循环

c++ - 如何使用 COMMTIMEOUTS 等待直到字节可用但读取了一个以上的字节?

c++ - 不再需要在子类化后恢复 GWLP_USERDATA

c - C语言的串口

delphi - 让 Chrome 在第二台显示器上打开?

Delphi 7 企业版或 Delphi 2010 专业版

windows-10 - Hyper-V W10(主机)Ubuntu 18.04(访客): Why does enhanced session mode not work?

c++ - c++ windows 10中的ascii heart不显示