CefSharp中文幫助文檔

来源:https://www.cnblogs.com/88223100/archive/2022/04/25/CefSharp_Chinese_Help_Documentation.html
-Advertisement-
Play Games

在開發過程中經常需要在程式中嵌入瀏覽器控制項用於訪問網頁,Visual Studio中自帶了一個webbrowser控制項,但無奈這個控制項是調用用戶電腦上的IE瀏覽器來實現的,如果用戶裝的是低版本IE(比如Win7的IE8)很多新的網頁標準就無法得到支持,這時使用CefSharp來替代webbrowse... ...


目錄


1、基礎知識

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操作

6、 資源清理

6.1 瀏覽器本身處理
6.2 需要關閉瀏覽器負載程式時操作

7、 擴展功能

8、 常見錯誤

8.1 下載CefSharp master zip code文件編譯報錯
8.2 無法創建新的堆棧防護頁面
8.3 結束瀏覽器後,CefSharp.BrowserSubprocess.exe進行無法結束

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

9.1 如何使用.NET 調用 JavaScript方法?
9.2 如何獲取 Javascript 方法返回的結果?
9.3 如何暴露.NET類,提供給Javascript?
9.4 為什麼我得到一個錯誤有關“無法載入文件或程式集 CefSharp.Core.dll ”或它的一個依賴。指定的模塊找不到。“當試圖運行基於我CefSharp的應用程式?它編譯成功,但不運行?它運行我的開發機器上,雖然拋出一個異常,當我把它複製到另一臺電腦?
9.5 為什麼當我將 ChromiumWebBrowser 添加到我的應用程式時,Visual Studio WPF設計器不起作用?
9.6 如何在目標應用程式中包含Visual Studio C ++ 2012/2013可再發行組件?
9.7 如何重寫 Javascript 的 window.alert 事件和相似的?
9.8 CefSharp3二進位程式在哪裡?
9.9 Windows XP/2003支持?
9.10 當我重新發佈使用CefSharp的應用程式時,需要包括什麼文件?
9.11 構建過程不能複製CEF文件
9.12 為什麼 IndexedDB 返回 QuotaExceededError?
9.13 在C#中如何處理Javascript事件?
9.14 如何實現 WinForms 拖放?

10、 參考網址

11、 其他


1、基礎知識

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.2 cefSharp 伺服器運行要求

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

1.3 cefsharp設置網頁接受語言AcceptLanguage

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

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

1.4 cef設置userAgent

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

2、配置管理

2.1、CommandLine配置

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

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

3、請求流程處理

3.1 讀取網頁源代碼

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

async void browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)  
{  
    Log.WriteLog("browser_FrameLoadEnd:" + e.Url);  

    var result = await browser.GetSourceAsync();  
}  

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

 var task = browser.GetSourceAsync();  
 task.Wait();  
 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類如下:

