【问题标题】:How to get FileName and Directory of Windows Control Panels?如何获取 Windows 控制面板的文件名和目录?
【发布时间】:2018-01-20 21:27:36
【问题描述】:

在 Delphi 中,创建一个 VCL 表单应用程序。如果您在 64 位 Windows 上,请使用 64 位 Windows 平台。

使用以下代码:

unit Unit1;

interface

uses
  CodeSiteLogging,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure GetControlPanelItems;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  Winapi.ShlObj, Winapi.ShellAPI, System.Win.ComObj;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  GetControlPanelItems;
end;

procedure TForm1.GetControlPanelItems;
var
  psfDeskTop: IShellFolder;
  psfControl: IShellFolder;
  pidControl: PITEMIDLIST;
  pidChild: PITEMIDLIST;
  pidAbsolute: PItemIdList;
  pEnumList: IEnumIDList;
  celtFetched: ULONG;
  FileInfo: SHFILEINFOW;
  ShExeInfo: SHELLEXECUTEINFO;
begin
  OleCheck(SHGetDesktopFolder(psfDeskTop));
  OleCheck(SHGetSpecialFolderLocation(0, CSIDL_CONTROLS, pidControl));
  OleCheck(psfDeskTop.BindToObject(pidControl, nil, IID_IShellFolder, psfControl));
  OleCheck(psfControl.EnumObjects(0, SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN or SHCONTF_FOLDERS, pEnumList));

  while pEnumList.Next(1, pidChild, celtFetched) = 0 do
  begin
    pidAbsolute := ILCombine(pidControl, pidChild);
    SHGetFileInfo(LPCTSTR(pidAbsolute), 0, FileInfo, SizeOf(FileInfo), SHGFI_PIDL or SHGFI_DISPLAYNAME or SHGFI_TYPENAME);

    CodeSite.Send('TForm1.GetControlPanelItems: szDisplayName', FileInfo.szDisplayName);

    // Exe-Info:
    ZeroMemory(@ShExeInfo, SizeOf(ShExeInfo));
    ShExeInfo.cbSize := SizeOf(ShExeInfo);
    ShExeInfo.lpVerb := 'Open';
    // control panel item's PIDL:
    ShExeInfo.lpIDList := pidAbsolute;
    ShExeInfo.nShow := SW_SHOWNORMAL;
    ShExeInfo.fMask := SEE_MASK_IDLIST;
    //ShExeInfo.lpFile := ???
    //ShExeInfo.lpDirectory := ???

    CodeSite.Send('TForm1.GetControlPanelItems: ShExeInfo.lpFile', ShExeInfo.lpFile);
    CodeSite.Send('TForm1.GetControlPanelItems: ShExeInfo.lpDirectory', ShExeInfo.lpDirectory);
  end;
end;

end.

这让我得到控制面板的显示名称

但是我怎样才能得到文件路径呢? (ShExeInfo.lpDirectory, SheExeInfo.lpFile)

【问题讨论】:

  • AFAIK,你不能。并非所有控制面板项目都是可执行文件。许多都是使用rundll32.exe 运行的,不能直接独立执行。
  • 此外,一个可执行文件还可以包含多个控制面板小程序。
  • 我们的根本问题是什么。我猜你对知道他们的名字不感兴趣。你想调用它们吗?
  • 每个小程序不一定有文件名。所以你所要求的无法实现。
  • 有 5 个反对票。连我都没有那么大的权力。我正在回复您坚持使用文件名的评论。我猜你现在意识到你在这方面是错误的。

标签: delphi delphi-10.1-berlin control-panel


【解决方案1】:

正如其他人在这里提到的,尝试获取某个小程序二进制文件的文件名可能毫无价值,因为在一个二进制文件中可以实现多个小程序。对于您的整体任务,在您的评论中删除,创建 shell 快捷链接,只需使用您在循环中知道的绝对 ITEMIDLIST,并通过 SetIDList 方法将其设置为创建的 IShellLink 对象。

【讨论】:

  • 反对者,请发表评论好吗?这是正确的做法。甚至 MSDN 也解释了 SetIDList 之类的“当应用程序需要将 Shell 链接设置到不是文件的对象(例如控制面板应用程序、打印机)时,此方法很有用,或另一台计算机。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-04
  • 2011-09-19
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2011-01-09
相关资源
最近更新 更多