2009-10-27 15 views
7

J'utilise l'excellent programme d'installation Inno Setup et je remarque que certaines applications (souvent de Microsoft) sont installées avec leur icône de lancement déjà très visible ('épinglé?') Dans le menu Démarrer (sous Windows 7). Suis-je totalement dépendant de l'algorithme le plus récemment utilisé pour que mon icône soit «grande» dans le menu Démarrer, ou existe-t-il un moyen de promouvoir mon application auprès de l'installateur, s'il vous plaît?Est-il possible de 'Pin to start menu' en utilisant Inno Setup?

Répondre

6

Il y a une raison pour laquelle il y a no programmatic way d'épingler les choses à la barre des tâches/menu Démarrer. Dans mon expérience, j'ai vu le menu de démarrage highlight newly-created shortcuts, et c'est conçu pour gérer exactement cette situation. Lorsque vous voyez un programme nouvellement installé apparaître dans le menu Démarrer, c'est probablement à cause de cet algorithme et non parce que le programme d'installation l'a placé là.

Cela dit, si un nouveau raccourci ne pas apparaît en surbrillance, il peut être parce que le programme d'installation extrait un raccourci pré-existante et conserve un ancien horodatage, plutôt que d'utiliser la fonction API pour créer un raccourci dans la le menu Démarrer.

6

Il est possible d'épingler des programmes, mais pas officiellement. Sur la base d'un code écrit dans this thread (qui utilise la même manière que décrite dans l'article lié par @ Mark Redman) J'ai écrit ce qui suit:

[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 '[email protected] 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; 

Le code ci-dessus se lit d'abord la légende de l'élément de menu pour épingler ou libérer les applications de la table de chaînes de la bibliothèque Shell32.dll. Puis se connecte à l'environnement Windows et à l'application cible. path crée l'objet Folder, puis obtient l'objet FolderItem et, sur cet objet, itère tous les verbes disponibles et vérifie si leur nom correspond à celui lu dans la table de chaînes de la bibliothèque Shell32.dll. Si tel est le cas, il appelle l'action du verbe en appelant la méthode DoIt et quitte l'itération.

Voici une utilisation possible du code ci-dessus, pour épingler:

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); 

Et pour annuler l'épinglage:

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); 

S'il vous plaît noter que même si ce code fonctionne sous Windows 7 (et épingler la barre des tâches aussi sur Windows 8.1 où je l'ai testé), il est vraiment hacky, puisqu'il n'y a pas de façon officielle de programmer les programmes sur la barre des tâches, ni de démarrer le menu. C'est ce que les utilisateurs devraient faire de leur propre choix.

+1

OMG, combien d'heures avez-vous essayé de comprendre? Merci beaucoup! – tmighty

+0

@tmighty, je suis content que ça a aidé quelqu'un! Et il m'a fallu moins d'une heure; c'est juste un code refactorisé du fil lié :-) – TLama

+0

Merci! :-) Pouvez-vous me dire votre façon préférée d'exécuter votre code? Je veux dire le "si PinAppTo (ExpandConstant ('{sys} \ calc.exe'), pdTaskbar) alors ...". Où faites-vous cela? Le définissez-vous comme une tâche ou exécutez-vous ce code automatiquement? Je n'ai jamais couru de code auparavant sauf pour installer les runtimes vcredist_x86 que j'ai couru en utilisant [Run] "Filename:" {tmp} \ vcredist_x86.exe "; Paramètres:"/q "; Check: VCRedistNeedsInstall .C'était juste un exe que je a dû fonctionner, pas une fonction comme la vôtre – tmighty