我們的 Windows 客戶端應用程式之一使用了一些 Microsoft Active Document / ActiveX 技術,要求用戶使用 IE 瀏覽器。應用程式顯示在 IE 瀏覽器選項卡中,但它在自己的行程中運行,而不是在 IE 瀏覽器選項卡行程中運行。它執行檔案編輯,有時需要向服務器應用程式發出 HTTP 請求以獲取額外資源。對于使用單點登錄產品(如 SiteMinder)的客戶,我們的客戶端應用程式可能需要發回一個或多個最初由服務器應用程式發送的 cookie(如 SMSESSION)。
在 IE 中,客戶端應用程式能夠通過使用 Microsoft 的SHDocVw::ShellWindows集合“找到”其 IE 選項卡,并且還能夠從該選項卡獲取 cookie。由于 IE 現在已于 2022 年 6 月停用,因此客戶正嘗試在 IE 模式下在 Edge 中運行該應用程式。SHDocVw::ShellWindows 集合似乎找不到在 Edge 上運行的這些“IE 模式”選項卡視窗。雖然我們可以使用EnumWindows定位客戶端視窗,僅僅擁有客戶端視窗的 HWND 似乎并不能讓我們獲取 cookie。因此,我們的客戶端應用程式對服務器的 HTTP 請求不會將 cookie 發送回服務器,服務器端的 Single Sign On 軟體會在回應中發送一個 Sign On HTML 頁面,而不是客戶端應用程式的檔案資源請求。
我試圖在下面創建一個示例程式來演示這個問題。使用 Visual Studio 構建此示例的一種方法是創建一個新的 C Win32 專案,選擇 Win32 控制臺應用程式,選中“為 MFC 添加通用頭檔案”復選框,完成,然后將下面的代碼粘貼到生成的起始源檔案中。
如果你打開 IE 并訪問http://microsoft.com,然后在 IE 打開的情況下運行程式,程式應該會找到 IE 瀏覽器視窗并顯示一些資訊,例如標題、pid 和 cookie 資訊。如果您隨后關閉 IE 并打開 Edge,并在 IE 模式下訪問http://microsoft.com (在 Edge 上啟用 IE 模式),程式似乎在以 IE 模式運行的 Edge 中找不到此選項卡。
是否需要進行任何其他設定才能讓 SHDocVw::ShellWindows 集合在 IE 模式選項卡中找到這些 Edge?或者,是否有其他方法能夠定位這些選項卡并獲取相關的 cookie,以便我們可以在下一個 HTTP 請求中將這些 cookie 回傳到服務器?謝謝。
#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;
}
uj5u.com熱心網友回復:
這是Edge IE 模式中的一個已知問題,并且是設計使然。視窗串列在 IE 模式下被禁用,因為否則它會與真正的 IE 共享狀態并導致其他問題。例如,初始化視窗串列的第一個行程將擁有它(IE 或 IE 模式),如果該行程關閉,則視窗串列將停止為其他行程作業。
解決此問題的唯一方法是啟用此策略 EnableGlobalWindowListInIEMode以允許 IE 模式視窗顯示在全域視窗串列中。此策略要求禁用 IE 作為獨立應用程式,并啟用 IE 模式。您可以參考此檔案禁用 IE 11。然后您可以通過編輯以下路徑中的注冊表來啟用此策略:
Registry Path: HKLM\Software\Policies\Microsoft\Internet Explorer\Main\EnterpriseMode
Value Name: EnableGlobalWindowListInIEMode
Value Type: REG_DWORD
Enabled Value: 1
Disabled Value: 0
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/521678.html
