在開發過程中經常需要在程式中嵌入瀏覽器控制項用於訪問網頁,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、配置管理
3、請求流程處理
3.1 讀取網頁源代碼
3.2 獲取頁面中的指定文件內容(.jpg,.js等)
3.3 過濾某些頁面內容,例如圖片或某些文字
3.4 文件進一步獲取,獲取完整內容
3.5 文件進一步獲取,獲取完整內容(優化,Content-Length不一致)
4、 Cookie處理
5、 Js處理
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!
- 如何使用.NET 調用 JavaScript方法?
- 如何獲取 Javascript 方法返回的結果呢?
- 如何暴露.NET類,提供給Javascript?
- “無法載入文件或程式集
CefSharp.Core.dll
”或它的一個依賴。 - 為什麼當我將 ChromiumWebBrowser 添加到我的應用程式時,Visual Studio WPF設計器不起作用?
- 如何在目標應用程式中包含Visual Studio C ++ 2012/2013可再發行組件?
- 如何重寫 Javascript 的
window.alert
事件和相似的? - CefSharp3二進位程式在哪裡?
- Windows XP/2003支持?
- 當我重新發佈使用CefSharp的應用程式時,需要包括什麼文件?
- 構建過程不能複製CEF文件
- 為什麼 IndexedDB 返回 QuotaExceededError?
- 在C#中如何處理Javascript事件?
- 如何實現 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());
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?
4. 為什麼我得到一個錯誤有關“無法載入文件或程式集 CefSharp.Core.dll
”或它的一個依賴。指定的模塊找不到。“當試圖運行基於我CefSharp的應用程式?它編譯成功,但不運行?它運行我的開發機器上,雖然拋出一個異常,當我把它複製到另一臺電腦?
這是一個常見的錯誤,通常是以下之一
- VC++ 2012/2013 可重新分發包*是為了在非開發者機器上運行CefSharp所必需的。有關詳細信息,請參閱下麵的FAQ#6。 您可以將所需的dll作為應用程式的一部分。
- 執行文件夾中不存在所有依賴關係。
CefSharp
包括非托管
的dll和資源,這些文件通過安裝Nuget
包時包含在項目中的兩個.props
文件複製到執行文件夾。 請參閱下麵所需的文件列表,確保所需的文件存在。 - 你通過安裝程式打包應用程式進行發佈,並且不會在目標電腦上運行。 預設情況下,安裝程式不包括
非托管
資源,您需要手動添加它們。 對於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 再發行
一個新的選項是 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:
// 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