You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SHDocVw::ShellWindows无法识别Edge IE模式标签窗口的解决方案咨询

问题描述

我们有一款基于Microsoft Active Document/ActiveX技术的Windows客户端应用,原本依赖IE浏览器运行——它在IE标签页中显示,但以独立进程运行,需要向服务器发起HTTP请求获取资源。对于使用SiteMinder等单点登录(SSO)产品的客户,应用必须回传服务器初始发送的SMSESSION等Cookie。

在IE环境中,客户端应用可以通过Microsoft的SHDocVw::ShellWindows集合找到对应的IE标签页并获取Cookie。但IE已于2022年6月退役,客户尝试在Edge的IE模式下运行该应用时,SHDocVw::ShellWindows集合无法识别这些Edge IE模式的标签窗口。虽然可以通过EnumWindows定位客户端窗口,但仅靠HWND无法获取Cookie,导致应用向服务器的HTTP请求未携带Cookie,服务器端SSO软件返回登录页面而非请求的文档资源。

演示问题的示例程序

使用Visual Studio构建步骤:创建C++ Win32控制台项目,勾选“添加MFC通用头文件”,完成后将以下代码粘贴到启动源文件中:

#include "stdafx.h"
#include "afxctl.h"
#import <mshtml.tlb>
#import <shdocvw.dll> 
#include "mshtml.h"

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    SHDocVw::IShellWindowsPtr m_spSHWinds;
    IDispatchPtr spDisp;
    IWebBrowser2Ptr m_webBrowser;
    char *pszLocName;
    char *pszTitle;
    char *pszCookie;
    HWND iehwnd;
    DWORD iepid;
    DWORD ietid;
    _bstr_t bStrLocname;
    _bstr_t bStrTitle;
    _bstr_t bStrCookie;
    DWORD rc;
    IHTMLDocument2 *pdoc2 = NULL;
    BSTR bptr;
    BSTR ck;
    char info[4096];
    int cntIEtabs = 0;

    CoInitialize(NULL);
    HRESULT hr = m_spSHWinds.CreateInstance(__uuidof(SHDocVw::ShellWindows));
    long nCount = m_spSHWinds->GetCount();

    for (long i = 0; i < nCount; i++)
    {
        _variant_t va(i, VT_I4);
        spDisp = m_spSHWinds->Item(va);
        SHDocVw::IWebBrowser2Ptr spBrowser(spDisp);
        if (spBrowser != NULL)
        {
            bStrLocname = spBrowser->GetLocationName();
            pszLocName = bStrLocname;
            spBrowser->get_Name(&bptr);
            bStrTitle = bptr;
            pszTitle = bStrTitle;

            try {
                iehwnd = (HWND)spBrowser->GetHWND();
            }
            catch (const _com_error &e) {
                // if GetHWND() fails
                continue;
            }

            ietid = GetWindowThreadProcessId(iehwnd, &iepid);

            // cookie stuff
            m_webBrowser = (IWebBrowser2Ptr)spBrowser;

            rc = m_webBrowser->get_Document(&spDisp);

            if (spDisp->QueryInterface(IID_IHTMLDocument2,
                (void**)&pdoc2) == S_OK)
            {
                pdoc2->get_cookie(&ck);
                bStrCookie = ck;
                pszCookie = bStrCookie;
                sprintf_s(info,
                    "LocationName: %s\n\n"
                    "PID: %d\n\n"
                    "Title: %s\n\n"
                    "Cookie string: %s",
                    pszLocName, iepid, pszTitle, pszCookie);

                MessageBox(NULL, CA2T(info), _T("Browser tab info:"), MB_OK);

                cntIEtabs++;
            }
        }
    }

    if (cntIEtabs == 0) {
        MessageBox(NULL, _T("No IE browser tabs found."), _T("Browser tab info:"), MB_OK);
    }

    return 0;
}

测试现象:打开IE访问http://microsoft.com并运行程序,可找到IE窗口并显示标题、PID、Cookie等信息;但关闭IE后,在Edge的IE模式下访问该网址,程序无法找到对应标签页。

咨询问题

  1. 是否需要额外配置让SHDocVw::ShellWindows识别Edge IE模式标签窗口?
  2. 有无其他方式定位这些标签页并获取关联Cookie,以在后续HTTP请求中回传给服务器?

解决方案

关于SHDocVw::ShellWindows识别Edge IE模式的配置

SHDocVw::ShellWindows集合无法直接识别Edge IE模式的标签窗口,这是因为Edge IE模式的标签进程是作为Edge的子进程运行,而非传统IE的独立进程,微软并未提供让SHDocVw兼容识别这些窗口的配置选项,因此这条路走不通。

替代方案获取Edge IE模式的Cookie

方案1:直接读取IE共享Cookie存储

Edge IE模式会复用传统IE的Cookie存储,你可以通过WinINet API直接读取目标域名的Cookie:

  • 使用InternetGetCookieExW函数,传入目标URL,需启用INTERNET_COOKIE_HTTPONLY标志以读取HTTPOnly类型的Cookie(SiteMinder的SMSESSION通常属于此类)。
  • 此方法无需定位标签页,直接获取系统中存储的对应域名Cookie,适合大多数场景。

示例代码片段:

#include <wininet.h>
#pragma comment(lib, "wininet.lib")

// 获取目标URL的Cookie
wchar_t cookieBuffer[4096] = {0};
DWORD bufferSize = sizeof(cookieBuffer) / sizeof(wchar_t);
BOOL result = InternetGetCookieExW(
    L"http://your-server-domain.com", 
    NULL, 
    cookieBuffer, 
    &bufferSize, 
    INTERNET_COOKIE_HTTPONLY, 
    NULL
);
if (result && bufferSize > 0) {
    // cookieBuffer中存储了目标域名的完整Cookie字符串
}

方案2:利用Edge WebDriver自动化获取

如果需要精准定位特定Edge IE模式标签页的Cookie,可以使用Edge WebDriver:

  1. 下载与Edge版本匹配的Edge WebDriver。
  2. 配置WebDriver以IE模式启动Edge,设置DesiredCapabilities参数:ie.edgechromium=true、ie.edgepath指定Edge安装路径。
  3. 通过WebDriver API获取当前标签页的Cookie集合,提取所需的SMSESSION等字段后传递给应用。

方案3:进程注入获取Trident引擎COM对象

Edge IE模式标签进程本质运行Trident引擎,可通过以下步骤获取Cookie:

  1. 通过EnumWindows找到Edge IE模式窗口,获取其进程ID(PID)。
  2. 使用进程注入技术(如CreateRemoteThread)将代码注入到目标进程。
  3. 在注入代码中,通过CoCreateInstance获取IHTMLDocument2对象,调用get_cookie方法读取Cookie。
  • 注意:此方法需处理进程权限、COM线程模型问题,实现复杂度高,且可能受Windows安全机制限制。

方案4:修改HTTP请求逻辑自动携带Cookie

如果应用使用WinINet/WinHTTP发起请求,可直接配置API使用系统默认浏览器会话:

  • 调用InternetOpen时指定INTERNET_OPEN_TYPE_PRECONFIG参数,让API自动复用Edge IE模式的Cookie会话。
  • 此方式发起的请求会自动携带对应域名的Cookie,无需手动获取和拼接,是最简便的适配方案。

内容的提问来源于stack exchange,提问作者John Carter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:02:21