cefsharp文檔


原文鏈接: https://github.com/cefsharp/CefSharp/wiki/CefSharp中文幫助文檔#a1_1

CefSharp中文幫助文檔

 

目錄

基礎知識

1.1 cefsharp設置默認語言

1.2 cefSharp 服務器運行要求

1.3 cefsharp設置網頁接受語言AcceptLanguage

1.4 cef設置userAgent

2、配置管理

2.1、CommandLine配置

3、請求流程處理

3.1 讀取網頁源代碼

3.2 獲取頁面中的指定文件內容(.jpg,.js等)

3.3 過濾某些頁面內容,例如圖片或某些文字

3.4 文件進一步獲取,獲取完整內容

3.5 文件進一步獲取,獲取完整內容(優化,Content-Length不一致)

4、Cookie處理

4.1 設置cookie

4.2 讀取cookie

5、Js處理

5.1 基本的同(異)步js操作

5.2 其他Frame操作

5.3 js回調,C#方法

6、資源清理

6.1 瀏覽器本身處理

6.2 需要關閉瀏覽器負載程序時操作

7、擴展功能

8、常見錯誤

8.1 下載CefSharp master zip code文件編譯報錯

8.2 無法創建新的堆棧防護頁面

8.3 結束瀏覽器后,CefSharp.BrowserSubprocess.exe進行無法結束

9、GitHub---Wiki(部分內容使用了Google進行翻譯)

快速FAQ TOC 英文版本

1. 如何使用.NET 調用 JavaScript方法?

2. 如何獲取 Javascript 方法返回的結果?

3. 如何暴露.NET類,提供給Javascript?

4. 為什么我得到一個錯誤有關“無法加載文件或程序集 CefSharp.Core.dll”或它的一個依賴。指定的模塊找不到。“當試圖運行基於我CefSharp的應用程序?它編譯成功,但不運行?它運行我的開發機器上,雖然拋出一個異常,當我把它復制到另一台計算機?

5. 為什么當我將 ChromiumWebBrowser 添加到我的應用程序時,Visual Studio WPF設計器不起作用?

6. 如何在目標應用程序中包含Visual Studio C ++ 2012/2013 再發布?

7. 如何重寫 Javascript 的 window.alert 事件和相似的事件?

8. CefSharp3二進制程序在哪里?

9. Windows XP/2003支持?

10. 當我重新發布使用CefSharp的應用程序時,需要包括什么文件?

11. 構建過程不能復制CEF文件

12. 為什么 IndexedDB 返回 QuotaExceededError?

13. 在C#中如何處理Javascript事件?

14. 如何實現 WinForms 拖放?

10、參考網址

11、其他


基礎知識

1.1 cefsharp設置默認語言

cefsharp是不錯的瀏覽器內核封裝版本之一,默認語言是en-US,這個一直困擾着項目,項目好多處需修改,后來經多次嘗試,才發現,原來設置默認語言這么簡單。 Loacal 屬性就是對CefSharp運行語言環境進行設置
var setting = new CefSharp.CefSettings();

// 設置語言
setting.Locale = "zh-CN";
CefSharp.Cef.Initialize(setting, true, false); 以上這段代碼一定要在new ChromiumWebBrowser之前調用

  1.  
    public App()
  2.  
    {
  3.  
    //Monitor parent process exit and close subprocesses if parent process exits first
  4.  
    //This will at some point in the future becomes the default
  5.  
    CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
  6.  
     
  7.  
    var settings = new CefSettings()
  8.  
    {
  9.  
    AcceptLanguageList = "zh-CN",
  10.  
    //By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
  11.  
    CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
  12.  
    };
  13.  
     
  14.  
    //Example of setting a command line argument
  15.  
    //Enables WebRTC
  16.  
    settings.CefCommandLineArgs.Add( "enable-media-stream", "1");
  17.  
     
  18.  
    //Perform dependency check to make sure all relevant resources are in our output directory.
  19.  
    Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
  20.  
    }

1.2 cefSharp 服務器運行要求

.net framework 環境和 vc++ 2013 runtime (x86/x64)

1.3 cefsharp設置網頁接受語言AcceptLanguage

什么是 cefsharp設置網頁接受語言AcceptLanguage
1.設置瀏覽器的請求控制器
 webView.RequestHandler = new RequestHandler(); 
