我使用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')之后,返回类似的结果。为此,我甚至不知道是否有相关的程序。
发布于 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。
并始终检查返回值是否有错误。
试试这个:
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;https://stackoverflow.com/questions/39367503
复制相似问题