Пошаговое руководство. Создание модуля HTTP Request-Level с помощью машинного кода
В этом пошаговом руководстве показано, как использовать C++ для создания примера http-модуля уровня запроса, который реализует новую архитектуру обработки запросов в IIS 7. Эта новая архитектура расширяет возможности программирования машинного кода при написании приложений IIS более ранних версий ASP.NET HTTP-модулей и фильтров или расширений ISAPI. Дополнительные сведения о проектировании http-модулей с использованием новой архитектуры обработки запросов см. в разделе Проектирование Native-Code HTTP-модулей.
В этом пошаговом руководстве вы создадите проект C++ для модуля HTTP, добавьте необходимый код для проекта "Hello World", а затем скомпилируете и протестируете модуль.
Предварительные требования
Для выполнения действий, описанных в примере, требуется следующее программное обеспечение:
IIS 7.
Visual Studio 2005.
Пакет средств разработки программного обеспечения (SDK) для Windows.
Примечание Вы можете использовать Visual Studio .NET 2003 или более ранней версии, хотя пошаговые инструкции могут быть не идентичными.
Создание модуля
В этой части пошагового руководства вы создадите пустой проект DLL C++ для модуля HTTP.
Создание нового проекта библиотеки DLL C++
Откройте Visual Studio 2005.
Убедитесь, что глобальные параметры имеют все правильные пути к пакету SDK, включая файлы:
В меню Сервис выберите пункт Параметры.
Разверните узел Проекты и решения в древовидном представлении и щелкните Каталоги VC++.
В раскрывающемся списке Показать каталоги для выберите Включить файлы.
Убедитесь, что в списке указан путь, по которому вы установили включаемые файлы Windows SDK. Если путь отсутствует в списке, щелкните значок Создать строку и добавьте путь, по которому вы установили файлы пакета SDK. Каталог установки по умолчанию — $(VCInstallDir)PlatformSDK\bin.
Нажмите кнопку ОК.
Создайте проект C++:
В меню Файл укажите Создать, затем нажмите Проект.
Откроется диалоговое окно Новый проект .
В области Типы проектов разверните узел Visual C++ и щелкните Win32.
В области Шаблоны выберите Проект Win32.
В поле Имя введите HelloWorld.
В поле Расположение введите путь к образцу.
Нажмите кнопку ОК.
Откроется мастер приложений Win32 .
Щелкните Параметры приложения.
В разделе Тип приложения щелкните DLL.
В разделе Дополнительные параметры щелкните Пустой проект.
Нажмите кнопку Готово.
Добавление кода и исходных файлов
Следующим шагом является добавление необходимых файлов C++ и определения модуля в проект.
Добавление исходных файлов в проект
Создайте файл определения модуля для экспорта функции RegisterModule :
В Обозреватель решений щелкните правой кнопкой мыши Исходные файлы, наведите указатель на пункт Добавить и выберите пункт Создать элемент.
Откроется диалоговое окно Добавление нового элемента.
Разверните узел Visual C++ в области Категории и щелкните Код.
В области Шаблоны выберите шаблон Файл определения модуля .
В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .
Нажмите кнопку Добавить.
Добавьте строку с
EXPORTS
помощью иRegisterModule
. Файл должен выглядеть следующим образом:LIBRARY"HelloWorld" EXPORTS RegisterModule
Примечание
Вместо создания файла определения модуля можно экспортировать функцию RegisterModule с помощью параметра /EXPORT:RegisterModule .
Создайте файл C++:
В Обозреватель решений щелкните правой кнопкой мыши Исходные файлы, наведите указатель на пункт Добавить и выберите пункт Создать элемент.
Откроется диалоговое окно Добавление нового элемента.
Разверните узел Visual C++ в области Категории и щелкните Код.
В области Шаблоны выберите шаблон Файл C++ .
В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .
Нажмите кнопку Добавить.
Добавьте следующий код:
#define _WINSOCKAPI_ #include <windows.h> #include <sal.h> #include <httpserv.h> // Create the module class. class CHelloWorld : public CHttpModule { public: REQUEST_NOTIFICATION_STATUS OnBeginRequest( IN IHttpContext * pHttpContext, IN IHttpEventProvider * pProvider ) { UNREFERENCED_PARAMETER( pProvider ); // Create an HRESULT to receive return values from methods. HRESULT hr; // Retrieve a pointer to the response. IHttpResponse * pHttpResponse = pHttpContext->GetResponse(); // Test for an error. if (pHttpResponse != NULL) { // Clear the existing response. pHttpResponse->Clear(); // Set the MIME type to plain text. pHttpResponse->SetHeader( HttpHeaderContentType,"text/plain", (USHORT)strlen("text/plain"),TRUE); // Create a string with the response. PCSTR pszBuffer = "Hello World!"; // Create a data chunk. HTTP_DATA_CHUNK dataChunk; // Set the chunk to a chunk in memory. dataChunk.DataChunkType = HttpDataChunkFromMemory; // Buffer for bytes written of data chunk. DWORD cbSent; // Set the chunk to the buffer. dataChunk.FromMemory.pBuffer = (PVOID) pszBuffer; // Set the chunk size to the buffer size. dataChunk.FromMemory.BufferLength = (USHORT) strlen(pszBuffer); // Insert the data chunk into the response. hr = pHttpResponse->WriteEntityChunks( &dataChunk,1,FALSE,TRUE,&cbSent); // Test for an error. if (FAILED(hr)) { // Set the HTTP status. pHttpResponse->SetStatus(500,"Server Error",0,hr); } // End additional processing. return RQ_NOTIFICATION_FINISH_REQUEST; } // Return processing to the pipeline. return RQ_NOTIFICATION_CONTINUE; } }; // Create the module's class factory. class CHelloWorldFactory : public IHttpModuleFactory { public: HRESULT GetHttpModule( OUT CHttpModule ** ppModule, IN IModuleAllocator * pAllocator ) { UNREFERENCED_PARAMETER( pAllocator ); // Create a new instance. CHelloWorld * pModule = new CHelloWorld; // Test for an error. if (!pModule) { // Return an error if the factory cannot create the instance. return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY ); } else { // Return a pointer to the module. *ppModule = pModule; pModule = NULL; // Return a success status. return S_OK; } } void Terminate() { // Remove the class from memory. delete this; } }; // Create the module's exported registration function. HRESULT __stdcall RegisterModule( DWORD dwServerVersion, IHttpModuleRegistrationInfo * pModuleInfo, IHttpServer * pGlobalInfo ) { UNREFERENCED_PARAMETER( dwServerVersion ); UNREFERENCED_PARAMETER( pGlobalInfo ); // Set the request notifications and exit. return pModuleInfo->SetRequestNotifications( new CHelloWorldFactory, RQ_BEGIN_REQUEST, 0 ); }
Компиляция и тестирование модуля
Компиляция и тестирование проекта
Скомпилируйте модуль HTTP:
В меню Сборка выберите Собрать решение.
Убедитесь, что Visual Studio не вернул никаких ошибок или предупреждений.
Добавьте модуль HelloWorld.dll (с полным путем) в
globalModules
раздел файла %windir%\system32\inetsrv\config\applicationHost.config.
Используйте интернет-Обозреватель для перехода на веб-сайт. Вы должны увидеть "Пример начала запроса" с отображаемым числом запросов.
Примечание
Прежде чем привязать проект к последующим сборкам, необходимо остановить службы IIS.
Устранение неполадок параметров
Если модуль не компилируется или не работает должным образом, можно проверка несколько областей:
Убедитесь, что вы указали
__stdcall
для экспортированных функций или настроили компиляцию с помощью соглашения о вызовах__stdcall (/Gz)
.Убедитесь, что службы IIS загружены HelloWorld.dll:
В диспетчере IIS щелкните Веб-сайт по умолчанию в области Подключения .
В рабочей области (центральная панель) выберите Представление функций.
В поле Группировать по выберите Категория.
В категории Серверные компоненты дважды щелкните Модули.
Убедитесь, что модуль HelloWorld указан в списке.
Убедитесь, что вы добавили правильный
RegisterModule
экспорт в файл определения.Убедитесь, что вы добавили файл определения в параметры проекта. Чтобы добавить файл в параметры проекта, выполните следующие действия.
В меню Проект выберите Свойства.
Разверните узел Свойства конфигурации в представлении дерева, разверните узел Компоновщик и щелкните Входные данные.
Для параметров Файл определения модуля убедитесь, что файл определения указан в списке.
См. также:
Создание Native-Code http-модулей
Проектирование Native-Code http-модулей