1. hg clone代码回来后,还要下载对应的cef dll .  从http://xilium.bitbucket.org/cefglue/ 选择对应的.

  然后把dll和resource目录里的内容都考到debug目录里才能运行.

2.不能使用 Enable the Visual Studio hosting process 来运行. 因为还会启动2个进程. 这两个进程是相同的exe只是命令行不同, 如果使用了 hosting process ,那么就不能启动另外两个进程.

调试的时候把所有的项目类型从framework 2.0 3.5 统一到4.0 调试断点才管用.

由于chrome是多进程运行, 有时候分不清楚代码是在哪个进程中运行, 所以断点很难下.

建议用Windbg 打开exe 并且 Debug child processes also ,来调试. 代码里用Console.WriteLine message的形式来看是否执行到.

3. Js 于Clr 交互:

  可以为window注册一个external:  

 private ClrObjectAv8Handler m_extantHandler =new JavaScriptExtMethod();
protected override void OnContextCreated(CefBrowser browser, CefFrame frame, CefV8Context context)
{
      var global = context.GetGlobal(); 6      var extent = CefV8Value.CreateObject(null);      global.SetValue("external", extent, CefV8PropertyAttribute.None);
     AddMethodToJSObject(this.m_extantHandler, extent);
}
//用反射的把所有公共方法注册到js object
public static void AddMethodToJSObject(CefV8Handler hendlerObj, CefV8Value extent)
{
Type t = hendlerObj.GetType();
var functions = t.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly); foreach (var m in functions)
{
string funName =m.Name; extent.SetValue(funName, CefV8Value.CreateFunction(m.Name, hendlerObj), CefV8PropertyAttribute.None); } }

  

JavaScriptExtMethod 继承CefV8Handler 重载方法Execute. 
   protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
{ exception = null;
try
{
List<object> paras = V8ValueClrMap.ConvertToClrParameters(arguments);
Type t = this.GetType(); var function = t.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod |
BindingFlags.IgnoreCase | BindingFlags.DeclaredOnly);
if (function != null)
{
var objRst = function.Invoke(this, paras.Count == ? null : paras.ToArray());
if (objRst is CefV8Handler)
{
returnValue = CefV8Value.CreateObject(null);
AddMethodToJSObject(objRst as CefV8Handler, returnValue);
}
else
{ returnValue = V8ValueClrMap.ConvertToV8Value(objRst);
}
}
else
{
exception = "Method no find:"+name;
returnValue = CefV8Value.CreateString("");
var message3 = CefProcessMessage.Create("Exception");
message3.Arguments.SetString(, exception);
var success2 = Browser.SendProcessMessage(CefProcessId.Browser, message3); return true;
}
return true;
}
catch (Exception ee)
{
returnValue = CefV8Value.CreateString("");
exception = ee.Message; returnValue = CefV8Value.CreateString("");
var message3 = CefProcessMessage.Create("Exception");
message3.Arguments.SetString(, ee.ToString());
var success2 = Browser.SendProcessMessage(CefProcessId.Browser, message3); return true;
} }

