Пошаговое руководство. Создание модуля HTTP Global-Level с помощью машинного кода
В этом пошаговом руководстве показано, как использовать C++ для создания примера модуля HTTP глобального уровня, реализующего новую архитектуру обработки запросов в IIS 7. Эта новая архитектура расширяет возможности программирования машинного кода при написании приложений IIS более ранних версий ASP.NET модулей HTTP и фильтров или расширений ISAPI. Дополнительные сведения о проектировании модулей HTTP с использованием новой архитектуры обработки запросов см. в разделе Проектирование модулей Native-Code HTTP.
В этом пошаговом руководстве вы создадите проект C++ для модуля HTTP, добавите необходимый код для проекта "Hello World", а затем скомпилируете и протестируете модуль.
Предварительные требования
Для выполнения действий, описанных в примере, требуется следующее программное обеспечение:
IIS 7.
Visual Studio 2005.
Примечание
Вы также можете использовать Visual Studio .NET 2003 или более ранней версии, хотя пошаговые инструкции могут быть не идентичными.
Создание модуля
В этой части пошагового руководства вы создадите пустой проект библиотеки DLL C++ для модуля HTTP.
Создание проекта библиотеки DLL C++
Запустите Visual Studio 2005.
Убедитесь, что глобальные параметры имеют все правильные пути к файлам пакета SDK:
В меню Сервис выберите пункт Параметры.
Разверните узел Проекты и решения в представлении в виде дерева, а затем щелкните Каталоги VC++.
В раскрывающемся списке Показать каталоги для выберите Включить файлы.
Убедитесь, что указан путь, по которому вы установили включаемые файлы пакета SDK. Если путь отсутствует в списке, щелкните значок Создать строку , а затем добавьте путь к установленным файлам включения пакета SDK.
Нажмите кнопку ОК.
Создайте проект C++:
В меню Файл укажите Создать, затем нажмите Проект.
Откроется диалоговое окно Новый проект .
В области Типы проектов разверните узел Visual C++ и щелкните Win32.
В области Шаблоны выберите Проект Win32.
В поле Имя введите HelloWorld.
В поле Расположение введите путь к примеру.
Нажмите кнопку ОК.
Откроется мастер приложений Win32 .
Щелкните Параметры приложения.
В разделе Тип приложения щелкните DLL.
В разделе Дополнительные параметры щелкните Пустой проект.
Нажмите кнопку Готово.
Добавление файлов кода и исходных файлов
Следующим шагом является добавление необходимых файлов C++ и module definition-files в проект.
Добавление исходных файлов в проект
Создайте файл определения модуля для экспорта функции RegisterModule :
В Обозреватель решений щелкните правой кнопкой мыши исходные файлы, наведите указатель мыши на пункт Добавить, а затем выберите пункт Создать элемент.
Откроется диалоговое окно Добавление нового элемента.
Разверните узел Visual C++ в области Категории и щелкните Код.
В области Шаблоны выберите шаблон Файл определения модуля .
В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .
Нажмите кнопку Добавить.
Добавьте следующий код:
LIBRARY HelloWorld EXPORTS RegisterModule
При необходимости можно экспортировать функцию RegisterModule с помощью параметра /EXPORT:RegisterModule :
В меню Проект выберите свойства HelloWorld.
Разверните узел Свойства конфигурации в представлении дерева, разверните узел Компоновщик и щелкните Командная строка.
В раскрывающемся списке Конфигурация выберите Все конфигурации.
В поле Дополнительные параметры введите /EXPORT:RegisterModule.
Нажмите кнопку ОК.
Создайте файл C++:
В Обозреватель решений щелкните правой кнопкой мыши исходные файлы, наведите указатель мыши на пункт Добавить, а затем выберите пункт Создать элемент.
Откроется диалоговое окно Добавление нового элемента.
Разверните узел Visual C++ в области Категории и щелкните Код.
В области Шаблоны выберите шаблон Файл C++ .
В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .
Нажмите кнопку Добавить.
Добавьте следующий код:
#define _WINSOCKAPI_ #include <windows.h> #include <sal.h> #include <httpserv.h> // Create the module's global class. class MyGlobalModule : public CGlobalModule { public: // Process a GL_APPLICATION_START notification. GLOBAL_NOTIFICATION_STATUS OnGlobalPreBeginRequest( IN IPreBeginRequestProvider * pProvider ) { UNREFERENCED_PARAMETER( pProvider ); WriteEventViewerLog( "Hello World!" ); return GL_NOTIFICATION_CONTINUE; } VOID Terminate() { // Remove the class from memory. delete this; } MyGlobalModule() { // Open a handle to the Event Viewer. m_hEventLog = RegisterEventSource( NULL,"IISADMIN" ); } ~MyGlobalModule() { // Test whether the handle for the Event Viewer is open. if (NULL != m_hEventLog) { // Close the handle to the Event Viewer. DeregisterEventSource( m_hEventLog ); m_hEventLog = NULL; } } private: // Create a handle for the event viewer. HANDLE m_hEventLog; // Define a method that writes to the Event Viewer. BOOL WriteEventViewerLog(LPCSTR szNotification) { // Test whether the handle for the Event Viewer is open. if (NULL != m_hEventLog) { // Write any strings to the Event Viewer and return. return ReportEvent( m_hEventLog, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, &szNotification, NULL ); } return FALSE; } }; // Create the module's exported registration function. HRESULT __stdcall RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pGlobalInfo ) { UNREFERENCED_PARAMETER( dwServerVersion ); UNREFERENCED_PARAMETER( pGlobalInfo ); // Create an instance of the global module class. MyGlobalModule * pGlobalModule = new MyGlobalModule; // Test for an error. if (NULL == pGlobalModule) { return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); } // Set the global notifications and exit. return pModuleInfo->SetGlobalNotifications( pGlobalModule, GL_PRE_BEGIN_REQUEST ); }
При необходимости можно скомпилировать код с помощью соглашения о вызовах
__stdcall (/Gz)
:В меню Проект выберите свойства HelloWorld.
Разверните узел Свойства конфигурации в представлении дерева, разверните узел C/C++ и нажмите кнопку Дополнительно.
В раскрывающемся списке Конфигурация выберите Все конфигурации.
В раскрывающемся списке Соглашение о вызовах выберите __stdcall (/Gz).
Нажмите кнопку ОК.
Компиляция и тестирование модуля
В модуле HTTP есть все необходимое. Все, что требуется, — это компиляция и тестирование модуля HTTP.
Компиляция и тестирование проекта
Скомпилируйте модуль HTTP:
В меню Сборка выберите Собрать решение.
Убедитесь, что Visual Studio не вернул никаких ошибок или предупреждений. При возникновении ошибок или предупреждений необходимо устранить эти проблемы перед тестированием проекта.
Скопируйте DLL-файл для модуля HTTP в папку IIS:
Откройте windows Обозреватель и найдите папку по умолчанию, указанную при создании проекта C++.
В зависимости от параметров сборки в папке по умолчанию для проекта должна появиться папка с именем Debug или Release.
В папке Отладка или Выпуск найдите файл с именем HelloWorld.dll.
Скопируйте файл HelloWorld.dll в папку Inetsrv, которая по умолчанию находится в папке %WinDir%\System32\Inetsrv.
Добавьте модуль HelloWorld.dll в список модулей (инструкции см. в разделе Проектирование модулей Native-Code HTTP).
Используйте интернет-Обозреватель для перехода на веб-сайт. Вы должны увидеть обычное содержимое веб-сайта.
Откройте Просмотр событий Windows и перейдите к глобальному журналу приложений. Вы увидите запись, в которую в качестве источника событий указан "IISADMIN".
Щелкните событие правой кнопкой мыши и выберите пункт Свойства , чтобы просмотреть сведения о событии. В области описания должно отобразиться сообщение "Hello World!".
Устранение неполадок с параметрами
Если модуль не компилируется или не работает должным образом, можно проверка несколько областей:
Убедитесь, что вы указали
__stdcall
для экспортированных функций или что вы настроили компиляцию с помощью соглашения о вызовах__stdcall (/Gz)
.Убедитесь, что вы добавили правильный
RegisterModule
экспорт в файл определения.Убедитесь, что вы добавили файл определения в параметры проекта. Чтобы добавить файл в параметры проекта, выполните следующие действия.
В меню Проект выберите Свойства.
Разверните узел Свойства конфигурации в представлении дерева, узел Компоновщик и нажмите кнопку Входные данные.
Для параметров Файл определения модуля убедитесь, что файл определения указан в списке.