如何从CefSharp 3打开本机浏览器中的链接

Aha*_*lik 5 .net c# wpf cefsharp

我需要在CefSharp 3的本机浏览器中打开一个链接.我需要在CefSharp 3的chrome浏览器中运行整个应用程序,除了表单.当我单击表单的链接按钮(例如 - 注册按钮.它有一个指向注册表单的链接)我需要在本机浏览器中打开此链接(例如 - Internet Explorer).

我们能在CefSharp中实现这一目标吗?

我搜索了谷歌以及堆栈溢出.但无法找到解决方案.

提前致谢.

Aha*_*lik 8

正如holroy所建议的那样,我在CefSharp.Example包中的RequestHandler类中实现了OnBeforeNavigation()方法.

这是工作代码,

 bool IRequestHandler.OnBeforeBrowse(IWebBrowser browserControl,
 IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
         {
             // If the url is Google open Default browser
             if (request.Url.Equals("http://google.com/"))
             {
                 // Open Google in Default browser 
                 System.Diagnostics.Process.Start("http://google.com/");
                 return true;
             }else
             {
                 // Url except Google open in CefSharp's Chromium browser
                 return false;
             }
         }
Run Code Online (Sandbox Code Playgroud)

我希望这将有助于其他人.

谢谢,


Mur*_*nat 5

首先,您需要创建一个自定义BrowserRequestHandler类,例如:

public class BrowserRequestHandler : IRequestHandler
{
    public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
    {
        // Open in Default browser
        if (!request.Url.StartsWith("file:"))
        {
            System.Diagnostics.Process.Start(request.Url);
            return true;
        }
        return false;
    }

    public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl,
        WindowOpenDisposition targetDisposition, bool userGesture)
    {
        return false;
    }

    public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl,
        ISslInfo sslInfo, IRequestCallback callback)
    {
        callback.Dispose();
        return false;
    }

    public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath)
    {
        throw new Exception("Plugin crashed!");
    }

    public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request,
        IRequestCallback callback)
    {
        return CefReturnValue.Continue;
    }

    public bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port,
        string realm, string scheme, IAuthCallback callback)
    {
        callback.Dispose();
        return false;
    }

    public bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port,
        X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
    {
        callback.Dispose();
        return false;
    }

    public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status)
    {
        throw new Exception("Browser render process is terminated!");
    }

    public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize,
        IRequestCallback callback)
    {
        callback.Dispose();
        return false;
    }

    public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response,
        ref string newUrl)
    {
        var url = newUrl;
        newUrl = url;
    }

    public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url)
    {
        return url.StartsWith("mailto");
    }

    public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser)
    {

    }

    public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
    {
        return false;
    }

    public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request,
        IResponse response)
    {
        return null;
    }

    public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request,
        IResponse response, UrlRequestStatus status, long receivedContentLength)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码的重要部分是:

public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
{
    // Open in Default browser
    if (!request.Url.StartsWith("file:"))
    {
        System.Diagnostics.Process.Start(request.Url);
        return true;
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我在 CEF 中打开本地保存的 HTML 文件,如果这些本地保存的 HTML 文件有外部链接,它们将在默认浏览器中打开。

现在您创建了 custom BrowserRequestHandler,您需要将其分配给浏览器。

如果您使用的是 MVVM,则可以BrowserRequestHandler在模型中创建一个并将其分配给RequestHandler浏览器控件的依赖项属性。但就我而言,存在计时问题,因为我在动态打开选项卡时有几个浏览器实例,并且浏览器打开速度不够快并抛出错误。

所以第二个选项是使用交互命名空间设置一个 Loaded 事件,如下所示:

<wpf:ChromiumWebBrowser Address="{Binding Html, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="ChromiumWebBrowser">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding BrowserLoadedCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</wpf:ChromiumWebBrowser>
Run Code Online (Sandbox Code Playgroud)

在此之后,您可以在视图模型中获取浏览器(或在管理器类中执行此操作),并将其设置RequestHandler为您的自定义,BrowserRequestHandler如下所示:

browser.RequestHandler = new BrowserRequestHandler();
Run Code Online (Sandbox Code Playgroud)

  • 通过从 DefaultRequestHandler 派生 BrowserRequestHandler,您可以跳过编写除 OnBeforeBrowse() {...} 方法之外的所有内容。它将提供所有样板 (2认同)