再实现一个V8Value与Clr的对应.

 public class V8ValueClrMap
{
public static List<object> ConvertToClrParameters(CefV8Value[] arguments)
{
List<object> rtn = new List<object>();
if (arguments == null || arguments.Length == )
{
return rtn;
}
foreach (var v in arguments)
{
rtn.Add(GetClrValue(v));
}
return rtn;
}
public static object GetClrValue(CefV8Value v)
{
if (v.IsArray)
{
int length = v.GetArrayLength();
object[] objs = new object[length];
for (int i = ; i < length; i++)
{
var value = v.GetValue(i);
objs[i] = GetClrValue(value);
}
return objs;
} if (v.IsBool ) return v.GetBoolValue(); if (v.IsDate) return v.GetDateValue();
if (v.IsInt) return v.GetIntValue(); if (v.IsDouble) return v.GetDoubleValue(); if (v.IsFunction){
throw new NotSupportedException("IsFunction");
} if (v.IsNull) return null;
if (v.IsObject)
{
//throw new NotSupportedException("IsObject");
var map = v.GetUserData() as Clr2V8ValueWrapper;
if (map != null)
return map.ClrObject;
return null;
}
if (v.IsString) return v.GetStringValue();
if (v.IsUInt) return v.GetUIntValue();
if (v.IsUndefined) return null;
if (v.IsUserCreated)
{
throw new NotSupportedException("IsUserCreated");
}
throw new NotSupportedException("??"); } public static CefV8Value ConvertToV8Value(object o)
{
if (o == null) return CefV8Value.CreateUndefined();
if (o is bool) return CefV8Value.CreateBool((bool)o);
if (o is DateTime) return CefV8Value.CreateDate((DateTime)o);
if (o is double) return CefV8Value.CreateDouble((double)o);
if (o is int) return CefV8Value.CreateInt((int)o);
if (o is string) return CefV8Value.CreateString((string)o);
if (o is uint) return CefV8Value.CreateUInt((uint)o);
if (o is Array)
{
var a=(Array)o;
var rtn = CefV8Value.CreateArray(a.Length);
for(int i=;i<a.Length;i++)
{
rtn.SetValue(i,ConvertToV8Value(a.GetValue(i)));
}
return rtn;
}
if (o is System.Collections.IList)
{
var a = (System.Collections.IList)o;
var rtn = CefV8Value.CreateArray(a.Count);
for (int i = ; i < a.Count; i++)
{
rtn.SetValue(i, ConvertToV8Value(a[i]));
}
return rtn;
}
throw new NotSupportedException("??");
}
}
然后就可以在js里调用JavaScriptExtMethod的方法: window.external.SomeMethod();

C# 里调用Js方法, 推荐使用发Message 到Render进程, 然后render进程执行完后再发消息给browser进程的方法.这样才能方便的捕获到js里的异常和返回值.

render进程:
 protected override bool OnProcessMessageReceived(CefBrowser browser, CefProcessId sourceProcess, CefProcessMessage message)
{
if (message.Name == "ExecuteJavaScript")
{
string code = message.Arguments.GetString();
var context = browser.GetMainFrame().V8Context;
context.Enter();
try
{
var global = context.GetGlobal();
var evalFunc = global.GetValue("eval");
CefV8Value arg0 = CefV8Value.CreateString(code); var rtn = evalFunc.ExecuteFunctionWithContext(context, evalFunc,
new CefV8Value[] { arg0 });
if (evalFunc.HasException)
{
var exception = evalFunc.GetException();
var message3 = CefProcessMessage.Create("Exception");
var arguments = message3.Arguments;
arguments.SetString(, exception.Message + " At Line" + exception.LineNumber);
var success2 = browser.SendProcessMessage(CefProcessId.Browser, message3); }
else
{
var message3 = CefProcessMessage.Create("JavascriptExecutedResult");
var arguments = message3.Arguments;
arguments.SetString(,rtn.GetStringValue());
var success2 = browser.SendProcessMessage(CefProcessId.Browser, message3);
}
} finally
{
context.Exit();
}
} return false;
}

4. javascript 的执行都在renderer 的Main Thread 上面.