public class TestImageFilter : IResponseFilter  
    {  
        public event Action<byte[]> NotifyData;  
        private int contentLength = 0;  
        private List<byte> dataAll = new List<byte>();  

        public void SetContentLength(int contentLength)  
        {  
            this.contentLength = contentLength;  
        }  

        public FilterStatus Filter(System.IO.Stream dataIn, out long dataInRead, System.IO.Stream dataOut, out long dataOutWritten)  
        {  
            try  
            {  
                if (dataIn == null)  
                {  
                    dataInRead = 0;  
                    dataOutWritten = 0;  

                    return FilterStatus.Done;  
                }  

                dataInRead = dataIn.Length;  
                dataOutWritten = Math.Min(dataInRead, dataOut.Length);  

                dataIn.CopyTo(dataOut);  
                dataIn.Seek(0, SeekOrigin.Begin);  
                byte[] bs = new byte[dataIn.Length];  
                dataIn.Read(bs, 0, bs.Length);  
                dataAll.AddRange(bs);  

                if (dataAll.Count == this.contentLength)  
                {  
                    // 通過這裡進行通知  
                    NotifyData(dataAll.ToArray());  

                    return FilterStatus.Done;  
                }  
                else if (dataAll.Count < this.contentLength)  
                {  
                    dataInRead = dataIn.Length;  
                    dataOutWritten = dataIn.Length;  

                    return FilterStatus.NeedMoreData;  
                }  
                else  
                {  
                    return FilterStatus.Error;  
                }  
            }  
            catch (Exception ex)  
            {  
                dataInRead = dataIn.Length;  
                dataOutWritten = dataIn.Length;  

                return FilterStatus.Done;  
            }  
        }  

        public bool InitFilter()  
        {  
            return true;  
        }  
    }  

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


        bool IRequestHandler.OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)  
        {  
            //NOTE: You cannot modify the response, only the request  
            // You can now access the headers  
            //var headers = response.ResponseHeaders;  
            try  
            {  
                var content_length = int.Parse(response.ResponseHeaders["Content-Length"]);  
                if (this.filter != null)  
                {  
                    this.filter.SetContentLength(content_length);  
                }  
            }  
            catch { }  
            return false;  
        }  

        private TestImageFilter filter = null;  
        public event Action<byte[]> NotifyData;  

        IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)  
        {  
            var url = new Uri(request.Url);  
            if (url.AbsoluteUri.Contains("http://test.test.com/somehead?"))  
            {  
                this.filter = new TestImageFilter();  
                filter.NotifyData += filter_NotifyData;  

                return filter;  
            }  

            return null;  
        }  

        void filter_NotifyData(byte[] data)  
        {  
            if (NotifyData != null)  
            {  
                NotifyData(data);  
            }  
        }  

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

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

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

public class FilterManager
    {
        private static Dictionary<string, IResponseFilter> dataList = new Dictionary<string, IResponseFilter>();

        public static IResponseFilter CreateFilter(string guid)
        {
            lock (dataList)
            {
                var filter = new TestImageFilter();
                dataList.Add(guid, filter);

                return filter;
            }
        }

        public static IResponseFilter GetFileter(string guid)
        {
            lock (dataList)
            {
                return dataList[guid];
            }
        }
    }

TestFilter類,對流進行合併

public class TestImageFilter : IResponseFilter
    {
        public List<byte> dataAll = new List<byte>();

        public FilterStatus Filter(System.IO.Stream dataIn, out long dataInRead, System.IO.Stream dataOut, out long dataOutWritten)
        {
            try
            {
                if (dataIn == null || dataIn.Length == 0)
                {
                    dataInRead = 0;
                    dataOutWritten = 0;

                    return FilterStatus.Done;
                }

                dataInRead = dataIn.Length;
                dataOutWritten = Math.Min(dataInRead, dataOut.Length);

                dataIn.CopyTo(dataOut);
                dataIn.Seek(0, SeekOrigin.Begin);
                byte[] bs = new byte[dataIn.Length];
                dataIn.Read(bs, 0, bs.Length);
                dataAll.AddRange(bs);

                dataInRead = dataIn.Length;
                dataOutWritten = dataIn.Length;

                return FilterStatus.NeedMoreData;
            }
            catch (Exception ex)
            {
                dataInRead = dataIn.Length;
                dataOutWritten = dataIn.Length;

                return FilterStatus.Done;
            }
        }

        public bool InitFilter()
        {
            return true;
        }
    }

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

public class RequestHandler : IRequestHandler
    {
        // 略去代碼 ...

        public event Action<byte[]> NotifyMsg;

        IResponseFilter IRequestHandler.GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
        {
            var url = new Uri(request.Url);
            if (url.AbsoluteUri.Contains("https://res.wx.qq.com/zh_CN/htmledition/v2/css/base/base2e4e03.css"))
            {
                var filter = FilterManager.CreateFilter(request.Identifier.ToString());

                return filter;
            }

            return null;
        }

        void filter_NotifyData(byte[] data)
        {
            if (NotifyMsg != null)
            {
                NotifyMsg(data);
            }
        }

        void IRequestHandler.OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
        {
            if (request.Url.Contains("https://res.wx.qq.com/zh_CN/htmledition/v2/css/base/base2e4e03.css"))
            {
                var filter = FilterManager.GetFileter(request.Identifier.ToString()) as TestImageFilter;

                filter_NotifyData(filter.dataAll.ToArray());
            }
        }
    }

