Можно ли «закрепить в меню пуска» с помощью Inno Setup? - PullRequest
8 голосов
/ 27 октября 2009

Я использую отличный установщик Inno Setup и замечаю, что некоторые Приложения (часто от Microsoft) устанавливаются с иконкой запуска, которая уже хорошо видна («закреплен?») В меню «Пуск» (в Windows 7). Я полностью полагаюсь на последний использованный алгоритм, чтобы иконка в меню «Пуск» была «большой», или есть способ продвижения моего приложения из установщика, пожалуйста?

Ответы [ 3 ]

8 голосов
/ 31 июля 2014

Можно закреплять программы, но не официально. Основываясь на коде, опубликованном в this thread (который использует тот же способ, который описан в статье, связанной с @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 и для целевого приложения. path создает объект 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, где я его тестировал), это действительно хакерский способ, так как не существует официального способа программно закрепить программы на панели задач, ни стартовое меню. Это то, что пользователи должны делать по своему выбору.

6 голосов
/ 27 октября 2009

Есть причина, по которой нет программного способа , чтобы прикрепить вещи к панели задач / меню Пуск. По своему опыту я видел, что в меню «Пуск» выделены вновь созданные ярлыки , и оно предназначено именно для этой ситуации. Когда вы видите, что недавно установленная программа отображается в меню «Пуск», это, вероятно, из-за этого алгоритма, а не потому, что установщик поместил его туда.

Тем не менее, если новый ярлык не отображается выделенным, это может быть связано с тем, что установщик извлекает ранее существующий ярлык и сохраняет на нем старую временную метку, а не использует функцию API для создания ярлык в меню «Пуск».

4 голосов
/ 27 октября 2009
...