Shortcuts, shell and COM apartments

Дурная голова ногам покоя не даёт.

Поставил свежий WDK и понял, что мне жутко надоело каждый раз исправлять все ярлыки, меняя шрифт на Lucida Console и размеры окна со стандартных 80x25 на более удобоваримые 170x75. Зачесались руки автоматизировать это дело.

После непродолжительной борьбы желание сделать все красиво победило здравый смысл и заглушило внутренний голос, который что-то невнятно бубнил про “простые решения”. Короче захотелось написать .NET обертку для стандартных IShellLink и IShellLinkDataList чтобы её можно было использовать из PowerShell. Сказано-сделано. Нашёл пару примеров на Code Project и vbAccelerator и принялся за дело.

С IShellLink все работало как по маслу. Дело застопорилось том, что QueryInterface наотрез отказывался возвращать IShellLinkDataList, утверждая, что такого интерфейса CLSID_ShellLink не поддерживает (E_NOINTERFACE). Покопавшись немного в интернете наткнулся на вот эту заметку. Оказалось, что все дело в разных COM Apartments. CLSID_ShellLink использует Apartment Threading Model, а PowerShell - Multithreaded Apartment. Кроме того, оказалось, что IShellLinkDataList вообще не зарегестрирован в реестре и, соответственно, для него не задан proxy (ProxyStubClsid32). Иными словами нормально работать с IShellLinkDataList можно только из Single-Threaded Apartment.

Теперь думаю как лучше обойти это ограничение. Вариантов пока всего два. Первый - создавать CLSID_ShellLink в отдельном потоке, выставив для него STA модель. Собственно говоря, это тоже самое, что предлагает Mow в своем блоге. Второе решение - написать proxy для IShellLinkDataList, мне нравиться гораздо больше в силу своей универсальности. Сложность в том, что я этого никогда не делал и весьма смутно представляю себе с чего надо начинать. Посмотрим, что из этого получится.

comments powered by Disqus