4、Cookie處理

4.1 設置cookie

var cookieManager = CefSharp.Cef.GetGlobalCookieManager();  
await cookieManager.SetCookieAsync("http://" + domain, new CefSharp.Cookie()  
{  
    Domain = domain,  
    Name = name,  
    Value = value,  
    Expires = DateTime.MinValue  
}); 

4.2 讀取cookie

建立Cookie讀取對象,繼承介面 ICookieVisitor

    public class CookieVisitor : CefSharp.ICookieVisitor  
    {  
        public event Action<CefSharp.Cookie> SendCookie;  
        public bool Visit(CefSharp.Cookie cookie, int count, int total, ref bool deleteCookie)  
        {  
            deleteCookie = false;  
            if (SendCookie != null)  
            {  
                SendCookie(cookie);  
            }  
  
            return true;  
        }  
    }  

在browser事件中進行處理

private void browser_FrameLoadEnd(object sender, CefSharp.FrameLoadEndEventArgs e)  
{  
    var cookieManager = CefSharp.Cef.GetGlobalCookieManager();  
  
    CookieVisitor visitor = new CookieVisitor();  
    visitor.SendCookie += visitor_SendCookie;  
    cookieManager.VisitAllCookies(visitor);  
}  

/// 回調事件

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

5、Js處理

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

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

5.2 其他Frame操作

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

5.3 js回調,C#方法

參見本文檔:9.3

6、資源清理

6.1 瀏覽器本身處理

static ChromiumWebBrowser()  
{  
    if (CefSharpSettings.ShutdownOnExit)  
    {  
        Application.ApplicationExit += OnApplicationExit;  
    }  
}  
  
private static void OnApplicationExit(object sender, EventArgs e)  
{  
    Cef.Shutdown();  
}  

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

try  
{  
    browser.CloseDevTools();  
    browser.GetBrowser().CloseBrowser(true);  
}  
catch { }   
  
try  
{  
    if (browser != null)  
    {  
        browser.Dispose();  
        Cef.Shutdown();  
    }  
}  
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方法?

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

var script = string.Format("document.body.style.background = '{0}'", colors[color_index++]);if (color_index >= colors.Length)  
{  
    color_index = 0;  
}  
  
browser.GetMainFrame().ExecuteJavaScriptAsync(script);  
什麼時候可以開始執行 Javascript

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

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

browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();

public class RenderProcessMessageHandler : IRenderProcessMessageHandler
{
  // Wait for the underlying `Javascript Context` to be created, this is only called for the main frame.
  // If the page has no javascript, no context will be created.
  void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
  {
    const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";

    frame.ExecuteJavaScriptAsync(script);
  }
}

//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
browser.LoadingStateChanged += (sender, args) =>
{
  //Wait for the Page to finish loading
  if (args.IsLoading == false)
  {
    browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");
  }
}

//Wait for the MainFrame to finish loading
browser.FrameLoadEnd += (sender, args) =>
{
  //Wait for the MainFrame to finish loading
  if(args.Frame.IsMain)
  {
    args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
  }
};

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

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

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

// Get Document Height  
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);
  
task.ContinueWith(t =>  
{  
    if (!t.IsFaulted)  
    {  
        var response = t.Result;  
        EvaluateJavaScriptResult = response.Success ? (response.Result ?? "null") : response.Message;  
    }  
}, 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中的匹配版本存在)的內容:
#對於VC ++ 2012(86)
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x86\Microsoft.VC110.CRT
#對於VC ++ 2012(64)
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\redist\x64\Microsoft.VC110.CRT
#對於VC ++ 2013(86)
C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\x86\Microsoft.VC120.CRT
#對於VC ++ 2013(64)
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 再發行

一個新的選項是 JetBrainsNuget.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。

請註意: 平臺目標

使用這些包時,必須 選擇 x86x64 。 如果您選擇 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:

