使用Inno Setup是否可以将应用程序“固定到开始菜单”?

9

我正在使用优秀的Inno Setup安装程序,我注意到一些应用程序(通常来自Microsoft)已经在开始菜单中高度可见(“固定”)。我的图标是否完全依赖于最近使用的算法才能在开始菜单中显示为“大”图标,或者有没有一种方法可以从安装程序中提升我的应用程序呢?

3个回答

9

虽然官方没有提供固定程序的方法,但是还是有办法的。根据这篇帖子中发布的代码(使用了与@Mark Redman链接文章中描述的相同方法),我编写了以下代码:

[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif

const
  // these constants are not defined in Windows
  SHELL32_STRING_ID_PIN_TO_TASKBAR = 5386;
  SHELL32_STRING_ID_PIN_TO_STARTMENU = 5381;
  SHELL32_STRING_ID_UNPIN_FROM_TASKBAR = 5387;
  SHELL32_STRING_ID_UNPIN_FROM_STARTMENU = 5382;

type
  HINSTANCE = THandle;
  HMODULE = HINSTANCE;

  TPinDest = (
    pdTaskbar,
    pdStartMenu
  );

function LoadLibrary(lpFileName: string): HMODULE;
  external 'LoadLibrary{#AW}@kernel32.dll stdcall';
function FreeLibrary(hModule: HMODULE): BOOL;
  external 'FreeLibrary@kernel32.dll stdcall';
function LoadString(hInstance: HINSTANCE; uID: UINT;
  lpBuffer: string; nBufferMax: Integer): Integer;
  external 'LoadString{#AW}@user32.dll stdcall';

function TryGetVerbName(ID: UINT; out VerbName: string): Boolean;
var
  Buffer: string;
  BufLen: Integer;
  Handle: HMODULE;
begin
  Result := False;

  Handle := LoadLibrary(ExpandConstant('{sys}\Shell32.dll'));
  if Handle <> 0 then
  try
    SetLength(Buffer, 255);
    BufLen := LoadString(Handle, ID, Buffer, Length(Buffer));

    if BufLen <> 0 then
    begin
      Result := True;
      VerbName := Copy(Buffer, 1, BufLen);
    end;
  finally
    FreeLibrary(Handle);
  end;
end;

function ExecVerb(const FileName, VerbName: string): Boolean;
var
  I: Integer;
  Shell: Variant;
  Folder: Variant;
  FolderItem: Variant;
begin
  Result := False;

  Shell := CreateOleObject('Shell.Application');
  Folder := Shell.NameSpace(ExtractFilePath(FileName));
  FolderItem := Folder.ParseName(ExtractFileName(FileName));

  for I := 1 to FolderItem.Verbs.Count do
  begin
    if FolderItem.Verbs.Item(I).Name = VerbName then
    begin
      FolderItem.Verbs.Item(I).DoIt;
      Result := True;
      Exit;
    end;
  end;  
end;

function PinAppTo(const FileName: string; PinDest: TPinDest): Boolean;
var
  ResStrID: UINT;
  VerbName: string;
begin
  case PinDest of
    pdTaskbar: ResStrID := SHELL32_STRING_ID_PIN_TO_TASKBAR;
    pdStartMenu: ResStrID := SHELL32_STRING_ID_PIN_TO_STARTMENU;
  end;
  Result := TryGetVerbName(ResStrID, VerbName) and ExecVerb(FileName, VerbName);
end;

function UnpinAppFrom(const FileName: string; PinDest: TPinDest): Boolean;
var
  ResStrID: UINT;
  VerbName: string;
begin
  case PinDest of
    pdTaskbar: ResStrID := SHELL32_STRING_ID_UNPIN_FROM_TASKBAR;
    pdStartMenu: ResStrID := SHELL32_STRING_ID_UNPIN_FROM_STARTMENU;
  end;
  Result := TryGetVerbName(ResStrID, VerbName) and ExecVerb(FileName, VerbName);
end;

上述代码首先从 Shell32.dll 库的字符串表中读取固定或取消固定应用程序的菜单项的标题。然后连接到 Windows Shell,并为目标应用程序路径创建 Folder 对象,接着获取 FolderItem 对象,并在此对象上迭代所有可用的动词,并检查它们的名称是否与从 Shell32.dll 库字符串表中读取的名称匹配。如果匹配,则通过调用 DoIt 方法来调用动词项操作并退出迭代。

以下是使用以上代码进行钉选的可能方法:

if PinAppTo(ExpandConstant('{sys}\calc.exe'), pdTaskbar) then
  MsgBox('Calc has been pinned to the taskbar.', mbInformation, MB_OK);
if PinAppTo(ExpandConstant('{sys}\calc.exe'), pdStartMenu) then
  MsgBox('Calc has been pinned to the start menu.', mbInformation, MB_OK);

对于取消固定:

if UnpinAppFrom(ExpandConstant('{sys}\calc.exe'), pdTaskbar) then
  MsgBox('Calc is not pinned to the taskbar anymore.', mbInformation, MB_OK);
if UnpinAppFrom(ExpandConstant('{sys}\calc.exe'), pdStartMenu) then
  MsgBox('Calc is not pinned to the start menu anymore.', mbInformation, MB_OK);

请注意,尽管此代码可在Windows 7上运行(并且我已经在测试过的Windows 8.1上固定了任务栏),但它是一种非常hacky的方式,因为没有官方方法来通过编程方式将程序固定到任务栏或开始菜单。这是用户自己选择应该做的事情。

1
哇,你试了多少个小时才弄明白的?非常感谢! - tmighty
1
@tmighty,我从未被要求部署一个可以将自己固定在某个位置的应用程序。这本来就是用户首先应该自己做的事情。但如果确实有这样的要求,我认为使用任务是公平的(因为任务通常用于确认创建图标)。对于执行,我会使用安装后步骤 - TLama
1
@tmighty,你可以使用这个辅助函数。它会返回True,如果你正在运行Windows Vista或更高版本,则返回False。 - TLama
@tmighty,恐怕我无法提供帮助。对于我来说很难确定即使您找到了该菜单项,也会有与经典桌面版本上相同的Windows Shell服务。 - TLama
@TLama,我该如何使用参数将其固定到任务栏?编辑:我现在尝试了没有参数的方式,在安装程序的最后一页中它无法在Windows 10上固定到任务栏。动词列表中没有关于固定到任务栏的任何内容。但是它有固定到开始菜单,而我不需要这个。 - Jaex
显示剩余9条评论

6

有一个原因,就是没有编程方式将事物固定在任务栏/开始菜单上。根据我的经验,我看到过开始菜单突出显示新创建的快捷方式,这正是为处理这种情况而设计的。当你在开始菜单上看到一个新安装的程序出现时,很可能是因为那个算法,而不是安装程序放置它。

话虽如此,如果一个新的快捷方式没有被突出显示,那可能是因为安装程序提取了一个现有的快捷方式并保留了旧的时间戳,而不是使用API函数在开始菜单中创建一个快捷方式。


4

6
正如那篇文章所指出的那样,没有直接固定窗口的API是有原因的。请不要在桌面、任务栏、开始菜单等地方进行垃圾信息推送。 - Jim Deville

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接