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


Руководство по созданию модуля на уровне запросов HTTP с использованием нативного кода

В этом пошаговом руководстве показано, как использовать C++ для создания примера http-модуля уровня запроса, реализующего новую архитектуру обработки запросов в IIS 7. Эта новая архитектура расширяет возможности программирования на нативном коде при разработке приложений IIS, когда используются более ранние версии ASP.NET, модули HTTP и фильтры или расширения ISAPI. Дополнительные сведения о проектировании модулей HTTP с использованием новой архитектуры обработки запросов см. в "Проектирование модулей HTTP в собственном коде".

В этом пошаговом руководстве вы создадите проект C++ для модуля HTTP, добавьте необходимый код для проекта Hello World, а затем скомпилируйте и протестируйте модуль.

Необходимые условия

Для выполнения действий, описанных в примере, требуется следующее программное обеспечение:

  • IIS 7.

  • Visual Studio 2005.

  • Комплект средств разработки программного обеспечения Windows (SDK).

    Примечание Вы можете использовать Visual Studio .NET 2003 или более ранних версий, хотя пошаговое руководство может не совпадать.

Создание модуля

В этой части пошагового руководства вы создадите пустой проект DLL C++ для модуля HTTP.

Создание проекта библиотеки DLL C++

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

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

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

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

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

    4. Убедитесь, что путь, в котором вы установили файлы включения SDK для Windows, указан в списке. Если путь не указан, щелкните значок "Новая строка" и добавьте путь к файлам include 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. В области шаблонов выберите шаблон файла Module-Definition.

    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. Перейдите на веб-сайт с помощью Internet Explorer; Вы увидите "Пример начала запроса" с отображаемым числом запросов.

Замечание

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

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

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

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

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

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

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

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

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

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

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

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

    1. В меню проекта щелкните Свойства.

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

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

См. также

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