2.新建RequestHandler類繼承IRequestHandler接口,實現方法OnBeforeResourceLoad,新版本如果又變更但是整體思路不變,內部處理是一致的請見諒。

  1.  
    public bool OnBeforeResourceLoad(IWebBrowser browser, IRequestResponse requestResponse)
  2.  
    {
  3.  
    IDictionary <string, string> headers = requestResponse.Request.GetHeaders();
  4.  
    headers.Add("Accept-Language", "zh,zh-cn,zh-tw");
  5.  
    requestResponse.Request.SetHeaders(headers);
  6.  
    return false;
  7.  
    }

1.4 cef設置userAgent

  1.  
    var setting = new CefSharp.CefSettings();
  2.  
    setting.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36";
  3.  
    CefSharp.Cef.Initialize(setting, true, false);

2、配置管理

2.1、CommandLine配置

所有配置:http://peter.sh/experiments/chromium-command-line-switches/
樣例參考:

  1.  
    var settings = new CefSettings();
  2.  
    settings.CefCommandLineArgs.Add("no-proxy-server", "1");
  3.  
    settings.CefCommandLineArgs.Add("proxy-server", "ProxyAddress");
  4.  
    Cef.Initialize(settings, true, true);

3、請求流程處理

3.1 讀取網頁源代碼

在頁面加載完成后處理, 依賴最低環境 4.5.2

  1.  
    async void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
  2.  
    {
  3.  
    Log.WriteLog("browser_FrameLoadEnd:" + e.Url);
  4.  
     
  5.  
    var result = await browser.GetSourceAsync();
  6.  
    }

如果想在4.0下環境操作需要使用。

  1.  
     var task = browser.GetSourceAsync();
  2.  
    task.Wait();
  3.  
    string content = task.Result;

3.2 獲取頁面中的指定文件內容(.jpg,.js等)

A.首先需要對ChromiumWebBrowser 的 IRequestHandler RequestHandler進行實現。
B.需要對 IRequestHandler 的IResponseFilter IRequestHandler.GetResourceResponseFilter 方法進行重寫。
C.需要寫一個類實現 IResponseFilter 接口。
D.然后就可用在IResponseFilter 的
FilterStatus Filter(Stream dataIn, out long dataInRead, Stream dataOut, out long dataOutWritten) 方法中,讀取指定內容的流了。

3.3 過濾某些頁面內容,例如圖片或某些文字

具體實現,參考 3.2 ,在最后的Filter方法中,對返回的dataOut不進行賦值或者,取到值,然后replace處理,返回其他數據,即可。

3.4 文件進一步獲取,獲取完整內容

說明:由於很多文件無法獲取到完整內容,再者具體文件內容在Filter里面進行了控制,而Fileter的內容依賴於IRequestHandler所以,外部只能操作Handler得到數據。 所以需要在,Filter和Hanlder類中,使用事件來傳遞具體的內容。代碼如下。 Filter類如下:

  1.  
    public class TestImageFilter : IResponseFilter
  2.  
    {
  3.  
    public event Action <byte[]> NotifyData;
  4.  
    private int contentLength = 0;
  5.  
    private List <byte> dataAll = new List<byte>();
  6.  
     
  7.  
    public void SetContentLength(int contentLength)
  8.  
    {
  9.  
    this.contentLength = contentLength;
  10.  
    }
  11.  
     
  12.  
    public FilterStatus Filter(System.IO.Stream dataIn, out long dataInRead, System.IO.Stream dataOut, out long dataOutWritten)
  13.  
    {
  14.  
    try
  15.  
    {
  16.  
    if (dataIn == null)
  17.  
    {
  18.  
    dataInRead = 0;
  19.  
    dataOutWritten = 0;
  20.  
     
  21.  
    return FilterStatus.Done;
  22.  
    }
  23.  
     
  24.  
    dataInRead = dataIn.Length;
  25.  
    dataOutWritten = Math.Min(dataInRead, dataOut.Length);
  26.  
     
  27.  
    dataIn.CopyTo(dataOut);
  28.  
    dataIn.Seek(0, SeekOrigin.Begin);
  29.  
    byte[] bs = new byte[dataIn.Length];
  30.  
    dataIn.Read(bs, 0, bs.Length);
  31.  
    dataAll.AddRange(bs);
  32.  
     
  33.  
    if (dataAll.Count == this.contentLength)
  34.  
    {
  35.  
    // 通過這里進行通知
  36.  
    NotifyData(dataAll.ToArray());
  37.  
     
  38.  
    return FilterStatus.Done;
  39.  
    }
  40.  
    else if (dataAll.Count < this.contentLength)
  41.  
    {
  42.  
    dataInRead = dataIn.Length;
  43.  
    dataOutWritten = dataIn.Length;
  44.  
     
  45.  
    return FilterStatus.NeedMoreData;
  46.  
    }
  47.  
    else
  48.  
    {
  49.  
    return FilterStatus.Error;
  50.  
    }
  51.  
    }
  52.  
    catch (Exception ex)
  53.  
    {
  54.  
    dataInRead = dataIn.Length;
  55.  
    dataOutWritten = dataIn.Length;
  56.  
     
  57.  
    return FilterStatus.Done;
  58.  
    }
  59.  
    }
  60.  
     
  61.  
    public bool InitFilter()
  62.  
    {
  63.  
    return true;
  64.  
    }
  65.  
    }

