Поделиться через


Пошаговое руководство. Создание модуля 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++

  1. Откройте Visual Studio 2005.

  2. Убедитесь, что глобальные параметры имеют все правильные пути к пакету SDK, включая файлы:

    1. В меню Сервис выберите пункт Параметры.

    2. Разверните узел Проекты и решения в древовидном представлении и щелкните Каталоги VC++.

    3. В раскрывающемся списке Показать каталоги для выберите Включить файлы.

    4. Убедитесь, что в списке указан путь, по которому вы установили включаемые файлы Windows SDK. Если путь отсутствует в списке, щелкните значок Создать строку и добавьте путь, по которому вы установили файлы пакета SDK. Каталог установки по умолчанию — $(VCInstallDir)PlatformSDK\bin.

    5. Нажмите кнопку ОК.

  3. Создайте проект C++:

    1. В меню Файл укажите Создать, затем нажмите Проект.

      Откроется диалоговое окно Новый проект .

    2. В области Типы проектов разверните узел Visual C++ и щелкните Win32.

    3. В области Шаблоны выберите Проект Win32.

    4. В поле Имя введите HelloWorld.

    5. В поле Расположение введите путь к образцу.

    6. Нажмите кнопку ОК.

      Откроется мастер приложений Win32 .

    7. Щелкните Параметры приложения.

    8. В разделе Тип приложения щелкните DLL.

    9. В разделе Дополнительные параметры щелкните Пустой проект.

    10. Нажмите кнопку Готово.

Добавление кода и исходных файлов

Следующим шагом является добавление необходимых файлов C++ и определения модуля в проект.

Добавление исходных файлов в проект

  1. Создайте файл определения модуля для экспорта функции RegisterModule :

    1. В Обозреватель решений щелкните правой кнопкой мыши Исходные файлы, наведите указатель на пункт Добавить и выберите пункт Создать элемент.

      Откроется диалоговое окно Добавление нового элемента.

    2. Разверните узел Visual C++ в области Категории и щелкните Код.

    3. В области Шаблоны выберите шаблон Файл определения модуля .

    4. В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .

    5. Нажмите кнопку Добавить.

    6. Добавьте строку с EXPORTS помощью и RegisterModule. Файл должен выглядеть следующим образом:

      LIBRARY"HelloWorld"  
      EXPORTS  
          RegisterModule  
      

      Примечание

      Вместо создания файла определения модуля можно экспортировать функцию RegisterModule с помощью параметра /EXPORT:RegisterModule .

  2. Создайте файл C++:

    1. В Обозреватель решений щелкните правой кнопкой мыши Исходные файлы, наведите указатель на пункт Добавить и выберите пункт Создать элемент.

      Откроется диалоговое окно Добавление нового элемента.

    2. Разверните узел Visual C++ в области Категории и щелкните Код.

    3. В области Шаблоны выберите шаблон Файл C++ .

    4. В поле Имя введите HelloWorld и оставьте путь к файлу по умолчанию в поле Расположение .

    5. Нажмите кнопку Добавить.

    6. Добавьте следующий код:

      #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
          );
      }
      

Компиляция и тестирование модуля

Компиляция и тестирование проекта

  1. Скомпилируйте модуль HTTP:

    1. В меню Сборка выберите Собрать решение.

    2. Убедитесь, что Visual Studio не вернул никаких ошибок или предупреждений.

    3. Добавьте модуль HelloWorld.dll (с полным путем) в globalModules раздел файла %windir%\system32\inetsrv\config\applicationHost.config.

  2. Используйте интернет-Обозреватель для перехода на веб-сайт. Вы должны увидеть "Пример начала запроса" с отображаемым числом запросов.

Примечание

Прежде чем привязать проект к последующим сборкам, необходимо остановить службы IIS.

Устранение неполадок параметров

Если модуль не компилируется или не работает должным образом, можно проверка несколько областей:

  • Убедитесь, что вы указали __stdcall для экспортированных функций или настроили компиляцию с помощью соглашения о вызовах __stdcall (/Gz) .

  • Убедитесь, что службы IIS загружены HelloWorld.dll:

    1. В диспетчере IIS щелкните Веб-сайт по умолчанию в области Подключения .

    2. В рабочей области (центральная панель) выберите Представление функций.

    3. В поле Группировать по выберите Категория.

    4. В категории Серверные компоненты дважды щелкните Модули.

    5. Убедитесь, что модуль HelloWorld указан в списке.

  • Убедитесь, что вы добавили правильный RegisterModule экспорт в файл определения.

  • Убедитесь, что вы добавили файл определения в параметры проекта. Чтобы добавить файл в параметры проекта, выполните следующие действия.

    1. В меню Проект выберите Свойства.

    2. Разверните узел Свойства конфигурации в представлении дерева, разверните узел Компоновщик и щелкните Входные данные.

    3. Для параметров Файл определения модуля убедитесь, что файл определения указан в списке.

См. также:

Создание Native-Code http-модулей
Проектирование Native-Code http-модулей