tencent / injectfix Goto Github PK
View Code? Open in Web Editor NEWInjectFix is a hot-fix solution library for Unity
License: Other
InjectFix is a hot-fix solution library for Unity
License: Other
频率不高,大部分时间出现在生成补丁后注入时。Unity版本:2019.2.0f1
日志文件如下:
Editor.log
error.log
List types = Assembly.Load("Assembly-CSharp").GetTypes().ToList();
将上述types 设置为配置列表后,注入报空指针
Unhandled Exception:System.NullReferenceException: Object reference not set to an instance of an object
at IFix.CodeTranslator.checkILAndGetOffset (Mono.Cecil.MethodDefinition method, Mono.Collections.Generic.Collection1[T] instructions, System.Collections.Generic.Dictionary
2[TKey,TValue] ilOffset, System.Int32& stopPos) [0x0033c] in :0
Windows平台下执行Fix(Android)第三方库会报has an extra field of type in the player and thus can't be serialized这类错误,切换到Android执行后正确,然后在Android平台下执行Fix(IOS)会报 The type or namespace name 'iOS' does not exist in the namespace 'UnityEngine' (are you missing an assembly reference?)这类错,切换到iOS平台下后执行正确。请问Fix(Android)和Fix(iOS)必须要在对应平台下执行吗?
如果项目更新了,或者目录下Instruction.cs
内容丢失了,需要重新生成 exe,那如果保证能发布出来 Patch 跟现网的 dll 对应?
是否可以将ShuffleInstruction.cs
里的随机函数种子改为用户输入的一个密钥,根据该密钥生成唯一的Instruction.cs
内容
1.Whether IL2CPP mode hotfix is supported?
2.For the XCode project published by IL2CPP, does the *.so file support repair?
热更是不是不支持成员变量,就是成员变量的get和set,谢谢!
我看了一下说明,并没有什么特殊的限制,比如继承,泛型等.是否都完整的支持呢?
性能和Lua以及ILRunTime的优劣在那?
对于已经注入的工程,如何取消注入呢?
unity版本 2019.1.5f1 64位 PC平台
按照 《编辑器下体验热补丁》 操作后。
报错:
Exception: instruction magic not match, expect 1657824154692109704, but got 5634132482224155774
IFix.Core.PatchManager.Load (System.IO.Stream stream) (at :0)
Helloworld.Start () (at Assets/Helloworld/Helloworld.cs:25)
1:打开项目工程 点菜单 InjectFix->Inject
2:打开calculator patch注释 修改Add函数 保存
3:点击InjectFix->Fix 报错
看了FAQ说 生成Patch的dll 不能进行注入 不是很懂如果解决这个问题
测试用例比较少, 用xlua的测试用例测试了下
发现
泛型方法 public T Test1()
InvalidDataException: not support generic method: T Test1T
IFix.Editor.IFixEditor.GenPatch (System.String assembly, System.String assemblyCSharpPath, System.String corePath, System.String patchPath) (at Assets/IFix/Editor/ILFixEditor.cs:671)
IFix.Editor.IFixEditor.Patch () (at Assets/IFix/Editor/ILFixEditor.cs:722)
泛型类 public class GenericClass
NullReferenceException: Object reference not set to an instance of an object
IFix.Editor.IFixEditor.GetCecilTypeName (System.Type type) (at Assets/IFix/Editor/ILFixEditor.cs:391)
IFix.Editor.IFixEditor.writeMethods (System.IO.BinaryWriter writer, System.Collections.Generic.List`1 methods) (at Assets/IFix/Editor/ILFixEditor.cs:645)
IFix.Editor.IFixEditor.GenPatch (System.String assembly, System.String assemblyCSharpPath, System.String corePath, System.String patchPath) (at Assets/IFix/Editor/ILFixEditor.cs:691)
IFix.Editor.IFixEditor.Patch () (at Assets/IFix/Editor/ILFixEditor.cs:722)
public struct StructTest
public GameObject GetGo(int a, object b)
应该都还没支持?
xlua中的一开始的这个
int CALL_TIME = 100 * 1000 * 1000;
xlua的数据
Hotfix using:1740.7495
No Hotfix using:1509.3954
drop:0.132904878042475
IFix的
没有注入的时候, 比如 reimport之后
using:1300.0526 基本1400左右
只执行了Inject
using:2899.4215 基本就是2800左右
放入之前打的补丁 Assembly-xx.bytes
using:73007~88536.4775 基本80000 左右
这个差距感觉比想象中要大啊, 虽然都是windows下debug测试的,为什么xlua的差距没有那么大,这个差距这么大呢?
InterpretAttribute,ReverseWrapperAttribute 这2个标签的用处是什么呢?
按照案列文档操作,把patch移到了IFix/Resources文件夹下,运行Unity的时候报以下错误:
Exception: assembly may be not injected yet, cat find IFix.ILFixInterfaceBridge, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
IFix.Core.PatchManager.Load (System.IO.Stream stream) (at <918685c187314494a24e37379d310620>:0)
Helloworld.Start () (at Assets/Helloworld/Helloworld.cs:24)
请问下,这个标签是干嘛用的
//父类
public virtual void SetData(T data)
{
Init ();
_data = data;
}
//子类
[iFix.Patch]
public override void SetData (TopupConfig.topup data)
{
base.SetData (data);
Title.text = data.name;
}
这样子修复是有问题的。
生成时并没有报错,逻辑会在base.SetData (data);这句卡住,并且没有任何报错。
大佬可否增加一个提醒
另外向大佬请教下[IFix.CustomBridge]的具体用途,重点 谢谢大佬!!!
public interface IClass
{
void Hello(T input);
void Hello();
}
public class BasicClass : IClass
{
[Patch]
public void Hello(T input)
{
FLogger.Debug(FLogTag.Misc,"adsasasd");
}
public void Hello()
{
FLogger.Debug(FLogTag.Misc, "adsasasd");
}
}
public class Calculator<T> : BasicClass<T>
{
public T Sum(T a, T b)
{
//this should still return a+b // is it magic?
Hello(a);
Hello();
return a;
}
}
patch public void Hello() 没有问题,但是patch public void Hello(T input)的时候unity编辑器会报错 ArgumentNullException: Value cannot be null. Parameter name: value System.IO.BinaryWriter.Write (System.String value) (at <23c160f925be47d7a4fd083a3a62c920>:0) IFix.Editor.IFixEditor.writeMethods (System.IO.BinaryWriter writer, System.Collections.Generic.List`1[T] methods) (at Assets/IFix/Editor/ILFixEditor.cs:666) IFix.Editor.IFixEditor.GenPatch (System.String assembly, System.String assemblyCSharpPath, System.String corePath, System.String patchPath) (at Assets/IFix/Editor/ILFixEditor.cs:707) IFix.Editor.IFixEditor.Patch () (at Assets/IFix/Editor/ILFixEditor.cs:745)
例子:
at IFix.CodeTranslator
.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType)
[0x00e46] in <4869fd109e9d46d786c063346dae80a5>:0
UnityEngine.Debug:Log(Object)
IFix.Editor.IFixEditor:CallIFix(List`1) (at Assets/IFix/Editor/ILFixEditor.cs:133)
IFix.Editor.IFixEditor:InjectAssembly(String) (at Assets/IFix/Editor/ILFixEditor.cs:283)
IFix.Editor.IFixEditor:InjectAllAssemblys() (at Assets/IFix/Editor/ILFixEditor.cs:301)
IFix.Editor.IFixEditor:InjectAssemblys() (at Assets/IFix/Editor/ILFixEditor.cs:152)
不方便排查问题
发现InjectAssembly方法默认会去“./Library/ScriptAssemblies/”目录找dll,现有注入流程会提示找不到dll错误。对于预生成的dll,是否可以脱离unity出包流程,单独进行dll注入和生成补丁呢。
顺便求个官方交流群~
unity 2018.4.5 ,原先的标题和这个内容无关,另开一个,希望能解决,直接在HelloWorld项目中,添加下面的文件,即可重现错误。
Unity2018.4.5\Editor\Data\il2cpp\build 路径下的Mono.Cecil.dll ,Mono.Cecil.Mdb.dll,Mono.Cecil.Pdb.dll三个文件替换项目中的文件,问题依旧
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
public class Utils
{
public async Task<byte[]> ReadBinaryFileAsync(string filePath)
{
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Open, FileAccess.Read, FileShare.Read,
bufferSize: 4096, useAsync: true))
{
List byteSource = new List();
byte[] buffer = new byte[4096];
while (await sourceStream.ReadAsync(buffer, 0, buffer.Length) != 0)
{
byteSource.AddRange(buffer);
}
return byteSource.ToArray();
}
}
}
报错:
Patch Error:System.Exception: can not load generic method [LoadAsset] of UnityEngine.AssetBundle
补丁中的方法
[Patch]
private void TestABLoad(AssetBundle ab){
GameObject prefab=ab.LoadAsset 《GameObject》 ("testPrefab");
}
打包时候 Temp 文件夹里面的 UnityTempFileXXXX根据 AssemblyDefinition 分成了多个文件 请问怎么处理。
unity 2018.4.5
报错:这个报错在HelloWorld例子中也出现
Warning: read ./Library/ScriptAssemblies/Assembly-CSharp.dll with symbol fail
自己的项目中:
Unhandled Exception:System.Exception: XXX.Utils/d__4 is CompilerGenerated
at IFix.CodeTranslator.addExternType (Mono.Cecil.TypeReference type, Mono.Cecil.TypeReference contextType) [0x00056] in :0
at IFix.CodeTranslator.addExternMethod (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller) [0x000ba] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00123] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00f64] in :0
at IFix.CodeTranslator.addAnonymousCtor (Mono.Cecil.MethodDefinition ctor) [0x00060] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00deb] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00f64] in :0
at IFix.CodeTranslator.addAnonymousCtor (Mono.Cecil.MethodDefinition ctor) [0x00060] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00deb] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00f64] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00f64] in :0
at IFix.CodeTranslator.getMethodId (Mono.Cecil.MethodReference callee, Mono.Cecil.MethodDefinition caller, System.Boolean directCallVirtual, IFix.CodeTranslator+InjectType callerInjectType) [0x00f64] in :0
at IFix.CodeTranslator.processMethod (Mono.Cecil.MethodDefinition method) [0x00000] in :0
at IFix.CodeTranslator.Process (Mono.Cecil.AssemblyDefinition assembly, Mono.Cecil.AssemblyDefinition ilfixAassembly, IFix.GenerateConfigure configure, IFix.ProcessMode mode) [0x00190] in :0
at IFix.Program.Main (System.String[] args) [0x0016c] in :0
UnityEngine.Debug:LogError(Object)
IFix.Editor.IFixEditor:CallIFix(List`1) (at Assets/IFix/Editor/ILFixEditor.cs:140)
IFix.Editor.IFixEditor:InjectAssembly(String) (at Assets/IFix/Editor/ILFixEditor.cs:269)
IFix.Editor.IFixEditor:InjectAllAssemblys() (at Assets/IFix/Editor/ILFixEditor.cs:287)
IFix.Editor.IFixEditor:InjectAssemblys() (at Assets/IFix/Editor/ILFixEditor.cs:152)
配置文件
[Configure]
public class IFixConfig {
[IFix]
static IEnumerable<Type> ToProcess
{
get
{
return (from type in Assembly.Load("Assembly-CSharp").GetTypes()
where type.Namespace == "XXX"
select type).ToList();
}
}
}
XXX是我们自己的命名空间
打包unity ios xcode工程编译不通过,错误信息如图。大佬帮看下,是哪里的问题。
BuildLog.txt
首先很感激作者,能共享又一个优秀的FixBug手段,从XLua到InjectFix,辛苦了
我用InjectFix在自己建立的测试工程中测试:
1.HotFixTest.cs中 一个TestRun方法,只是UnityEngine.Debug.Log一个字符串,并返回这个字符串
2.LogicMgr.cs中 根据按钮点击 呼叫 TestRun方法并接受其返回的字符串,通过一个Text对象LogText来显示到屏幕上.并且Debug.Log字符串的内容;
3.LogicMgr.cs中还有一个按钮是会到Server上拉取对应的HotPatch并通过 PatchManager.Load加载;
测试的结果,Debug.Log中的信息的确热更成功了,但是 Text对的内容却没有更新,而且没有看到任何的错误信息
请作者大大,帮忙分析一下,如果需要我贴一下代码
可以在一个项目中,使用ILRuntime做热更新,使用injectfix做热修复吗?
IFix编译过不了 我按照安装说明做的 unity2018.1.9
我们在编辑器下测试的时候,一旦我们运行了"InjectFix/Inject"之后除了reimport unity工程,有没有更好的方法回滚injection来重新修改逻辑和运行”InjectFix/Fix“?
报错:System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ExecutionEngineException: Attempting to call method 'MBaseView::GetView' for which no ahead of time (AOT) code was generated.
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in :0
at IFix.Core.ReflectionMethodInvoker.Invoke (IFix.Core.VirtualMachine virtualMachine, Call& call, Boolean isInstantiate) [0x00000] in :0
at IFix.Core.VirtualMachine.Execute (IFix.Core.Instruction* pc, IFix.Core.Value* argumentBase, System.Object[] managedStack, IFix.Core.Value* evaluationStackBase, Int32 argsCount, Int32 methodIndex, Int32 refCount, IFix.Core.Value** topWriteBack) [0x00000] in :0
at IFix.Core.VirtualMachine.Execute (Int32 methodIndex, Call& call, Int32 argsCount, Int32 refCount) [0x00000] in :0
at IFix.ILFixDynamicMethodWrapper.__Gen_Wrap_0 (System.Object P0) [0x00000] in :0
at BaseView.OnShowLoadComplete (.CacheInfoData cacheInfo, System.Object[] args) [0x00000] in :0
at AssetsCachePool.onLoadComplete (.AssetsData ad, System.Object[] args) [0x00000] in :0
at Assets+c__Iterator0.MoveNext () [0x00000] in :0
at UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) [0x00000] in :0
--- End of inner exception stack trace ---
at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] in :0
at IFix.Core.ReflectionMethodInvoker.Invoke (IFix.Core.VirtualMachine virtualMachine, Call& call, Boolean isInstantiate) [0x00000] in :0
at IFix.Core.VirtualMachine.Execute (IFix.Core.Instruction* pc, IFix.Core.Value* argumentBase, System.Object[] managedStack, IFix.Core.Value* evaluationStackBase, Int32 argsCount, Int32 methodIndex, Int32 refCount, IFix.Core.Value** topWriteBack) [0x00000] in :0
at IFix.Core.VirtualMachine.Execute (Int32 methodIndex, Call& call, Int32 argsCount, Int32 refCount) [0x00000] in :0
at IFix.ILFixDynamicMethodWrapper.__Gen_Wrap_0 (System.Object P0) [0x00000] in :0
at MBaseView.OnShowLoadComplete (.CacheInfoData cacheInfo, System.Object[] args) [0x00000] in :0
方法:
[IFix.Patch]
public void InitUserInfoData()
{
if(null == mUserHead)
mUserHead = GetView(预制体, 父预制体);
mUserHead.ShowUserHead(Lv)
{
//赋值
});
// userName.text = this.Nickname; //原代码
userName.text = "热更代码测试"; //patch修改的部分
}
PS:
1、这个要Patch的方法InitUserInfoData(),是在加载预制体的回调里调用的。
2、GetView()是父类的一个方法,具体如下
public virtual T GetView(Transform source, Transform parent = null, SyncEvent Event = null) where T : BaseViewWidgets
{
//实例化操作
}
3、在同一脚本下,热更其他方法是正常的。
请问大神这个也是因为泛型的原因吗?
哈哈哈哈哈哈哈哈哈哈
看源码目前为方法分配id,是通过nextAllocId
自增实现的,这样是否存在隐患:新增方法后注入的dll使用旧的补丁导致方法对应不上?
是否应该直接根据方法签名来分配id,这样可以保证一定程度的兼容
按照文档配置的,有报错求解答
Windows和Mac都试过,Unity用的是2019.2版本
我们试着在patch的函数中用base.function来调用父类的函数,结果导致无限循环。
目前可以使用PatchManager.Load方法来加载补丁
如果重复调用该方法会覆盖之前的补丁
那么现在有卸载补丁的接口吗,还是说现在需要卸载的情况必须加载一个默认补丁来覆盖之前的补丁来实现?
Unity2018.4.7,导出安卓工程时,报错:
IL2CPP error for type 'IFix.IDMAP' in assembly '/xxx.../Data/Managed/Assembly-CSharp.dll'
Additional information: Value of type 'int' is too large to convert to ushort.
打包方式为IL2CPP,是否支持?
老项目的dll,注入了3万5千多个函数,生成IDMAP在ios的il2cpp阶段出错了。
Unity 5.6.7f1的il2cpp对字段数量的限制是32767【这应该是Unity.IL2CPP的bug】。
看了下iFix实现,如果直接用IDTag来标识函数唯一int索引,应该也没有问题。
现在IDTag主要为了重载函数准备的。
自己尝试建了个XIDAtrribute,使用有效,生成的dll还变小了。
感觉没必要使用IDMAP,直接用IDTag来标记不是挺好的。有什么特殊考虑吗?
InjectFix, 补丁里不能新添加方法吗 ? 编辑下会报错"can't load ......"
2019.2.10f1正常Inject后,unity发布时会重新生成Assembly-CSharp.dll,导致产品无法InjectFix,是否对Unity有版本要求?测试发现2019.1.X的版本正常。
以下测试了3个带out关键字的hotfix,
发现只有OutTest2是可以被Patch的
其他两个不生效
using System.Collections.Generic;
using IFix;
using UnityEngine;
public class HotfixTest : MonoBehaviour
{
public void Run()
{
List<string> s;
int a;
this.OutTest1(2, out s);
this.OutTest2(out a);
this.OutTest3(out s);
}
[Patch]
public void OutTest1(int count, out List<string> s)
{
s = new List<string>();
Debug.Log("OutTest1-fix");
}
[Patch]
public void OutTest2(out int count)
{
count = 22;
Debug.Log("OutTest2-fix");
}
[Patch]
public void OutTest3(out List<string> s)
{
s = new List<string>();
Debug.Log("OutTest3-fix");
}
}
Patch前,输出
OutTest1-fix
OutTest2-fix
OutTest3-fix
Patch中Log代码改为
Debug.Log("OutTest*-fixed");
运行并加载Patch,输出
OutTest1-fix
OutTest2-fixed
OutTest3-fix
=========================
随便也测试了ref关键字测试,情况和out一样
删除方法的ref/out关键字后,可以正常注入Patch
求增加一个Inject和Fix时的UI效果!提醒用户正在Inject或者Fix中!
如下Class:
public class Calculator
{
private System.Action action;
public void TestFix()
{
action += async go =>
{
await Task.Delay(1000);
};
}
}
在Inject的时候报错:
Unhandled Exception:System.Exception: IFix.Test.Calculator/c__async1 is CompilerGenerated
一个函数这样写没有问题
private int Cal(int a, int b)
{
//int[] temp = new int[] { 1,2,3};
return a + b;// + temp[0];
}
这样写就会报Warning: not support il[IL_0008: ldtoken /_
private int Cal(int a, int b)
{
int[] temp = new int[] { 1,2,3};
return a + b + temp[0];
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.