Filter類有了,那我們如何知道數據流的具體長度呢?這就需要在Handler的實現的其他方法里面尋找了。

  1.  
    bool IRequestHandler.OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
  2.  
    {
  3.  
    //NOTE: You cannot modify the response, only the request
  4.  
    // You can now access the headers
  5.  
    //var headers = response.ResponseHeaders;
  6.  
    try
  7.  
    {
  8.  
    var content_length = int.Parse(response.ResponseHeaders["Content-Length"]);
  9.  
    if (this.filter != null)
  10.  
    {
  11.  
    this.filter.SetContentLength(content_length);
  12.  
    }
  13.  
    }
  14.  
    catch { }
  15.  
    return false;
  16.  
    }
  17.  
     
  18.  
    private TestImageFilter filter = null;
  19.  
    public event Action <byte[]> NotifyData;
  20.  
     
  21.  
    IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
  22.  
    {
  23.  
    var url = new Uri(request.Url);
  24.  
    if (url.AbsoluteUri.Contains("http://test.test.com/somehead?"))
  25.  
    {
  26.  
    this.filter = new TestImageFilter();
  27.  
    filter.NotifyData += filter_NotifyData;
  28.  
     
  29.  
    return filter;
  30.  
    }
  31.  
     
  32.  
    return null;
  33.  
    }
  34.  
     
  35.  
    void filter_NotifyData(byte[] data)
  36.  
    {
  37.  
    if (NotifyData != null)
  38.  
    {
  39.  
    NotifyData(data);
  40.  
    }
  41.  
    }

此方法位IRequestHandler的一部分實現,通過實現函數:IRequestHandler.GetResourceResponseFilter得到資源文件的長度,然后長度傳入Filter,在Filter中控制從而得到整個數據的真正長度。

3.5 文件進一步獲取,獲取完整內容(優化,Content-Length不一致)

由於,部分站點,返回數據是分片了的,即:不能通過,Content-Length的長度來判斷,程序的流是否完成。
所以需要其他方式處理,即:單個http請求完成的時候,會調用Complete方法,所以可以在這里處理。
下面是測試代碼: Filter管理類

  1.  
    public class FilterManager
  2.  
    {
  3.  
    private static Dictionary <string, IResponseFilter> dataList = new Dictionary<string, IResponseFilter>();
  4.  
     
  5.  
    public static IResponseFilter CreateFilter(string guid)
  6.  
    {
  7.  
    lock (dataList)
  8.  
    {
  9.  
    var filter = new TestImageFilter();
  10.  
    dataList.Add(guid, filter);
  11.  
     
  12.  
    return filter;
  13.  
    }
  14.  
    }
  15.  
     
  16.  
    public static IResponseFilter GetFileter(string guid)
  17.  
    {
  18.  
    lock (dataList)
  19.  
    {
  20.  
    return dataList[guid];
  21.  
    }
  22.  
    }
  23.  
    }

