是否可以使用Inno Setup'Pin to start menu'?

时间:2009-10-27 08:22:15

标签: scripting windows-7 installer inno-setup startmenu

我正在使用优秀的Inno安装程序安装程序,我注意到一些应用程序(通常来自Microsoft)已安装,其启动图标已在开始菜单(Windows 7中)中高度可见('固定?')。我完全依赖于最近使用的算法,使我的图标在开始菜单中变得“大”,或者有没有办法从安装程序中推广我的应用程序?

3 个答案:

答案 0 :(得分:8)

可以固定节目,但不是正式的。基于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 Shell和目标应用程序。 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上,我已经对其进行了测试),但这种方式确实很糟糕,因为没有正式的方法以编程方式将程序固定到任务栏,也没有开始菜单。这是用户应该根据自己的选择做的事情。

答案 1 :(得分:6)

有一个原因是no programmatic way将任务固定到任务栏/开始菜单。根据我的经验,我已经看到了开始菜单highlight newly-created shortcuts,而这正是为了处理这种情况而设计的。当您看到开始菜单上显示新安装的程序时,可能是因为该算法,而不是因为安装程序将其放在那里。

也就是说,如果新的快捷方式 not 突出显示,可能是因为安装程序提取了预先存在的快捷方式并在其上保留了旧的时间戳,而不是使用API​​函数来创建开始菜单中的快捷方式。

答案 2 :(得分:4)