演练:创建托管 Web Core 应用程序

本演练演示如何创建使用 IIS 7 中提供的托管 Web 核心功能的 Windows 控制台应用程序。

通过 IIS 7 中的托管 Web 核心功能,可以创建一个加载 IIS 核心实例的应用程序,这是 IIS 提供的基本 Web 应用程序和内容服务功能。 有关托管 Web 核心的详细信息,请参阅 托管 Web 核心 API 参考

必须为应用程序提供遵循 ApplicationHost.config 文件格式的配置文件。 但是,不应使用实际ApplicationHost.config文件,因为它可能包含与网站设置冲突的设置。 有关如何为应用程序创建配置文件的详细信息,请参阅 演练:为托管 Web Core 创建配置文件

本演练演示以下任务:

  • 为应用程序创建 C++ 项目。

  • 为应用程序添加 C++ 代码。

  • 编译和测试应用程序。

  • 排查使用应用程序时出现的错误。

先决条件

需要以下软件才能完成示例中的步骤:

  • IIS 7。

注意

虽然必须在安装了 IIS 7 的计算机上运行托管 Web Core 应用程序,但不必在安装了 IIS 7 的计算机上编译示例应用程序。 可以在不同版本的 Windows 上编译应用程序,然后将应用程序复制到安装了 IIS 7 的计算机。

  • Visual Studio 2005。

注意

也可以使用 Visual Studio .NET 2003 或更早版本,但演练步骤可能并不相同。

创建托管 Web Core 应用程序

在本演练的这一部分,你将为应用程序创建一个 C++ 控制台应用程序项目。

为应用程序创建 C++ 项目

  1. 启动 Visual Studio 2005。

  2. 验证全局选项是否具有 SDK 包含文件的所有正确路径:

    1. “工具” 菜单上,单击 “选项”

      “选项”对话框将打开。

    2. 在树视图中展开 “项目和解决方案 ”节点,然后单击“ VC++ 目录”。

    3. “显示目录” 框中,选择“ 包括文件”。

    4. 验证是否已列出 SDK 的安装路径(包括文件)。 如果未列出路径,请单击“ 新建行 ”图标,然后添加安装 SDK 包含文件的路径。

    5. 单击 “确定”

  3. 创建新的 C++ 项目:

    1. “文件” 菜单上,指向 “新建” ,然后单击 “项目”

      “新建项目” 对话框随即打开。

    2. 在“ 项目类型 ”窗格中,展开 “Visual C++ ”节点,然后单击“ Win32”。

    3. “模板 ”窗格中,单击“ Win32 项目”。

    4. 在“ 名称 ”框中,键入 “HostedWebTest”。

    5. 在“ 位置 ”框中,键入项目的路径。

    6. 单击 “确定”

      Win32 应用程序向导随即打开。

    7. 单击“应用程序设置”。

    8. 在“ 应用程序类型”下,单击“ 控制台应用程序”。

    9. 单击“完成”。

      Visual Studio 将打开 HostWebTest.cpp 项目。

  4. 使用 __stdcall (/Gz) 调用约定将项目配置为进行编译:

    1. 在“ 项目 ”菜单上,单击“ HostedWebTest 属性”。

    2. 在树视图中展开 “配置属性” 节点,展开 C/C++ 节点,然后单击“ 高级”。

    3. “配置 ”框中,选择“ 所有配置”

    4. 在“ 调用约定 ”框中,选择 __stdcall (/Gz)

    5. 单击 “确定”

为应用程序添加代码

本部分介绍如何将自动添加到 C++ 文件的代码替换为将运行托管 Web Core 的代码。

注意

本示例在 Inetsrv 文件夹中查找名为 HostedWebTest.config 的文件。 可以修改路径和文件名,但必须提供有效的配置文件。 有关如何为应用程序创建配置文件的详细信息,请参阅 演练:为托管 Web Core 创建配置文件