TestFilter類,對流進行合並

  1.  
    public class TestImageFilter : IResponseFilter
  2.  
    {
  3.  
    public List <byte> dataAll = new List<byte>();
  4.  
     
  5.  
    public FilterStatus Filter(System.IO.Stream dataIn, out long dataInRead, System.IO.Stream dataOut, out long dataOutWritten)
  6.  
    {
  7.  
    try
  8.  
    {
  9.  
    if (dataIn == null || dataIn.Length == 0)
  10.  
    {
  11.  
    dataInRead = 0;
  12.  
    dataOutWritten = 0;
  13.  
     
  14.  
    return FilterStatus.Done;
  15.  
    }
  16.  
     
  17.  
    dataInRead = dataIn.Length;
  18.  
    dataOutWritten = Math.Min(dataInRead, dataOut.Length);
  19.  
     
  20.  
    dataIn.CopyTo(dataOut);
  21.  
    dataIn.Seek(0, SeekOrigin.Begin);
  22.  
    byte[] bs = new byte[dataIn.Length];
  23.  
    dataIn.Read(bs, 0, bs.Length);
  24.  
    dataAll.AddRange(bs);
  25.  
     
  26.  
    dataInRead = dataIn.Length;
  27.  
    dataOutWritten = dataIn.Length;
  28.  
     
  29.  
    return FilterStatus.NeedMoreData;
  30.  
    }
  31.  
    catch (Exception ex)
  32.  
    {
  33.  
    dataInRead = dataIn.Length;
  34.  
    dataOutWritten = dataIn.Length;
  35.  
     
  36.  
    return FilterStatus.Done;
  37.  
    }
  38.  
    }
  39.  
     
  40.  
    public bool InitFilter()
  41.  
    {
  42.  
    return true;
  43.  
    }
  44.  
    }

最后是部分的。IRequestHandler實現代碼

  1.  
    public class RequestHandler : IRequestHandler
  2.  
    {
  3.  
    // 略去代碼 ...
  4.  
     
  5.  
    public event Action <byte[]> NotifyMsg;
  6.  
     
  7.  
    IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
  8.  
    {
  9.  
    var url = new Uri(request.Url);
  10.  
    if (url.AbsoluteUri.Contains("https://res.wx.qq.com/zh_CN/htmledition/v2/css/base/base2e4e03.css"))
  11.  
    {
  12.  
    var filter = FilterManager.CreateFilter(request.Identifier.ToString());
  13.  
     
  14.  
    return filter;
  15.  
    }
  16.  
     
  17.  
    return null;
  18.  
    }
  19.  
     
  20.  
    void filter_NotifyData(byte[] data)
  21.  
    {
  22.  
    if (NotifyMsg != null)
  23.  
    {
  24.  
    NotifyMsg(data);
  25.  
    }
  26.  
    }
  27.  
     
  28.  
    void IRequestHandler.OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
  29.  
    {
  30.  
    if (request.Url.Contains("https://res.wx.qq.com/zh_CN/htmledition/v2/css/base/base2e4e03.css"))
  31.  
    {
  32.  
    var filter = FilterManager.GetFileter(request.Identifier.ToString()) as TestImageFilter;
  33.  
     
  34.  
    filter_NotifyData(filter.dataAll.ToArray());
  35.  
    }
  36.  
    }
  37.  
    }

4、Cookie處理

4.1 設置cookie

  1.  
    var cookieManager = CefSharp.Cef.GetGlobalCookieManager();
  2.  
    await cookieManager.SetCookieAsync("http://" + domain, new CefSharp.Cookie()
  3.  
    {
  4.  
    Domain = domain,
  5.  
    Name = name,
  6.  
    Value = value,
  7.  
    Expires = DateTime.MinValue
  8.  
    });

4.2 讀取cookie

建立Cookie讀取對象,繼承接口 ICookieVisitor

  1.  
    public class CookieVisitor : CefSharp.ICookieVisitor
  2.  
    {
  3.  
    public event Action <CefSharp.Cookie> SendCookie;
  4.  
    public bool Visit(CefSharp.Cookie cookie, int count, int total, ref bool deleteCookie)
  5.  
    {
  6.  
    deleteCookie = false;
  7.  
    if (SendCookie != null)
  8.  
    {
  9.  
    SendCookie(cookie);
  10.  
    }
  11.  
     
  12.  
    return true;
  13.  
    }
  14.  
    }

在browser事件中進行處理

  1.  
    private void browser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)
  2.  
    {
  3.  
    var cookieManager = CefSharp.Cef.GetGlobalCookieManager();
  4.  
     
  5.  
    CookieVisitor visitor = new CookieVisitor();
  6.  
    visitor.SendCookie += visitor_SendCookie;
  7.  
    cookieManager.VisitAllCookies(visitor);
  8.  
    }

/// 回調事件

  1.  
    private void visitor_SendCookie(CefSharp.Cookie obj)
  2.  
    {
  3.  
    cookies += obj.Domain.TrimStart('.') + "^" + obj.Name + "^" + obj.Value + "$";
  4.  
    }

5、Js處理

5.1 基本的同(異)步js操作

  1.  
    browser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("document.getElementById('testid').click();");
  2.  
    browser.GetBrowser().MainFrame.ExecuteJavaScriptAsync("document.getElementById('testid2').value='123'");

