Korzystam z doskonałego instalatora Inno Setup i zauważam, że niektóre aplikacje (często z Microsoft) są instalowane z ikoną uruchamiania, która jest już bardzo widoczna ("przypięta?") W menu startowym (w systemie Windows 7). Czy jestem całkowicie uzależniony od ostatnio używanego algorytmu, aby moja ikona była "duża" w menu startowym, czy jest jakiś sposób na promowanie mojej aplikacji z instalatora?Czy możliwe jest "Przypnij do menu startowego" za pomocą Inno Setup?
Odpowiedz
Jest powód jest no programmatic way rzeczy przypiąć do paska zadań/menu start. Z mojego doświadczenia wynika, że widziałem menu startowe highlight newly-created shortcuts, które zaprojektowano tak, aby obsługiwać dokładnie tę sytuację. Gdy pojawi się nowo zainstalowany program w menu startowym, jest to prawdopodobnie spowodowane tym algorytmem, a nie dlatego, że instalator umieścił go w tym menu.
Powiedział, że jeśli nowy skrót robi nie zostaną podświetlone, to może być, ponieważ instalator wypakowuje wcześniej istniejącego skrótu i zachowuje starą znacznik czasu na nim, a nie przy użyciu funkcji API do tworzenia skrótów w menu startowe.
Możliwe jest przypinanie programów, ale nie jest to oficjalnie. Na podstawie kodu zamieszczonych w this thread
(który wykorzystuje ten sam sposób, jak opisano w artykule połączonych @Mark Redman) Napisałem następujący:
[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;
Powyższy kod najpierw odczytuje podpis pozycji menu lub do przypinania odpinanie aplikacji z tabeli ciągów biblioteki Shell32.dll
. Następnie łączy się ze skorupą systemu Windows i docelową aplikacją. Ścieżka tworzy obiekt Folder
, a następnie uzyskuje obiekt FolderItem
i na tym obiekcie iteruje wszystkie dostępne czasowniki i sprawdza, czy ich nazwa jest zgodna z tą odczytaną z tabeli ciągów biblioteki bibliotecznej . Jeśli tak, wywołuje działanie elementu czasownika, wywołując metodę DoIt
i zamyka tę iterację.
Tutaj jest możliwe korzystanie z powyższym kodem, na przypinanie:
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);
I odpiąć:
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);
Należy pamiętać, że chociaż ten kod działa na Windows 7 (i paska zadań pinningu również w systemie Windows 8.1, gdzie testowałem), jest to naprawdę hacky, ponieważ nie ma oficjalnego sposobu programowego przypinania programów do paska zadań, ani uruchamiania menu. To właśnie użytkownicy powinni robić według własnego wyboru.
OMG, ile godzin próbowałeś to rozgryźć? Dziękuję bardzo! – tmighty
@tmighty, cieszę się, że pomogło komuś! Zajęło mi to mniej niż godzinę; to tylko refaktoryzowany kod z połączonego wątku :-) – TLama
Dziękuję! :-) Czy możesz mi podać preferowany sposób wykonywania kodu? Mam na myśli "if PinAppTo (ExpandConstant ('{sys} \ calc.exe'), pdTaskbar), a następnie ...". Gdzie to robisz? Czy definiujesz to jako zadanie, czy też wykonujesz ten kod automatycznie? Nigdy wcześniej nie uruchamiałem kodu z wyjątkiem instalacji środowiska uruchomieniowego vcredist_x86, które uruchomiłem przy użyciu polecenia [Uruchom] "Nazwa pliku:" {tmp} \ vcredist_x86.exe "; Parametry:"/q "; Sprawdź: VCRedistNeedsInstall. To był tylko exe, który musiał biec, a nie jak twoja. – tmighty
i jak zauważono w tym artykule, istnieje powód, dla którego nie istnieje interfejs API do przypinania bezpośrednio. Proszę nie spamować pulpitu/paska zadań/startmenu/etc. –