// On Win7 this will create a directory in AppData.
var cache = System.IO.Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData), System.IO.Path.Combine("MyApplication","cache"));
if (!System.IO.Directory.Exists (cache))
    System.IO.Directory.CreateDirectory (cache);

// Set the CachePath during initialization.
var settings = new CefSettings(){CachePath = cache};
Cef.Initialize (settings);

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

public class BoundObject
{
    public void OnFrameLoadEnd (object sender, FrameLoadEndEventArgs e)
    {
      if(e.Frame.IsMain)
      {
        browser.ExecuteScriptAsync(@"
          document.body.onmouseup = function()
          {
            bound.onSelected(window.getSelection().toString());
          }
        ");
      }
    }

    public void OnSelected(string selected)
    {
        MessageBox.Show("The user selected some text [" + selected + "]");
    }
}

// ...

// After your ChromiumWebBrowser has been instantiated (for WPF directly after `InitializeComponent();` in the control constructor).
var obj = new BoundObject();
browser.RegisterJsObject("bound", obj);
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、其他

                                                   文檔僅供參考,錯誤之處望修改,或指正

本文來自博客園,作者:古道輕風,轉載請註明原文鏈接:https://www.cnblogs.com/88223100/p/CefSharp_Chinese_Help_Documentation.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.開發環境 新建一個工程-配置jdk版本-配置maven 2.創建maven工程 修改打包方式為jar 導入依賴: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" x ...
  • 在前後端分離的項目中後端返回的格式一定要友好,不然會對前端的開發人員帶來很多的工作量。那麼SpringBoot如何做到統一的後端返回格式呢?今天我們一起來看看。 為什麼要對SpringBoot返回統一的標準格式 在預設情況下,SpringBoot的返回格式常見的有三種: 返回String @GetM ...
  • Python基礎知識 今天給大家分享一些Python的基礎知識,想要蓋好大房子,不把地基打扎實打牢怎麼行呢?所以,今天咱們就來學習基礎知識, 這樣後期學習Python的時候才能更容易掌握,更輕鬆的學會Python的使用。別跟我說你都學過了,看完再告訴我… 一、編程基礎 1.基本的輸入輸出: prin ...
  • 最近一個粉絲說,他面試了4個公司,有三個公司問他:“Spring Boot 中自動裝配機制的原理” 他回答了,感覺沒回答錯誤,但是怎麼就沒給offer呢? 對於這個問題,看看普通人和高手該如何回答。 普通人: 嗯… Spring Boot裡面的自動裝配,就是@EnableAutoConfigurat ...
  • 首發地址:day01-從一個基礎的socket服務說起 教程說明:C++高性能網路服務保姆級教程 本節目的 實現一個基於socket的echo服務端和客戶端 服務端監聽流程 第一步:使用socket函數創建套接字 在linux中,一切都是文件,所有文件都有一個int類型的編號,稱為文件描述符。服務端 ...
  • 前言 好想玩點不一樣的,感覺平常的已經不能吸引大家了。想了又想,我今天給大家分享如何給人像添加口罩吧。畢竟最近疫情那麼 嚴重,也只能玩玩這個了,大家千萬別亂跑啊。 效果展示 數據集展示 數據集來源:使用了開源數據集FaceMask_CelebA github地址:https://github.com ...
  • 前言 許多社區類平臺都具備點贊功能,應運而生的就是自動點贊器,今天用Python寫一款點贊機器人,最簡單易理解的核心邏輯。全 文涉及的偽代碼,使用 Python 編寫,由於是偽代碼的原因,不懂Python,你也能看懂。 一、簡介 1.適用場景 本次點贊機器人,主要面向電腦上的 Web 站點,不涉及 ...
  • 作者:血夜之末 來源:www.cnblogs.com/Tiancheng-Duan/p/16002433.html 一、背景 一轉眼,又到了金三銀四的跳槽 & 求職季。 在 IT 行業,跳槽就離不開一個詞,那就是外包。 可以說,每一位 IT 人都接觸過外包,甚至參與其中。而多數IT職場萌新,都面臨著 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...