5.2 其他Frame操作

  1.  
    string script = "if(document.getElementById('img_out_10000')){ document.getElementById('img_out_10000').click(); }";
  2.  
    var list = browser.GetBrowser().GetFrameNames();
  3.  
    if (list.Count > 1)
  4.  
    {
  5.  
    browser.GetBrowser().GetFrame(list[1]).ExecuteJavaScriptAsync(script);
  6.  
    }

5.3 js回調,C#方法

參見本文檔:9.3

6、資源清理

6.1 瀏覽器本身處理

  1.  
    static ChromiumWebBrowser()
  2.  
    {
  3.  
    if (CefSharpSettings.ShutdownOnExit)
  4.  
    {
  5.  
    Application.ApplicationExit += OnApplicationExit;
  6.  
    }
  7.  
    }
  8.  
     
  9.  
    private static void OnApplicationExit(object sender, EventArgs e)
  10.  
    {
  11.  
    Cef.Shutdown();
  12.  
    }

6.2 需要關閉瀏覽器負載程序時操作

  1.  
    try
  2.  
    {
  3.  
    browser.CloseDevTools();
  4.  
    browser.GetBrowser().CloseBrowser(true);
  5.  
    }
  6.  
    catch { }
  7.  
     
  8.  
    try
  9.  
    {
  10.  
    if (browser != null)
  11.  
    {
  12.  
    browser.Dispose();
  13.  
    Cef.Shutdown();
  14.  
    }
  15.  
    }
  16.  
    catch { }

7、擴展功能

8、常見錯誤

8.1 下載CefSharp master zip code文件編譯報錯

下載地址:https://codeload.github.com/cefsharp/CefSharp/zip/master
錯誤提示:

由於編譯路徑存在中文導致。

8.2 無法創建新的堆棧防護頁面

可能是由於 進程“ CefSharp.BrowserSubprocess.exe ”沒有正常結束掉,一直占用內存增加,直到...

8.3 結束瀏覽器后,CefSharp.BrowserSubprocess.exe進行無法結束

需要確保,創建瀏覽器的線程和調用Cef.ShutDown();的線程確保在同一個線程中進行操作。 如果是主線程創建。關閉程序后BrowserSubprocess進程可以直接退出。 如果是非主線程,需要在創建瀏覽器,即:把瀏覽器綁定到控件的線程,調用shutdown方法。

9、GitHub---Wiki(部分內容使用了Google進行翻譯)

本文檔的大部分將被替換為新的 一般使用指南 - 必須閱讀!

快速FAQ TOC 英文版本

本FAQ〜10項。嘗試列出一些很酷的CefSharp特性和一些最常見的問題的的。

有關更多提示,請查看不斷增加的問題列表faq-able!

  1. 如何使用.NET 調用 JavaScript方法?
  2. 如何獲取 Javascript 方法返回的結果呢?
  3. 如何暴露.NET類,提供給Javascript?
  4. “無法加載文件或程序集 CefSharp.Core.dll ”或它的一個依賴。
  5. 為什么當我將 ChromiumWebBrowser 添加到我的應用程序時,Visual Studio WPF設計器不起作用?
  6. 如何在目標應用程序中包含Visual Studio C ++ 2012/2013可再發行組件?
  7. 如何重寫 Javascript 的 window.alert 事件和相似的?
  8. CefSharp3二進制程序在哪里?
  9. Windows XP/2003支持?
  10. 當我重新發布使用CefSharp的應用程序時,需要包括什么文件?
  11. 構建過程不能復制CEF文件
  12. 為什么 IndexedDB 返回 QuotaExceededError?
  13. 在C#中如何處理Javascript事件?
  14. 如何實現 WinForms 拖放?

1. 如何使用.NET 調用 JavaScript方法?

簡單代碼可能看起來像這樣:

  1.  
    var script = string.Format("document.body.style.background = '{0}'", colors[color_index++]);if (color_index >= colors.Length)
  2.  
    {
  3.  
    color_index = 0;
  4.  
    }
  5.  
     
  6.  
    browser.GetMainFrame().ExecuteJavaScriptAsync(script);

什么時候可以開始執行 Javascript ?

不幸的是加載DOM之前OnFrameLoadStart被調用,所以你需要使用如下之一:FrameLoadEnd / LoadingStateChanged / IRenderProcessMessageHandler.OnContextCreated。下面是幾個例子

