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
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.
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.
OMG, combien d'heures avez-vous essayé de comprendre? Merci beaucoup! – tmighty
@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
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
et comme indiqué dans cet article, il y a une raison pour laquelle il n'y a pas d'API pour épingler directement. S'il vous plaît ne pas spammer le bureau/barre des tâches/startmenu/etc. –