处理程序的模块列表中有一个错误模块 "WebSocketModule"

Handler has a bad module "WebSocketModule" in its module list

在 64 位 Windows 10 和 IIS 10 上,我正在尝试开发和测试一个本机 HTTP 模块,该模块将充当一组特定脚本文件的 WebSockets 处理程序映射。这一切都是在以 RegisterModule() 开头的本机 C++ 中完成的。我没有使用 ASP.NET 的任何部分。

当我访问应该调用处理程序的 URL 时,我收到此响应:

HTTP Error 500.21 - Internal Server Error

Handler "QuadooWebSocket" has a bad module "WebSocketModule" in its module list

Detailed Error Information:

Module IIS Web Core
Notification ExecuteRequestHandler
Handler QuadooWebSocket
Error Code 0x8007000d

More Information:

IIS core does not recognize the module.

我使用 IIS 管理器设置处理程序映射,它在 applicationHost.config 文件中创建了一个条目。

        <handlers accessPolicy="Read, Script">
            <other_modules />
            <add name="QuadooWebSocket" path="*.qws" verb="*" modules="WebSocketModule" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" preCondition="bitness32" />
        </handlers>

在此之前,我使用 "Windows Features" 控制面板安装了对 WebSockets 的支持,它还在 applicationHost.config 文件中添加了一行。

        <globalModules>
            <other_modules />
            <add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" />
        </globalModules>

当我将 Visual Studio 附加到 w3wp.exe 时,我的代码中的 none 断点被解析。 RegisterModule() 未被调用。 DllMain() 甚至没有被调用。我的模块还实现了 IActiveScript,并且 IIS 确实为经典 ASP 请求加载了我的模块。

我的代码被构建到 32 位模块中,我在 applicationHost.config 文件中有 enable32BitAppOnWin64="true"。这适用于经典 ActiveScript/ASP 环境,但是当使用预期通过 RegisterModule() 导出加载的代码时,此设置是否也适用?如果这不是问题,那么是否需要其他步骤来为 WebSockets 启用本机 HTTP 模块?

谢谢!

时隔近两年,我决定用这几天的时间再次研究这个,终于成功了!

回答 32 位问题...是的,IIS 可以 运行 64 位 OS.

上的 32 位 WebSockets 处理程序

至于为什么它现在可以工作...我又重新运行 APPCMD.EXE,我在配置中四处寻找,直到它看起来像这样:

    <globalModules>
        ...
        <add name="WebSocketModule" image="%windir%\System32\inetsrv\iiswsock.dll" />
        <add name="WebSocketModule32" image="%windir%\SysWOW64\inetsrv\iiswsock.dll" />
        <add name="QuadooWebSocket" image="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" />
    </globalModules>

    <handlers accessPolicy="Read, Script">
        ...
        <add name="QuadooWebSocket" path="*.qws" verb="*" modules="WebSocketModule32" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" preCondition="bitness32" />
        ...
    </handlers>

    <location path="Default Web Site">
        <system.webServer>
            <handlers>
                <remove name="QuadooWebSocket" />
                <add name="QuadooWebSocket" path="*.qws" verb="*" modules="QuadooWebSocket" scriptProcessor="E:\dev\projects\trunk\target\debug\ActiveQuadoo.dll" resourceType="File" requireAccess="Script" preCondition="bitness32" />
            </handlers>
        </system.webServer>
    </location>

一个区别是我的处理程序现在已在 WebSocketModule32 模块中注册。

我可以在这里结束答案,但是在最终加载我的处理程序之后,在它真正正常工作之前我必须解决许多问题。我学到的一些知识可能对其他人有用。

由于我正在异步处理 WebSocket,因此我需要从 OnExecuteRequestHandler() return RQ_NOTIFICATION_PENDING。否则,IIS立即关闭连接。

切换到 WebSockets 时,这是我最终使用的顺序:

  1. 设置模块上下文。
  2. 将响应状态设置为 101。
  3. 加载我的脚本虚拟机。
  4. 写headers(例如Sec-WebSocket-Protocol)。
  5. Flush() 异步。

如果 Flush() 没有立即完成,那么它将通过调用 OnAsyncCompletion() 来完成。如果它确实立即完成,请使用将从 OnAsyncCompletion() 调用的相同代码路径并执行以下操作:

  1. 获取 IIS_WEBSOCKET 的命名上下文。
  2. 将上下文转换为 IWebSocketContext 指针。
  3. 启动异步 reader 循环。
  4. Return RQ_NOTIFICATION_PENDING.

收到来自 ReadFragment() 的关闭事件后,我调用 IndicateCompletion(RQ_NOTIFICATION_FINISH_REQUEST) 通知 IIS 我已完成连接。在我添加之前,IIS 没有调用我的处理程序的 CleanupStoredContext() 方法。