CefGlue 学习杂记的更多相关文章

  1. [Flask]学习杂记--模板

    这个学习杂记主要不是分享经验,更多是记录下falsk的体验过程,以后做东西在深入研究,因为django之前用的时间比较长,所以很多概念都是一看而过,做个试验了解下flask的功能. flask中使用是 ...

  2. Java编程思想学习杂记(1-4章)

    程序流程控制 移位运算符 移位运算符面向的运算对象是二进制的位,可单独用它们处理整数类型.左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)." ...

  3. Thinking in Java学习杂记(5-6章)

    Java中可以通过访问控制符来控制访问权限.其中包含的类别有:public, "有好的"(无关键字), protected 以及 private.在C++中,访问指示符控制着它后面 ...

  4. Thinking in Java学习杂记(第7章)

    将一个方法调用同一个方法主体连接到一起就称为"绑定"(Binding).若在程序运行以前执行绑定,就叫做"早期绑定".而Java中绑定的所有方法都采用后期绑定技 ...

  5. Android学习杂记

    Jni接口学习资料: http://www.cnblogs.com/lsnproj/archive/2012/01/09/2317519.html classLoader和插件化: http://bl ...

  6. django 学习杂记

    django1.9 学习路径 http://python.usyiyi.cn/django/intro/tutorial02.html django 中url路径带参数,在view中应该如何处理 应该 ...

  7. Linux学习杂记

    近期一口气看完了韩顺平老师讲的Linux视频教程,自己也在学习的过程中做了些笔记,记载例如以下.希望帮助到一些喜欢研究Linux的同学.也算是在云端备份一下笔记吧.以免电脑出现不可控的因素而遗失自己的 ...

  8. Python学习杂记_4_分支和循环

    分支 和 循环 分支和循环这俩结构在各语言中都有着很重要的地位,当然我之前都没有学好,这里总结一下在Python学习中对这俩结构的认识. 分支结构 # 单分支 if 条件判断: 执行语句… # 双分支 ...

  9. Disruptor学习杂记

    慎入,有点乱,只是学习记录,disruptor_2.10.4 1.Disruptor对象有一个EventProcessorRepository对象   2.EventProcessorReposito ...

随机推荐

  1. js 回调函数 精析

      UpdateTime--2018年9月13日16点51分 1.什么是回调函数? 在JavaScript中,回调函数具体的定义为: 函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行 ...

  2. docker sshd image problem, session required pam_loginuid.so, cann't login

    在使用sshd docker 镜像时, 发现一个比较诡异的问题, 有些启动的容器可以连接, 有些不能. 例如 :  启动2个容器(这两个容器都有问题) :  [root@localhost ~]# d ...

  3. mybatis实战教程(mybatis in action)之四:实现关联数据的查询

    有了前面几章的基础,对一些简单的应用是可以处理的,但在实际项目中,经常是关联表的查询,比如最常见到的多对一,一对多等.这些查询是如何处理的呢,这一讲就讲这个问题.我们首先创建一个Article 这个表 ...

  4. 用ASP.NET/C#连接Access和SQL Server数据库

    连接Access 首先看一个例子代码片断:程序代码: ------------------------------------------------------------------------- ...

  5. 函数适配器bind2nd 、mem_fun_ref 源码分析、函数适配器应用举例

    一.适配器 三种类型的适配器: 容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) 函数适配器:函数适配器能够将仿函数 ...

  6. unity, editorWindow update计时

    对于editorWindow,Time.deltaTime不起作用,所以需用下面方法对update进行计时: public class myEditorWindow : EditorWindow{ p ...

  7. unity, 两个动画同时播

    法一,animationLayer. 处于不同animationLayer中的状态可以同时运行,即其中的动画可以同时播放. 所以通常一个角色至少需要用两个animationLayer,一个layer用 ...

  8. Redis(十四):主从复制

    当数据量变得庞大的时候,读写分离还是很有必要的.同时避免一个redis服务宕机,导致应用宕机的情况,我们启用sentinel(哨兵)服务,实现主从切换的功能. 主从复制 Redis 支持简单且易用的主 ...

  9. Intel 5 6 7 8系列芯片组介绍

    Intel 5 6 7 8系列芯片组介绍 Iknow.2015-11-05 22:40|知识编号:122257 操作步骤: [Inetl 5.6.7.8系列芯片组介绍] 芯片组是主板电路的核心.一定意 ...

  10. SCWS 中文分词

    SCWS 中文分词v1.2.3 开源免费的中文分词系统,PHP分词的上乘之选! 首页 下载 演示 文档 关于 服务&支持 API/HTTP 论坛 捐赠 源码@github 文档目录 SCWS- ...