为应用程序添加 C++ 代码

  1. 打开 HostedWebTest.cpp 文件(如果尚未打开),然后删除所有现有的 C++ 代码。

  2. 将以下 C++ 代码复制到 文件中:

    #include "stdafx.h"
    #include <windows.h>
    #include <stdio.h>
    #include <conio.h>
    #include <hwebcore.h>
    
    // NOTE: Set the project's calling convention to "__stdcall (/Gz)".
    
    HRESULT _cdecl _tmain(int argc, _TCHAR* argv[])
    {
        // Create a handle for the Web core DLL.
        HINSTANCE hDLL;
    
        // Specify the HRESULT for returning errors.
        HRESULT hr = S_OK;
    
        // Create arrays to hold paths.
        WCHAR wszInetPath[MAX_PATH];
        WCHAR wszDllPath[MAX_PATH];
        WCHAR wszCfgPath[MAX_PATH];
    
        // Retrieve the path of the Inetsrv folder.
        DWORD nSize = ::ExpandEnvironmentStringsW(
            L"%windir%\\system32\\inetsrv",wszInetPath,MAX_PATH);
    
        // Exit if the path of the Inetsrv folder cannot be determined.
        if (nSize == 0)
        {
            // Retrieve the last error.
            hr = HRESULT_FROM_WIN32(GetLastError());
            // Return an error status to the console.
            printf("Could not determine the path to the Inetsrv folder.\n");
            printf("Error: 0x%x\n",hr);
            // Return an error from the application and exit.
            return hr;
        }
    
        // Append the Web core DLL name to the Inetsrv path.
        wcscpy_s(wszDllPath,MAX_PATH-1,wszInetPath);
        wcscat_s(wszDllPath,MAX_PATH-1,L"\\");
        wcscat_s(wszDllPath,MAX_PATH-1,WEB_CORE_DLL_NAME);
    
        // Append the config file name to the Inetsrv path.
        wcscpy_s(wszCfgPath,MAX_PATH-1,wszInetPath);
        wcscat_s(wszCfgPath,MAX_PATH-1,L"\\HostedWebTest.config");
    
        // Create a pointer to WebCoreActivate.
        PFN_WEB_CORE_ACTIVATE pfnWebCoreActivate = NULL;
    
        // Create a pointer to WebCoreShutdown.
        PFN_WEB_CORE_SHUTDOWN pfnWebCoreShutdown = NULL;
    
        // Load the Web core DLL.
        hDLL = ::LoadLibraryW(wszDllPath);
    
        // Test whether the Web core DLL was loaded successfully.
        if (hDLL == NULL)
        {
            // Retrieve the last error.
            hr = HRESULT_FROM_WIN32(GetLastError());
            // Return an error status to the console.
            printf("Could not load DLL.\n");
            printf("Error: 0x%x\n",hr);
        }
        else
        {
            // Return a success status to the console.
            printf("DLL loaded successfully.\n");
            // Retrieve the address for "WebCoreActivate".
            pfnWebCoreActivate = (PFN_WEB_CORE_ACTIVATE)GetProcAddress(
                hDLL,"WebCoreActivate");
            // Test for an error.
            if (pfnWebCoreActivate==NULL)
            {
                // Retrieve the last error.
                hr = HRESULT_FROM_WIN32(GetLastError());
                // Return an error status to the console.
                printf("Could not resolve WebCoreActivate.\n");
                printf("Error: 0x%x\n",hr);
            }
            else
            {
                // Return a success status to the console.
                printf("WebCoreActivate successfully resolved.\n");
                // Retrieve the address for "WebCoreShutdown".
                pfnWebCoreShutdown = (PFN_WEB_CORE_SHUTDOWN)GetProcAddress(
                    hDLL,"WebCoreShutdown");
                // Test for an error.
                if (pfnWebCoreShutdown==NULL)
                {
                    // Retrieve the last error.
                    hr = HRESULT_FROM_WIN32(GetLastError());
                    // Return an error status to the console.
                    printf("Could not resolve WebCoreShutdown.\n");
                    printf("Error: 0x%x\n",hr);
                }
                else
                {
                    // Return a success status to the console.
                    printf("WebCoreShutdown successfully resolved.\n");
                    // Return an activation status to the console.
                    printf("Activating the Web core...\n");
                    // Activate the Web core.
                    hr = pfnWebCoreActivate(wszCfgPath,L"",L"TestWebCore");
                    // Test for an error.
                    if (FAILED(hr))
                    {
                        // Return an error status to the console.
                        printf("WebCoreActivate failed.\n");
                        printf("Error: 0x%x\n",hr);
                    }
                    else
                    {
                        // Return a success status to the console.
                        printf("WebCoreActivate was successful.\n");
                        // Prompt the user to continue.
                        printf("Press any key to continue...\n");
                        // Wait for a key press.
                        int iKeyPress = _getch();
                        // Return a shutdown status to the console.
                        printf("Shutting down the Web core...\n");
                        // Shut down the Web core.
                        hr = pfnWebCoreShutdown(0L);
                        // Test for an error.
                        if (FAILED(hr))
                        {
                            // Return an error status to the console.
                            printf("WebCoreShutdown failed.\n");
                            printf("Error: 0x%x\n",hr);
                        }
                        else
                        {
                            // Return a success status to the console.
                            printf("WebCoreShutdown was successful.\n");
                        }
                    }
                }
            }
            // Release the DLL.
            FreeLibrary(hDLL);
        }    
        // Return the application status.
        return hr;
    }
    
  3. 保存 HostedWebTest.cpp 文件。

