Можно ли закрепить в меню "Пуск" с помощью Inno Setup?

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

3 ответа

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

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

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

Другие вопросы по тегам