目錄
基礎知識
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處理
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之前調用
-
public App()
-
{
-
//Monitor parent process exit and close subprocesses if parent process exits first
-
//This will at some point in the future becomes the default
-
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
-
-
var settings = new CefSettings()
-
{
-
AcceptLanguageList = "zh-CN",
-
//By default CefSharp will use an in-memory cache, you need to specify a Cache Folder to persist data
-
CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache")
-
};
-
-
//Example of setting a command line argument
-
//Enables WebRTC
-
settings.CefCommandLineArgs.Add( "enable-media-stream", "1");
-
-
//Perform dependency check to make sure all relevant resources are in our output directory.
-
Cef.Initialize(settings, performDependencyCheck: true, browserProcessHandler: null);
-
}
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());
有關更詳細的例子 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?
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