Перехоплення ShellExecuteEx в
Обговорити на форумі
| Перехоплення ShellExecuteEx в .NET |
| ShellExtension.zip (88,48 Kb) |
У цій статті буде описано метод реалізації інтерфейсу IShellExecuteHook з метою перехоплення викликів функції ShellExecuteEx використовуваною оболонкою Windows. Це дозволить написати найпростіше розширення оболонки Windows
У цій статті буде описано метод реалізації інтерфейсу IShellExecuteHook з метою перехоплення викликів функції ShellExecuteEx використовуваною оболонкою Windows. Це дозволить написати найпростіше розширення оболонки Windows (докладніше про розширення оболонки та написання розширень за допомогою Visual C++ та бібліотеки ATL дивіться статті Michael Dunn).
Створення COM компонента
Для того, щоб створити COM компонент програмісту не потрібно докладати зайвих зусиль і писати будь-який додатковий код, достатньо у властивостях складання (Build) проекту Visual Studio .NET встановити значення Register for COM Interop в True.
Інтерфейс IShellExecuteHook
Інтерфейс IShellExecuteHook описує функції ShellExecute та ShellExecuteEx використовувані оболонкою Windows. Наприклад, коли користувач вводить команду, використовуючи пункт меню Run (Виконати) у меню Start (Пуск), або при подвійному клацанні по файлу. Таким чином, перехопивши виклик функції, ми можемо отримати ім'я файлу, директорії, або параметри командного рядка і виконати будь-яку дію, або змусити оболонку не виконувати жодних дій.
Інтерфейс описаний у заголовному файлі shlobj.h, що входить до Platform SDK.
Розглянемо функцію Execute:
Функція повертає S_OK, якщо оболонка не повинна передавати об'єкт у подальшу обробку (це значення можна використовувати для інформуванняоболонку у тому, що розширення обробило об'єкт, або у разі, коли подальша обробка небажана) або S_FALSE інакше.
Аргумент pei являє собою структуру SHELLEXECUTEINFO, що містить інформацію про об'єкт, що викликається. Заглянувши до заголовкового файлу shellapi.h знайдемо опис цієї структури:
Для повноти викладу наведу опис аргументів:
Реалізація C#
Сподіваюся, що Ви не встигли занудьгувати, розглядаючи опис структур C++. Ви чекали .NET. От і дочекалися. Зараз ми "перекладемо" наведені вище описи C++ в описи структур та методів .NET. Також, як описано далі, Ви можете реалізувати будь-який інтерфейс.
Для початку нам знадобиться GUID інтерфейс, який ми хочемо реалізувати. За ним ми заліземо в заголовний файл ShlGuid.h, що входить до Platform SDK і знайдемо рядок:
У більш звичному та знайомому вигляді: . Це значення нам знадобиться для імпорту інтерфейсу COM в C#:
Оскільки IShellExecuteHook успадковує IUnknown, ми вказуємо тип COM інтерфейсу InterfaceIsIUnknown. Аттрибут PreserveSig() вказується для того, щоб параметр, що повертається розглядався саме як параметр стандартного типу HRESULT і не зазнавав будь-яких перетворень.
Потім опишемо наш COM клас, для цього нам знадобиться унікальний GUID, який можна отримати скориставшись стандартною утилітою, що входить до постачання Visual Studio .NET - Create GUID.

Отримавши GUID опишемо клас, який буде доступний як COM:
Даний клас повинен містити лише один метод Execute, в реалізації якого є тільки одна складність - необхідно перекласти структуру SHELLEXECUTEINFO з C++ C# і привести некеровані типи до керованих. Для того, щоб члени структури розміщувалися в пам'ятівказаному порядку необхідно вказати атрибут [StructLayout(LayoutKind.Sequential)]. Наведемо типи та опишемо структуру:
Зверніть увагу, що для відповідності керованого варіанта структури некерованому необхідно явно вказати, що рядки повинні передаватися як некеровані, для чого використовується атрибут MarshalAs (UnmanagedType.LPWStr).
Залишається зовсім небагато - визначити типи значень, що повертаються, щоб код реалізації функції ще більше нагадував стандартний код COM класу. Типів значень, що повертаються в нашому випадку всього два S_OK і S_FALSE, опишемо їх безпосередньо в класі:
Напишемо код для функції Execute:
Головне, при реалізації цієї функції, не забути повертати значення S_FALSE у випадках, коли обробка не потрібна. Як невеликий експеримент можна спробувати на початку функції повертати S_OK. Після цього Ви не зможете змусити оболонку запустити будь-яку програму або будь-яку команду без видалення обробника. Будьте обережні!
Реєстрація "перехоплювача"
Для того, щоб встановити наш COM компонент, що перехоплює функцію ShellExecuteEx, необхідно зареєструвати сам компонент (як зазвичай), а також вказати його GUID у гілці реєстру, призначеної для реєстрації компонентів:
Для цього створимо найпростішу утиліту реєстрації, яка реєструватиме та видалятиме реєстраційні дані з реєстру. Ось два методи, що реалізують цю функціональність:
Для початку відкрийте вихідний код, що додається до статті, потім зберіть рішення та використовуючи утиліту реєстрації зареєструйте наше найпростіше розширення оболонки. Насолоджуйтесь! Ось як виглядає утиліта:
А ось так працює наше розширення:

Спробуйте просто ввести команду time до встановлення розширенняі після встановлення розширення. Різниця видно сама собою.

Висновок
У цій статті було розглянуто спосіб перехоплення функції ShellExecuteEx, а також принагідно розказано про те, як перекласти опис методів і структур із С++ до C#, а також реалізувати стандартний інтерфейс у власному COM компоненті.