c++ - 为 C++/CLI 中的所有请求向 WebBrowser 控件添加自定义 header ?

标签 c++ .net winforms c++-cli webbrowser-control

我正在尝试重现此 C# workaround在 C++/CLI 中,但它不起作用,这是我的代码:

private: System::Void WebBrowser1_Navigating(System::Object^ sender, System::Windows::Forms::WebBrowserNavigatingEventArgs^ e) {
    System::Diagnostics::Debug::WriteLine("Running...");
    auto activeXInstance = (SHDocVw::IWebBrowser2^) this->webBrowser1->GetType()->InvokeMember("ActiveXInstance", System::Reflection::BindingFlags::GetProperty | System::Reflection::BindingFlags::Instance | System::Reflection::BindingFlags::NonPublic, nullptr, this->webBrowser1, gcnew array<System::Object^>{});
    System::Diagnostics::Debug::WriteLine("I won't be printed.");
    auto setupEvents2 = (SHDocVw::DWebBrowserEvents2_Event^) activeXInstance;
    setupEvents2->BeforeNavigate2 += gcnew SHDocVw::DWebBrowserEvents2_BeforeNavigate2EventHandler(this, &MyForm::OnBeforeNavigate2);
}

private: System::Void OnBeforeNavigate2(System::Object^ pDisp, System::Object^% URL, System::Object^% Flags, System::Object^% TargetFrameName, System::Object^% PostData, System::Object^% Headers, bool %Cancel) {
    Headers = "User-Agent:Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19";
}

该方法会被执行,但是它会在第一行停止,接下来的行会被限制并且不会抛出任何异常。

最佳答案

这就是我在 C# 中解决问题的方法:

  • 添加了对 SHDocVw 的引用。您可以在引用管理器窗口的 COM 选项卡中找到 SHDocVw 作为“Microsoft Internet 控件”。
  • 浏览 about:blank *订阅了 DWebBrowserEvents2_EventBeforeNavigate2 事件。我从 webBrowser1.ActiveXInstance 获得了接口(interface)的实例。
  • BeforeNavigate2 事件处理程序中,我检查我感兴趣的 header 是否不存在于 header 中,以及 URL 是否为 http 或 https URL(例如是不是 javascript: url),如果请求不是针对 iframe,那么我会停止请求并发送带有新 header 的请求。

这是我预期的有效代码:

string additionalHeader = "User-Agent:Mozilla/5.0 (Windows Phone 10.0; Android 6.0.1; " +
    "Microsoft; Lumia 950 XL Dual SIM) AppleWebKit/537.36 (KHTML, like Gecko) " +
    "Chrome/52.0.2743.116 Mobile Safari/537.36 Edge/15.15063\r\n";
private void Form1_Load(object sender, EventArgs e)
{
    webBrowser1.ScriptErrorsSuppressed = true;
    webBrowser1.Navigate("about:blank", null, null, additionalHeader);
    var wbevents = (DWebBrowserEvents2_Event)webBrowser1.ActiveXInstance;
    wbevents.BeforeNavigate2 += Wbevents_BeforeNavigate2;
    webBrowser1.Navigate("http://google.com", null, null, additionalHeader);
}

private void Wbevents_BeforeNavigate2(object pDisp, ref object URL, ref object Flags,
    ref object TargetFrameName, ref object PostData, ref object Headers, ref bool Cancel)
{
    if (!$"{Headers}".Contains(additionalHeader) &&
        TargetFrameName == null &&
        $"{URL}".ToLower().StartsWith("http"))
    {
        Cancel = true;
        ((IWebBrowser2)pDisp).Stop();
        object headers = additionalHeader + $"{Headers}";
        object url = $"{URL}";
        object flags = null;
        object targetFrameName = $"{TargetFrameName}";
        ((IWebBrowser2)pDisp).Navigate2(ref url, ref flags,
            ref targetFrameName, ref PostData, ref headers);
    }
}

注意 1 - 导航不会在刷新时出现

浏览器中存在刷新功能/缺陷。当您刷新浏览器时,不会引发 Navigating 事件,这意味着在刷新时不会添加 header 。解决方法是禁用快捷方式和上下文菜单:

this.webBrowser1.WebBrowserShortcutsEnabled = false;
this.webBrowser1.IsWebBrowserContextMenuEnabled = false;

备注2——设置用户代理

因为这个问题是关于为用户代理添加 header 的,所以有一个更好的解决方案。您可以使用本文底部共享的解决方案:Winform Webbrowser being recognized as a mobile device .

即使您刷新浏览器,它也能正常工作。

关于c++ - 为 C++/CLI 中的所有请求向 WebBrowser 控件添加自定义 header ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57361094/

相关文章:

c++ - Windows C++ 管道创建黑色大终端窗口

c++ - 如何将 'this' 作为参数传递给另一个没有循环依赖的类构造函数?

c# - 使用提供程序 'RsaProtectedConfigurationProvider' 解密失败

c# - 如何用相同大小的按钮填充面板

c# - 外部化 WinForms 应用程序的翻译?

c# - 如何创建一个新类来检查图像类型?

c++ - 如何使这些 std::function 参数明确?

C++/WinRT : Can I await a single IAsyncAction handle from multiple coroutine calls?

c# - 如何修复 C# Windows 窗体应用程序中的窗体大小而不让用户更改其大小?

c# - 如何处理 "Unset"事件