不幸的是,在加載DOM之前調用 OnFrameLoadStart ,所以你需要使用下面的一個方法: FrameLoadEnd/LoadingStateChanged/IRenderProcessMessageHandler.OnContextCreated 。這里有幾個例子

  1.  
    browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();
  2.  
     
  3.  
    public class RenderProcessMessageHandler : IRenderProcessMessageHandler
  4.  
    {
  5.  
    // Wait for the underlying `Javascript Context` to be created, this is only called for the main frame.
  6.  
    // If the page has no javascript, no context will be created.
  7.  
    void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
  8.  
    {
  9.  
    const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";
  10.  
     
  11.  
    frame.ExecuteJavaScriptAsync(script);
  12.  
    }
  13.  
    }
  14.  
     
  15.  
    //Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
  16.  
    browser.LoadingStateChanged += (sender, args) =>
  17.  
    {
  18.  
    //Wait for the Page to finish loading
  19.  
    if (args.IsLoading == false)
  20.  
    {
  21.  
    browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");
  22.  
    }
  23.  
    }
  24.  
     
  25.  
    //Wait for the MainFrame to finish loading
  26.  
    browser.FrameLoadEnd += (sender, args) =>
  27.  
    {
  28.  
    //Wait for the MainFrame to finish loading
  29.  
    if(args.Frame.IsMain)
  30.  
    {
  31.  
    args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
  32.  
    }
  33.  
    };

注意:腳本是在 Frame 級別執行,永遠頁面至少有一個Frame( MainFrame )。 IWebBrowser.ExecuteScriptAsync 擴展方法是為了向后兼容,可以將其用作在主框架上執行 js 的快捷方式。

2. 如何獲取 Javascript 方法返回的結果?

如果需要評估返回值的代碼,使用 Task<JavascriptResponse> EvaluateScriptAsync(string script, TimeSpan? timeout) 方法。 JavaScript代碼是異步執行的,因此使用.NET Task 類返回一個響應,其中包含錯誤消息,結果和一個成功(bool)標志。

  1.  
    // Get Document Height
  2.  
    var task = frame.EvaluateScriptAsync("(function() { var body = document.body, html = document.documentElement; return Math.max( body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight ); })();", null);
  3.  
     
  4.  
    task.ContinueWith(t =>
  5.  
    {
  6.  
    if (!t.IsFaulted)
  7.  
    {
  8.  
    var response = t.Result;
  9.  
    EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message;
  10.  
    }
  11.  
    }, TaskScheduler.FromCurrentSynchronizationContext());

有關更詳細的例子 Gist

