Problémy s Shell Extensions: z pohledu AS2.5
Posted: 08 May 2007, 08:01
S podporou pro overlay icons (od 2.5RC3) jsme narazili na novou vlnu nestability díky TortoiseSVN. Zakládám toto vlákno za účelem prodiskutování možných řešení.
Nezbytné čtení na úvod: Creating Shell Extension Handlers (MSDN). Většina popsaných handlerů se Salamandera týká.
Popis problému (KDY a KDE je voláme):
1. některé shell extension jsou do procesu Salamandera načteny v rámci odbavováni drag&drop a context menu -- v těchto případech nad jejich načtením a vyvoláním nemáme žádnou kontrolu, enumeraci registry, načtení DLL a jejích zavolání provádí Windows v rámci zavolaných API funkcí; tyto běží v našem hlavním vlákně, které odbavuje message queue a kde běží GUI
1.1 častým případem předešlého jsou problémy s otevíráním dokumentů, které jsme se pokoušeli vyřešit pomocí zavolání IContextMenu2::QueryContextMenu() a InvokeCommand() v rámci jiného procesu SALOPEN.EXE
2. implementace overlay icons probíhá kompletně v režii Salamandera, známe seznam všech poskytovatelů a sami je postupně voláme pro každý soubor a adresář (máme šanci vytvořit black/white list); tyto shell extensions načítáme a voláme ve dvou vláknech (levý a pravý panel), které obsluhují načítání ikonek do panelech, viz "apartment threaded" chyba 2.5RC3 opravená v 2.5
3. ze zmíněných dvou vláken pro čtení ikon dochází u některých souborů k získávání ikonek pomocí Icon Handlers; v tomto případě je načtení a vyvolání DLL opět v režii Windows API, jako v případě (1.)
(JAK nám konkrétně škodí)
4. pády bez korupce zásobníku -- ty zachytíme a korektně zobrazíme bug report, ze kterého lze shell extension určite (její DLL je vidět na stacku)
5. korupce zásobníku nebo paměti (shell extension například zapíše do ANSI bufferu na stacku UNICODE string, takže přepíše okolí bufferu; k pádu může dojít v shell extension nebo po návratu) -- tyto pády je problém diagnostikovat
6. shell extension zavolá DestroyWindow() na parent okno, protože tímto způsobem zavírají Windows Explorer okna (dříve jsme podávali handle okna panelu, nyní předhazujeme speciální dočasné child okno, u kterého po návratu detekujeme, zda bylo zavřeno a zobrazíme Bug Report) -- pokud shell extension provede iteraci směrem k main window, stějně dokáže Salamandera přes DestroyWindow sestřelit
7. Windows Media Player, pokud je spuštěn poprvé, zobrazuje úvodní okénko s dotazy na konektivitu atd; toto proběhne v našem hlavním vlákně po zavolání IContextMenu2::InvokeCommand() (viz konkrétní případ); po zavření tohoto okna neukončí svou message loop a pumpuje zprávy ze svého DLL; Total Commander i Windows Explorer celkem bez potíží v tomto stavu fungují, ale Salamander má poměrně komplikovanou obsluhu message queue a pokud se nám do ní hlavní vlákno nevrátí, vzniká problém
Edit: další případ
8. Shell Extensions s oblibou zapomínají zavírat handly na otevřené soubory a adresáře, viz tento problém, kde jsem se pokusil problematiku shell extensions popsat; Salamander následně se souborem nebo adresářem nedokáže pracovat (sám si blokuje přístup) a pomůže až restart Salamandera
9. Icon Handlers dokážou během získávání ikonek spadnout; často tak padají Adobe Photoshop a Illustrator Icon Handlery, vedlo to dokonce na poměrně tvrdou výměnu názorů mezi Adobe a Microsoft (Adobe tvrdil, že Windows Explorer je nestabilní platforma a Microsoft naopak z problému vinil vadný Adobe Icon Handler, což můžeme jen potvrdit); malá ukázka této pohromy: Photoshop a Illustrator
Protože jsou shell extensions nejčastějším zdrojem problémů, připravili jsme kuchařku jak vadné shell extensions dohledat a vyřadit.
Pokud máte nápady na zlepšení současné situace, neváhejte a pište. Rádi také zodpovíme doplňující dotazy.
Nezbytné čtení na úvod: Creating Shell Extension Handlers (MSDN). Většina popsaných handlerů se Salamandera týká.
Popis problému (KDY a KDE je voláme):
1. některé shell extension jsou do procesu Salamandera načteny v rámci odbavováni drag&drop a context menu -- v těchto případech nad jejich načtením a vyvoláním nemáme žádnou kontrolu, enumeraci registry, načtení DLL a jejích zavolání provádí Windows v rámci zavolaných API funkcí; tyto běží v našem hlavním vlákně, které odbavuje message queue a kde běží GUI
1.1 častým případem předešlého jsou problémy s otevíráním dokumentů, které jsme se pokoušeli vyřešit pomocí zavolání IContextMenu2::QueryContextMenu() a InvokeCommand() v rámci jiného procesu SALOPEN.EXE
2. implementace overlay icons probíhá kompletně v režii Salamandera, známe seznam všech poskytovatelů a sami je postupně voláme pro každý soubor a adresář (máme šanci vytvořit black/white list); tyto shell extensions načítáme a voláme ve dvou vláknech (levý a pravý panel), které obsluhují načítání ikonek do panelech, viz "apartment threaded" chyba 2.5RC3 opravená v 2.5
3. ze zmíněných dvou vláken pro čtení ikon dochází u některých souborů k získávání ikonek pomocí Icon Handlers; v tomto případě je načtení a vyvolání DLL opět v režii Windows API, jako v případě (1.)
(JAK nám konkrétně škodí)
4. pády bez korupce zásobníku -- ty zachytíme a korektně zobrazíme bug report, ze kterého lze shell extension určite (její DLL je vidět na stacku)
5. korupce zásobníku nebo paměti (shell extension například zapíše do ANSI bufferu na stacku UNICODE string, takže přepíše okolí bufferu; k pádu může dojít v shell extension nebo po návratu) -- tyto pády je problém diagnostikovat
6. shell extension zavolá DestroyWindow() na parent okno, protože tímto způsobem zavírají Windows Explorer okna (dříve jsme podávali handle okna panelu, nyní předhazujeme speciální dočasné child okno, u kterého po návratu detekujeme, zda bylo zavřeno a zobrazíme Bug Report) -- pokud shell extension provede iteraci směrem k main window, stějně dokáže Salamandera přes DestroyWindow sestřelit
7. Windows Media Player, pokud je spuštěn poprvé, zobrazuje úvodní okénko s dotazy na konektivitu atd; toto proběhne v našem hlavním vlákně po zavolání IContextMenu2::InvokeCommand() (viz konkrétní případ); po zavření tohoto okna neukončí svou message loop a pumpuje zprávy ze svého DLL; Total Commander i Windows Explorer celkem bez potíží v tomto stavu fungují, ale Salamander má poměrně komplikovanou obsluhu message queue a pokud se nám do ní hlavní vlákno nevrátí, vzniká problém
Edit: další případ
8. Shell Extensions s oblibou zapomínají zavírat handly na otevřené soubory a adresáře, viz tento problém, kde jsem se pokusil problematiku shell extensions popsat; Salamander následně se souborem nebo adresářem nedokáže pracovat (sám si blokuje přístup) a pomůže až restart Salamandera
9. Icon Handlers dokážou během získávání ikonek spadnout; často tak padají Adobe Photoshop a Illustrator Icon Handlery, vedlo to dokonce na poměrně tvrdou výměnu názorů mezi Adobe a Microsoft (Adobe tvrdil, že Windows Explorer je nestabilní platforma a Microsoft naopak z problému vinil vadný Adobe Icon Handler, což můžeme jen potvrdit); malá ukázka této pohromy: Photoshop a Illustrator
Protože jsou shell extensions nejčastějším zdrojem problémů, připravili jsme kuchařku jak vadné shell extensions dohledat a vyřadit.
Pokud máte nápady na zlepšení současné situace, neváhejte a pište. Rádi také zodpovíme doplňující dotazy.