我正在使用 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 asHKEY_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
InstructsIQueryAssociations
methods to ignoreRundll.exe
and return information about its target. TypicallyIQueryAssociations
methods return information about the first.exe
or.dll
in a command string. If a command usesRundll.exe
, setting this flag tells the method to ignoreRundll.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/