Notes

  • 腳本是在 Frame 級別執行,永遠頁面至少有一個Frame( MainFrame )
  • 只能返回一般的值(如int,bool,string等) - 不是您自己定義的復雜(用戶定義)類型。這是因為沒有(容易的)方式將隨機的JavaScript對象暴露給.NET World,至少不是今天。但是,一種可能的技術是,將要返回到.NET代碼的Javascript對象轉換為JSON對象,使用 JSON.toStringify() 方法轉化為JSON字符串,並將該字符串返回到您的.NET代碼。然后,您可以將該字符串解碼為一個類似JSON.net的.NET對象。有關更多信息,請參閱此MSDN鏈接。 (https://msdn.microsoft.com/library/cc836459(v=vs.94).aspx)

3. 如何暴露.NET類,提供給Javascript?

參考 般使用指南 - 如何公開.Net類

4. 為什么我得到一個錯誤有關“無法加載文件或程序集 CefSharp.Core.dll”或它的一個依賴。指定的模塊找不到。“當試圖運行基於我CefSharp的應用程序?它編譯成功,但不運行?它運行我的開發機器上,雖然拋出一個異常,當我把它復制到另一台計算機?

這是一個常見的錯誤,通常是以下之一

  1. VC++ 2012/2013 可重新分發包*是為了在非開發者機器上運行CefSharp所必需的。有關詳細信息,請參閱下面的FAQ#6。 您可以將所需的dll作為應用程序的一部分。
  2. 執行文件夾中不存在所有依賴關系。 CefSharp 包括 非托管 的dll和資源,這些文件通過安裝 Nuget 包時包含在項目中的兩個 .props 文件復制到執行文件夾。 請參閱下面所需的文件列表,確保所需的文件存在。
  3. 你通過安裝程序打包應用程序進行發布,並且不會在目標計算機上運行。 默認情況下,安裝程序不包括 非托管 資源,您需要手動添加它們。 對於 ClickOnce ,請參閱#1314其他用戶提出的一些指針和解決方案。

可以在這里找到所需文件的列表:Output files description (Redistribution)

注: 如果在 XAML 中初始化 WPF 控件時遇到 FileNotFoundException ,這也適用。

注2:如果從源代碼編譯(不推薦使用 Nuget 包),並注意到您不能再以debug模式構建,但是release構建工作正常,您可能需要修復Visual Studio版本。 這種情況發生在少數情況下,您將獲得如上所示,丟失的非托管.dll文件相同的提示信息。

5. 為什么當我將 ChromiumWebBrowser 添加到我的應用程序時,Visual Studio WPF設計器不起作用?

注 版本 57.0.0 增加了最小的設計器支持,有關詳細信息,請參見 https://github.com/cefsharp/CefSharp/pull/1989。

舊版本不支持 WPF 設計器,這是不幸的,CefSharp是用C++代碼編寫的,后者又引用了CEF DLLs 導致的結果。這種情況下,Visual Studio 設計器不能夠很好的支持。在論壇的主題將進一步解釋,並提供可能的解決方法。 我認為(不幸的是)最簡單的解決方法是接受一個事實,即支持並不容易,但是還有其他方法,如果你真的覺得你需要舊版本。

6. 如何在目標應用程序中包含Visual Studio C ++ 2012/2013 再發布

CefSharp 需要 VC ++運行時 。你必須安裝/包括這與你的應用程序的幾個選項:

  • 你可以在你希望運行 CefSharp 基於應用程序的每台計算機上安裝 VC++ 。一旦安裝更新就可以通過 Windows Update 進行管理。
  • 您可以設置在 Visual Studio C++ 再分發作為安裝程序的先決條件(即的ClickOnce或WiX的工具集)
  • 通過復制到您的項目在此文件夾(只有當你安裝了Visual Studio中的匹配版本存在)的內容:
  1.  
    #對於 VC ++ 2012(86)
  2.  
    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x86\Microsoft.VC110.CRT
  3.  
    #對於 VC ++ 2012(64)
  4.  
    C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x64\Microsoft.VC110.CRT
  5.  
    #對於 VC ++ 2013(86)
  6.  
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x86\Microsoft.VC120.CRT
  7.  
    #對於 VC ++ 2013(64)
  8.  
    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x64\Microsoft.VC120.CRT

隨着第三方法,你將不再需要為前提的 Visual C++ 2012/2013 運行時文件 安裝到客戶端。就目前的計划是留在VC2013官方CefSharp二進制版本。可行時,我們可能會切換到VC2015。如果你從源代碼構建自己的你部署的過程中必須與您構建環境。對於官方的 Nuget 版本的詳細信息請參見發布分支表

欲了解更多信息,請參閱重新分發 Visual C++ 文件。要下載,請訪問Visual Studio C++ 2012/2013 再發行

一個新的選項是 JetBrains 在 Nuget.org 上有一個Microsoft.VC120.CRT.JetBrains ,似乎包含相關文件,您仍然需要連接一些后期構建任務將其復制到您的bin文件夾。

注意 當從源代碼構建時,確保在部署到沒有安裝 Visual Studio 的機器時以 Release 模式進行編譯。 Visual C++ 使用一套不同的調試和發布版本的運行時庫。 Debug 運行時庫僅安裝有 Visual Studio 中。如果你使用他們已經建在釋放模式官方的 NuGet軟件包 ,您可以隨后建立在調試模式下您的應用程序,因為只有在 Visual C++ 項目需要在 Release 模式下進行編譯。

7. 如何重寫 Javascript 的 window.alert 事件和相似的事件?

ChromiumWebBrowser 控件提供了一個名為 JsDialogHandler 的屬性。 該屬性可以設置為一個類,可以用來覆蓋這些對話框的行為。

8. CefSharp3二進制程序在哪里?

CefSharp3被發布為 Nuget 包。 請參閱https://github.com/cefsharp/CefSharp/blob/master/README.md#nuget-packages 以獲取最新的穩定版本和預發行版本。

對於使用NuGet軟件包的一個非常簡單的示例項目,請參閱CefSharp.MinimalExample 存儲庫。 克隆它/下載源碼,如果你想要一個真正的小而簡單的例子,如何使用CefSharp3。

請注意: 平台目標

使用這些包時,必須 選擇 x86 或 x64 。 如果您選擇 AnyCPU ,NuGet magic將無法正常工作。_請參閱steps to configure your solution here

9. Windows XP/2003支持?

我們不再支持 Windows XP/2003 。官方的 Nuget 軟件包沒有在 Windows XP/2003 上進行測試。 您可能會喜歡使用目標為 VC++ 2013 的較新版本( VC++ 2012 packages 有一個已知問題)。(記住 CefSharp.Example.* 項目是使用 .Net 4.5 編譯的,所以如果你想使用提供的例子,你必須重新定位它們並相應地更新代碼)。

請不要創建與 Windows XP 相關的 新的 問題。 以下 https://github.com/cefsharp/CefSharp/wiki/Windows-XP-No-Longer-Supported Wiki 頁面可能很有用,可以由任何具有 GitHub 帳戶的人進行編輯,因此請隨時提供,您認為可能證明有用的任何信息。

10. 當我重新發布使用CefSharp的應用程序時,需要包括什么文件?

請參閱: Output files description (Redistribution)

11. 構建過程不能復制CEF文件

有時,編譯過程不能復制CEF文件,並且會在最終失敗之前重試多次。 即使應用程序關閉,CefSharp.BrowserSubprocess.exe 仍然運行時也會發生這種情況。 解決方案,使用任務管理器,手動殺死 CefSharp.BrowserSubprocess.exe 。

12. 為什么 IndexedDB 返回 QuotaExceededError?

使用IndexedDB時,必須將CefSettings CachePath設置為當前用戶具有寫入權限的目錄。 在大多數情況下,您可以使用這樣的代碼創建緩存目錄,並在Initialize() 期間將設置傳遞給Cef:

  1.  
    // On Win7 this will create a directory in AppData.
  2.  
    var cache = System.IO.Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), System.IO.Path.Combine("MyApplication","cache"));
  3.  
    if (!System.IO.Directory.Exists (cache))
  4.  
    System.IO.Directory.CreateDirectory (cache);
  5.  
     
  6.  
    // Set the CachePath during initialization.
  7.  
    var settings = new CefSettings(){CachePath = cache};
  8.  
    Cef.Initialize (settings);

