共用方式為


逐步解說:使用機器碼建立 Global-Level HTTP 模組

本逐步解說示範如何使用 C++ 來建立範例全域層級 HTTP 模組,以在 IIS 7 中實作新的要求處理架構。 當您在舊版 ASP.NET HTTP 模組和 ISAPI 篩選器或延伸模組上撰寫 IIS 應用程式時,這個新架構會擴充原生程式碼程式設計的功能。 如需使用新要求處理架構設計 HTTP 模組的詳細資訊,請參閱 設計Native-Code HTTP 模組

在本逐步解說中,您將為 HTTP 模組建立 C++ 專案、新增 「Hello World」 專案所需的程式碼,然後編譯及測試模組。

必要條件

需要下列軟體才能完成範例中的步驟:

  • IIS 7。

  • Visual Studio 2005。

注意

您也可以使用 Visual Studio .NET 2003 或更早版本,雖然逐步解說步驟可能不相同。

建立模組

在本逐步解說的這個部分中,您將為 HTTP 模組建立空的 C++ DLL 專案。

若要建立新的 C++ DLL 專案

  1. 啟動 Visual Studio 2005。

  2. 確認全域選項具有 SDK 包含檔案的所有正確路徑:

    1. [工具] 功能表上,按一下 [選項]

    2. 展開樹狀檢視中的 [ 專案和方案 ] 節點,然後按一下 [VC++ 目錄]。

    3. 在 [ 顯示目錄的 下拉式方塊] 中,選取 [包含檔案]。

    4. 確認您安裝 SDK 包含檔案的路徑已列出。 如果未列出路徑,請按一下 [ 新增行 ] 圖示,然後新增您安裝 SDK 包含檔案的路徑。

    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. 新增下列程式碼:

      LIBRARY HelloWorld  
      
      EXPORTS  
          RegisterModule  
      
  2. 您可以選擇性地使用/EXPORT:RegisterModule參數匯出RegisterModule函式:

    1. 在 [ 專案] 功能表上,按一下 [HelloWorld 屬性]。

    2. 展開樹狀檢視中的 [ 組態屬性 ] 節點,展開 [連結器] 節點,然後按一下 [ 命令列]。

    3. 在 [ 組態 ] 下拉式方塊中,選取 [所有組態]。

    4. 在 [ 其他選項 ] 方塊中,輸入 /EXPORT:RegisterModule

    5. 按一下 [確定]。

  3. 建立 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'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 );
      }
      
  4. 您可以選擇性地使用 __stdcall (/Gz) 呼叫慣例來編譯器代碼:

    1. 在 [ 專案] 功能表上,按一下 [HelloWorld 屬性]。

    2. 展開樹狀檢視中的 [ 組態屬性 ] 節點,展開 [C/C++ ] 節點,然後按一下 [ 進階]。

    3. 在 [ 組態 ] 下拉式方塊中,選取 [所有組態]。

    4. 在 [ 呼叫慣例 ] 下拉式方塊中,選取 [__stdcall (/Gz) ]。

    5. 按一下 [確定]。

編譯及測試模組

您的 HTTP 模組具有它所需的一切。 只需要編譯及測試您的 HTTP 模組。

編譯及測試專案

  1. 編譯 HTTP 模組:

    1. 在 [建置] 功能表上,按一下 [建置方案]。

    2. 確認 Visual Studio 未傳回任何錯誤或警告。 如果您遇到任何錯誤或警告,則必須先解決這些問題,才能測試專案。

  2. 將 HTTP 模組的 DLL 檔案複製到 IIS 資料夾:

    1. 開啟 Windows 檔案總管,並找出您在建立 C++ 專案時所指定的預設資料夾。

      根據您的組建選項,您應該會在專案的預設資料夾中看到名為 Debug 或 Release 的資料夾。

    2. 在 [偵錯] 或 [發行] 資料夾中,找出名為 HelloWorld.dll 的檔案。

    3. 將HelloWorld.dll檔案複製到 Inetsrv 資料夾,此資料夾預設位於 %WinDir%\System32\Inetsrv。

  3. 如需指示,請將HelloWorld.dll模組新增至模組清單 (,請參閱 設計Native-Code HTTP 模組) 。

  4. 使用 Internet Explorer 流覽至您的網站;您應該會看到您的一般網站內容。

  5. 開啟 Windows 事件檢視器並切換至全域應用程式記錄檔;您應該會看到一個專案,其中列出 「IISADMIN」 做為事件來源。

  6. 以滑鼠右鍵按一下事件,然後按一下 [ 屬性 ] 以檢視事件詳細資料。 您應該會看到 [描述] 窗格中顯示的「Hello World!」 訊息。

針對您的設定進行疑難排解

如果您的模組未如預期般編譯或無法正常運作,以下是您可以檢查的數個區域:

  • 請確定您已為匯出的函式指定 __stdcall ,或使用呼叫慣例來設定編譯 __stdcall (/Gz)

  • 請確定您已將正確的 RegisterModule 匯出新增至定義檔。

  • 請確定您已將定義檔新增至專案設定。 若要將檔案新增至專案設定,請完成下列步驟:

    1. 按一下 [專案] 功能表上的 [屬性] 。

    2. 展開樹狀檢視中的 [ 組態屬性 ] 節點,展開 [連結器] 節點,然後按一下 [ 輸入]。

    3. 針對 [模組定義檔案 ] 設定,請確定已列出您的定義檔。

另請參閱