编译和测试应用程序

创建并保存 C++ 文件后,下一步是编译和测试应用程序。

注意

如果未在安装了 IIS 7 的计算机上编译应用程序,则必须将HostedWebTest.exe文件复制到安装了 IIS 7 的计算机,然后才能测试该应用程序。

编译和测试应用程序

  1. 编译应用程序:

    1. 在“生成”菜单中,单击“生成解决方案”。

    2. 验证 Visual Studio 是否未返回任何错误或警告。 如果看到任何错误或警告,则必须在测试项目之前解决这些问题。

  2. 打开 Windows 资源管理器,找到创建 C++ 项目时指定的文件夹。

    根据生成选项,应在项目的默认文件夹中看到名为 DebugRelease 的文件夹。

  3. “调试”“发布 ”文件夹中,找到名为 HostedWebTest.exe 的文件。

  4. 验证配置文件是否在应用程序的相应文件夹中。 例如,本演练前面列出的代码示例旨在使用位于 Inetsrv 文件夹中的名为 HostedWebTest.config 的文件。

  5. 打开命令提示符窗口,将目录更改为HostedWebTest.exe文件所在的路径。

  6. 键入 HostedWebTest 并按 Enter 启动应用程序。

  7. 应会看到来自应用程序的输出,如下所示:

    DLL loaded successfully.
    WebCoreActivate successfully resolved.
    WebCoreShutdown successfully resolved.
    Activating the Web core...
    WebCoreActivate was successful.
    Press any key to continue...
    
  8. 最小化命令提示符窗口,而无需按键盘上的任何键。

  9. 根据配置设置,可以打开 Web 浏览器并浏览到配置文件中定义的网站。

  10. 浏览完网站后,返回到命令提示符窗口,然后按空格键。

  11. 应会看到来自应用程序的输出,如下所示:

    Shutting down the Web core...
    WebCoreShutdown was successful.
    

排查错误

如果应用程序未加载,或在运行时返回错误,以下步骤将帮助你诊断可能遇到的一些错误。

排查应用程序中的错误

  • 如果应用程序返回以下错误:

    Could not load DLL.
    Error: 0x8007007e
    

    这是ERROR_MOD_NOT_FOUND状态。 此错误指示无法找到Hwebcore.dll文件。 如果未安装 IIS,则会发生此错误。

  • 如果应用程序返回以下错误:

    DLL loaded successfully.
    WebCoreActivate successfully resolved.
    WebCoreShutdown successfully resolved.
    Activating the Web core...
    WebCoreActivate failed.
    Error: 0x8007000d
    

    这是ERROR_INVALID_DATA状态。 此错误表示配置文件无法定位或包含错误。 你应该在 Windows 事件查看器中查找其他错误说明。

  • 如果应用程序返回以下错误:

    DLL loaded successfully.
    WebCoreActivate successfully resolved.
    WebCoreShutdown successfully resolved.
    Activating the Web core...
    WebCoreActivate failed.
    Error: 0x800700b7
    

    这是ERROR_ALREADY_EXISTS状态。 此错误表示配置文件已加载,但它包含重复信息。 例如,你可能已定义多个应用程序池,或者可能创建了重复的网站绑定。 应检查 Windows 事件查看器以获取其他错误说明。

  • 如果应用程序加载成功,但在浏览应用程序托管的网站时收到 HTTP 404 错误,则应检查应用程序创建的 IIS 日志,以获取 404 子状态代码。 下面是你可能会看到的一些子状态代码:

    • 404.3“被 Mime 映射拒绝”- 此子状态代码指示未正确配置所请求资源的 MIME 类型。 例如,如果浏览到文件扩展名为 .txt 的文件,并且尚未将该扩展名添加到配置文件中的 MIME 映射,则会遇到此代码。

    • 404.4“无处理程序”- 此子状态代码指示尚未为请求的资源配置处理程序。 例如,如果浏览到文件扩展名为 .htm 的文件,并且尚未将静态文件处理程序添加到配置文件,则会遇到此代码。

    • 404.7“文件扩展名被拒绝”- 此子状态代码指示文件扩展名已被请求筛选阻止。 例如,如果浏览到文件扩展名为 .gif 的文件,并且请求筛选已配置为拒绝访问具有该扩展名的文件,则会遇到此代码。

      其中每个错误都表示应用程序配置文件中的设置存在问题。 有关详细信息,请参阅 演练:为托管 Web 核心创建配置文件

另请参阅