cefsharp文檔

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

CefSharp中文幫助文檔javascript

 

目錄css

基礎知識html

1.1 cefsharp設置默認語言java

1.2 cefSharp 服務器運行要求c++

1.3 cefsharp設置網頁接受語言AcceptLanguagegit

1.4 cef設置userAgentgithub

二、配置管理web

2.一、CommandLine配置redis

三、請求流程處理瀏覽器

3.1 讀取網頁源代碼

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

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

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

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

四、Cookie處理

4.1 設置cookie

4.2 讀取cookie

五、Js處理

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

5.2 其餘Frame操做

5.3 js回調,C#方法

六、資源清理

6.1 瀏覽器自己處理

6.2 須要關閉瀏覽器負載程序時操做

七、擴展功能

八、常見錯誤

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

8.2 沒法建立新的堆棧防禦頁面

8.3 結束瀏覽器後,CefSharp.BrowserSubprocess.exe進行沒法結束

九、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 拖放?

十、參考網址

十一、其餘


基礎知識

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.一、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.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.  
    }

四、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.  
    }

五、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.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 { }

七、擴展功能

八、常見錯誤

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方法。

九、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

十、參考網址

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

十一、其餘

相關文章
相關標籤/搜索