13. 在C#中如何處理Javascript事件?

  1.  
    public class BoundObject
  2.  
    {
  3.  
    public void OnFrameLoadEnd (object sender, FrameLoadEndEventArgs e)
  4.  
    {
  5.  
    if(e.Frame.IsMain)
  6.  
    {
  7.  
    browser.ExecuteScriptAsync(@"
  8.  
    document.body.onmouseup = function()
  9.  
    {
  10.  
    bound.onSelected(window.getSelection().toString());
  11.  
    }
  12.  
    ");
  13.  
    }
  14.  
    }
  15.  
     
  16.  
    public void OnSelected(string selected)
  17.  
    {
  18.  
    MessageBox.Show("The user selected some text [" + selected + "]");
  19.  
    }
  20.  
    }
  21.  
     
  22.  
    // ...
  23.  
     
  24.  
    // After your ChromiumWebBrowser has been instantiated (for WPF directly after `InitializeComponent();` in the control constructor).
  25.  
    var obj = new BoundObject();
  26.  
    browser.RegisterJsObject("bound", obj);
  27.  
    browser.FrameLoadEnd += obj.OnFrameLoadEnd ;

請注意:

  • 在創建 ChromiumWebBrowser 實例之后,應該直接調用 RegisterJsObject
  • "bound" 將作為可在網頁上運行的任何JS腳本訪問的頂級對象創建的對象的名稱。 您可以使用任何您喜歡的,但確保它不與現有的JS對象沖突,並且名稱與C#和JS匹配。
  • 此示例使用 FrameLoadEnd 事件即時將JS代碼注入到網頁中。 如果您控制了網頁,可以將JS代碼添加到網頁中。
  • 我們使用單個字符串參數調用 OnSelected C#方法。 您可以使用任何數量的參數,也可以不使用任何參數,但都必須是原始類型。
  • 確保將復雜的JS對象轉換為字符串,或將其轉換為JSON。
  • 由於CefSharp將通過其名稱搜索 OnSelected 方法,請確保您的混淆器不會將該方法重命名為別的東西,否則將不會被執行。

14. 如何實現 WinForms 拖放?

一個可能的解決方案概述 https://github.com/cefsharp/CefSharp/issues/1593#issuecomment-304451518

10、參考網址

http://www.cnblogs.com/TianFang/p/4658151.html

11、其他


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM