private static void BuildAssetBundles() { DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); DLLMgr.Delete(Directory.GetParent(Application.dataPath) + "/Assets/XAsset/ScriptableObjects/Rules.asset"); DLLMgr.Delete(Directory.GetParent(Application.dataPath) + "/Assets/XAsset/ScriptableObjects/Manifest.asset"); CryptoWindow.ShowWindow(); CryptoWindow.Build = s => { var watch = new Stopwatch(); watch.Start(); var bytes = DLLMgr.FileToByte(DLLMgr.DllPath); var result = DLLMgr.ByteToFile(CryptoHelper.AesEncrypt(bytes, s), "Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch.Stop(); Log.Print("Convert Dlls in: " + watch.ElapsedMilliseconds + " ms."); if (!result) { Log.PrintError("DLL转Byte[]出错!"); } watch = new Stopwatch(); watch.Start(); BuildScript.ApplyBuildRules(); watch.Stop(); Log.Print("ApplyBuildRules in: " + watch.ElapsedMilliseconds + " ms."); watch = new Stopwatch(); watch.Start(); BuildScript.BuildAssetBundles(); watch.Stop(); Log.Print("BuildAssetBundles in: " + watch.ElapsedMilliseconds + " ms."); }; }
private static void CleanBundles() { var watch = new Stopwatch(); watch.Start(); DLLMgr.Delete(Directory.GetParent(Application.dataPath) + "/DLC"); watch.Stop(); Log.Print("Clean bundles in: " + watch.ElapsedMilliseconds + " ms."); }
static void Update() { if (!isDone) { return; } if (!Directory.Exists("Assets/HotUpdateResources/Dll/Hidden~")) { Directory.CreateDirectory("Assets/HotUpdateResources/Dll/Hidden~"); } DirectoryInfo di = new DirectoryInfo("Assets/HotUpdateResources/Dll/Hidden~"); var files = di.GetFiles(); if (files.Length > 1) { isDone = false; int counts = 0; var watch = new Stopwatch(); watch.Start(); foreach (var file in files) { var name = file.Name; if (!file.Name.Contains("HotUpdateScripts")) { DLLMgr.Delete(file.FullName); counts++; } } watch.Stop(); if (counts > 0) { Log.Print("Cleaned: " + counts + " files in: " + watch.ElapsedMilliseconds + " ms."); DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); AssetDatabase.Refresh(); } isDone = true; } if (!File.Exists("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes")) { isDone = false; var watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); AssetDatabase.Refresh(); isDone = true; } }
private static void BuildAssetBundles() { DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); // DLLMgr.Delete(Directory.GetParent(Application.dataPath)+"/Assets/XAsset/ScriptableObjects/Rules.asset"); // DLLMgr.Delete(Directory.GetParent(Application.dataPath)+"/Assets/XAsset/ScriptableObjects/Manifest.asset"); Action <string> buildAct = async s => { var watch = new Stopwatch(); watch.Start(); var bytes = DLLMgr.FileToByte(DLLMgr.DllPath); var result = DLLMgr.ByteToFile(CryptoHelper.AesEncrypt(bytes, s), "Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch.Stop(); Log.Print("Convert Dlls in: " + watch.ElapsedMilliseconds + " ms."); if (!result) { Log.PrintError("DLL转Byte[]出错!"); return; } Setting.EncryptPassword = s; await Task.Delay(3); AssetDatabase.Refresh(); watch = new Stopwatch(); watch.Start(); BuildScript.ApplyBuildRules(); watch.Stop(); Log.Print("ApplyBuildRules in: " + watch.ElapsedMilliseconds + " ms."); watch = new Stopwatch(); watch.Start(); BuildScript.BuildAssetBundles(); watch.Stop(); Log.Print("BuildAssetBundles in: " + watch.ElapsedMilliseconds + " ms."); }; if (string.IsNullOrEmpty(Setting.EncryptPassword)) { CryptoWindow.ShowWindow(); CryptoWindow.Build = buildAct; } else { buildAct.Invoke(Setting.EncryptPassword); } }
void LoadHotFixAssembly() { appdomain = new AppDomain(); pdb = null; //编译模式 if (!Assets.runtimeMode) { if (File.Exists(dllPath)) { fs = new MemoryStream(DLLMgr.FileToByte(dllPath)); } else { Log.PrintError("DLL文件不存在"); return; } //查看是否有PDB文件 if (File.Exists(pdbPath) && UsePdb && (File.GetLastWriteTime(dllPath) - File.GetLastWriteTime(pdbPath)).Seconds < 30) { pdb = new MemoryStream(DLLMgr.FileToByte(pdbPath)); } } else//解密加载 { var dllAsset = Assets.LoadAsset("HotUpdateScripts.bytes", typeof(TextAsset)); if (dllAsset.error != null) { Log.PrintError(dllAsset.error); return; } var dll = (TextAsset)dllAsset.asset; try { var original = CryptoHelper.AesDecrypt(dll.bytes, Key); fs = new MemoryStream(original); } catch (Exception ex) { Log.PrintError("加载热更DLL失败,可能是解密密码不正确"); Log.PrintError("加载热更DLL错误:\n" + ex.Message); return; } } try { appdomain.LoadAssembly(fs, pdb, new PdbReaderProvider()); } catch (Exception e) { if (!UsePdb) { Log.PrintError("加载热更DLL失败,请确保HotUpdateResources/Dll里面有HotUpdateScripts.bytes文件,并且Build Bundle后将DLC传入服务器"); Log.PrintError("加载热更DLL错误:\n" + e.Message); return; } Log.PrintError("PDB不可用,可能是DLL和PDB版本不一致,可能DLL是Release,如果是Release出包,请取消UsePdb选项,本次已跳过使用PDB"); UsePdb = false; LoadHotFixAssembly(); } InitILrt.InitializeILRuntime(appdomain); OnHotFixLoaded(); }
static void Update() { if (!isDone || EditorApplication.isPlaying) { return; } if (!Directory.Exists("Assets/HotUpdateResources/Dll/Hidden~")) //DLL导入到隐藏文件夹,防止每次加载浪费时间 { Directory.CreateDirectory("Assets/HotUpdateResources/Dll/Hidden~"); } if (!File.Exists(DLLMgr.DllPath)) //没热更dll就返回 { return; } //有的话比较日期 DateTime lastModified = File.GetLastWriteTime(DLLMgr.DllPath); string lastModifiedStr = lastModified.ToString(JEngineSetting.GetString(JEngineSetting.DATE_FORMAT)); if (JEngineSetting.LastDLLCleanUpTime != lastModifiedStr) //不一样再处理 { var files = di.GetFiles(); var watch = new Stopwatch(); int counts = 0; List <string> fileNames = Directory.GetFiles("Assets/", "*.dll", SearchOption.AllDirectories).ToList(); DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); if (watch.ElapsedMilliseconds > 0) { Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); } AssetDatabase.Refresh(); JEngineSetting.LastDLLCleanUpTime = lastModifiedStr; isDone = false; fileNames = fileNames.FindAll((x) => !x.Contains("~")); watch.Start(); foreach (var file in files) { var name = file.Name; if (!File.Exists(library.FullName + "/" + name) && !name.Contains("netstandard") && !name.Contains("HotUpdateScripts") && !name.Contains("Unity") && !name.Contains("System") && ((name.Contains(".pdb") || name.Contains(".dll")))) { if (fileNames.Find(x => x.Contains(name)) == null) //不存在就添加 { DLLMgr.Delete(file.FullName.Replace("Hidden~", "../Dll")); File.Move(file.FullName, file.FullName.Replace("Hidden~", "../Dll")); Log.Print( $"Find new referenced dll `{name}`, note that your hot update code may not be able " + $"to run without rebuild application\n" + $"发现新的引用DLL`{name}`,请注意,游戏可能需要重新打包,否则热更代码无法将有可能运行"); } else //存在就删了 { DLLMgr.Delete(file.FullName); counts++; } } else if (!name.Contains("HotUpdateScripts")) { DLLMgr.Delete(file.FullName); counts++; } else { if (!name.Contains("HotUpdateScripts")) { Log.PrintError($"无法删除{file.FullName},请手动删除"); } } } watch.Stop(); if (counts > 0) //如果删除过东西,就代表DLL更新了,就需要生成文件 { Log.Print("Cleaned: " + counts + " files in: " + watch.ElapsedMilliseconds + " ms."); } isDone = true; } if (!File.Exists("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes")) { isDone = false; var watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); AssetDatabase.Refresh(); isDone = true; } }
static void Update() { if (!isDone) { return; } if (!Directory.Exists("Assets/HotUpdateResources/Dll/Hidden~"))//DLL导入到隐藏文件夹,防止每次加载浪费时间 { Directory.CreateDirectory("Assets/HotUpdateResources/Dll/Hidden~"); } DirectoryInfo library = new DirectoryInfo(new DirectoryInfo(Application.dataPath).Parent.FullName + "/Library/ScriptAssemblies"); DirectoryInfo di = new DirectoryInfo("Assets/HotUpdateResources/Dll/Hidden~"); var files = di.GetFiles(); if (files.Length > 1) { isDone = false; int counts = 0; var watch = new Stopwatch(); watch.Start(); foreach (var file in files) { var name = file.Name; if (!File.Exists(library.FullName + "/" + name) && !name.Contains("HotUpdateScripts") && !name.Contains("Unity") && (name.Contains(".pdb") || name.Contains(".dll")))//不存在就添加 { File.Move(file.FullName, file.FullName.Replace("/Hidden~", "")); } else if (!name.Contains("HotUpdateScripts")) { DLLMgr.Delete(file.FullName); counts++; } } watch.Stop(); if (counts > 0)//如果删除过东西,就代表DLL更新了,就需要生成文件 { Log.Print("Cleaned: " + counts + " files in: " + watch.ElapsedMilliseconds + " ms."); DLLMgr.Delete("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes"); watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); if (watch.ElapsedMilliseconds > 0) { Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); } AssetDatabase.Refresh(); } isDone = true; } if (!File.Exists("Assets/HotUpdateResources/Dll/HotUpdateScripts.bytes")) { isDone = false; var watch = new Stopwatch(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print("Convert DLL in: " + watch.ElapsedMilliseconds + " ms."); AssetDatabase.Refresh(); isDone = true; } }
void LoadHotFixAssembly() { Appdomain = new AppDomain(); _pdb = null; byte[] buffer; //开发模式 #if XASSET_PRO if (Assets.development) #else if (!Assets.runtimeMode) #endif { if (File.Exists(DLLPath))//直接读DLL { buffer = DLLMgr.FileToByte(DLLPath); //模拟加密 buffer = CryptoHelper.AesEncrypt(buffer, key); } else { Log.PrintError("DLL文件不存在"); return; } //查看是否有PDB文件 if (File.Exists(PdbPath) && usePdb && (File.GetLastWriteTime(DLLPath) - File.GetLastWriteTime(PdbPath)).Seconds < 30) { _pdb = new MemoryStream(DLLMgr.FileToByte(PdbPath)); } } else//真机模式解密加载 { var dllAsset = Assets.LoadAsset("HotUpdateScripts.bytes", typeof(TextAsset)); if (dllAsset.error != null) { Log.PrintError(dllAsset.error); return; } var dll = (TextAsset)dllAsset.asset; buffer = new byte[dll.bytes.Length]; Array.Copy(dll.bytes, buffer, dll.bytes.Length); dllAsset.Release();//释放掉不需要再用的dll } try { // var original = CryptoHelper.AesDecrypt(dll.bytes, Key);以前的用法,过时了 _fs = new JStream(buffer, key); /* * 如果一定要先解密,可以这样: * var original = CryptoHelper.AesDecrypt(dll.bytes, Key); * fs = new JStream(original, Key); * fs.Encrypted = false; */ Appdomain.LoadAssembly(_fs, _pdb, new PdbReaderProvider()); } catch (Exception e) { Log.PrintError("加载热更DLL错误:\n" + e); if (!usePdb) { Log.PrintError("加载热更DLL失败,请确保HotUpdateResources/Dll里面有HotUpdateScripts.bytes文件,并且Build Bundle后将DLC传入服务器"); } else { Log.PrintError("PDB不可用,可能是DLL和PDB版本不一致,可能DLL是Release,如果是Release出包,请取消UsePdb选项,本次已跳过使用PDB"); usePdb = false; LoadHotFixAssembly(); } return; } Success = true; LoadILRuntime.InitializeILRuntime(Appdomain); }
public static void Update() { if (!_isDone || EditorApplication.isPlaying) { return; } if (!HiddenDirectory.Exists) //DLL导入到隐藏文件夹,防止每次加载浪费时间 { HiddenDirectory.Create(); } if (!File.Exists(DLLMgr.DllPath)) //没热更dll就返回 { return; } //有的话比较日期 DateTime lastModified = File.GetLastWriteTime(DLLMgr.DllPath); string lastModifiedStr = lastModified.ToString(Setting.GetString(SettingString.DateFormat)); if (Setting.LastDLLCleanUpTime != lastModifiedStr) //不一样再处理 { var files = HiddenDirectory.GetFiles(); int counts = 0; List <string> fileNames = Directory.GetFiles("Assets/", "*.dll", SearchOption.AllDirectories).ToList(); var watch = new Stopwatch(); watch.Start(); DLLMgr.MakeBytes(); watch.Stop(); if (watch.ElapsedMilliseconds > 0) { Log.Print(String.Format(Setting.GetString(SettingString.DLLConvertLog), watch.ElapsedMilliseconds)); } AssetDatabase.Refresh(); Setting.LastDLLCleanUpTime = lastModifiedStr; _isDone = false; fileNames = fileNames.FindAll(x => !x.Contains("~")); watch.Start(); foreach (var file in files) { var name = file.Name; var success = true; if (!File.Exists(LibraryDirectory.FullName + "/" + name) && !name.Contains("netstandard") && !name.Contains(HotProjectName) && !name.Contains("Unity") && !name.Contains("System") && ((name.Contains(".pdb") || name.Contains(".dll")))) { if (fileNames.Find(x => x.Contains(name)) == null) //不存在就添加 { success = false; } else //存在就删了 { DLLMgr.Delete(file.FullName); counts++; } } else if (!name.Contains(HotProjectName)) { try { DLLMgr.Delete(file.FullName); counts++; } catch { Log.Print(String.Format( Setting.GetString(SettingString.DeleteErrorLog), file.Name)); success = false; } } if (!success) { if (file.Directory != null) { DirectoryInfo newPath = new DirectoryInfo(file.Directory.FullName)?.Parent?.Parent?.Parent; if (newPath != null) { File.Move(file.FullName, newPath.FullName + "/" + file.Name); Log.Print(String.Format( Setting.GetString(SettingString.DLLNewReferenceLog), newPath.FullName + "/" + file.Name)); } } } } watch.Stop(); if (counts > 0) //如果删除过东西,就代表DLL更新了,就需要生成文件 { Log.Print(String.Format(Setting.GetString(SettingString.DLLCleanLog), counts, watch.ElapsedMilliseconds)); } _isDone = true; } if (!HotFile.Exists) { _isDone = false; var watch = new Stopwatch(); watch.Start(); DLLMgr.MakeBytes(); watch.Stop(); Log.Print(String.Format(Setting.GetString(SettingString.DLLConvertLog), watch.ElapsedMilliseconds)); AssetDatabase.Refresh(); _isDone = true; } }
void LoadHotFixAssembly() { Appdomain = new AppDomain(); _pdb = null; byte[] dll; #if UNITY_EDITOR //开发模式 if (!AssetMgr.RuntimeMode) { if (File.Exists(DLLPath)) //直接读DLL { dll = DLLMgr.FileToByte(DLLPath); //模拟加密 dll = CryptoHelper.AesEncrypt(dll, key); } else { Log.PrintError("DLL文件不存在"); return; } //查看是否有PDB文件 if (File.Exists(PdbPath) && usePdb && (File.GetLastWriteTime(DLLPath) - File.GetLastWriteTime(PdbPath)).Seconds < 30) { _pdb = new MemoryStream(DLLMgr.FileToByte(PdbPath)); } } else //真机模式解密加载 #endif { var dllFile = (TextAsset)AssetMgr.Load(DllName, typeof(TextAsset)); if (dllFile == null) { return; } dll = dllFile.bytes; } var buffer = new byte[dll.Length]; Array.Copy(dll, buffer, dll.Length); AssetMgr.Unload(DllName, true); try { //这里默认用分块解密,JStream _fs = new JStream(buffer, key); /* * 如果一定要直接解密然后不进行分块解密加载Dll,可以这样: * var original = CryptoHelper.AesDecrypt(dll.bytes, Key); * _fs = new JStream(original, Key); * _fs.Encrypted = false; */ Appdomain.LoadAssembly(_fs, _pdb, new PdbReaderProvider()); } catch (Exception e) { Log.PrintError("加载热更DLL错误:\n" + e); if (!usePdb) { Log.PrintError( "加载热更DLL失败,请确保HotUpdateResources/Dll里面有HotUpdateScripts.bytes文件,并且Build Bundle后将DLC传入服务器"); Log.PrintError("也有可能是密码不匹配或密码包含特殊字符导致的"); } else { Log.PrintError("PDB不可用,可能是DLL和PDB版本不一致,可能DLL是Release,如果是Release出包,请取消UsePdb选项,本次已跳过使用PDB"); usePdb = false; LoadHotFixAssembly(); } return; } Success = true; LoadILRuntime.InitializeILRuntime(Appdomain); }
void LoadHotFixAssembly() { appdomain = new AppDomain(); if (!Assets.runtimeMode) { DLLMgr.MakeBytes(); } var dllAsset = Assets.LoadAsset("HotUpdateScripts.bytes", typeof(TextAsset)); if (dllAsset.error != null) { Log.PrintError(dllAsset.error); return; } var dll = (TextAsset)dllAsset.asset; byte[] original = dll.bytes; try { if (!Assets.runtimeMode) { original = CryptoHelper.AesDecrypt(original, "DevelopmentMode."); } else { original = CryptoHelper.AesDecrypt(original, Key); } } catch (Exception ex) { Log.PrintError("加载热更DLL失败,可能是解密密码不正确"); Log.PrintError("加载热更DLL错误:\n" + ex.Message); return; } fs = new MemoryStream(original); MemoryStream pdb = null; #if UNITY_EDITOR if (File.Exists("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.pdb")) { try { pdb = new MemoryStream(AssetDatabase.LoadAssetAtPath <TextAsset>("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.pdb").bytes); } catch { } } #endif try { appdomain.LoadAssembly(fs, pdb, new PdbReaderProvider()); } catch (Exception e) { Log.PrintError("加载热更DLL失败,请确保HotUpdateResources/Dll里面有HotUpdateScripts.bytes文件,并且Build Bundle后将DLC传入服务器"); Log.PrintError("加载热更DLL错误:\n" + e.Message); return; } InitILrt.InitializeILRuntime(appdomain); OnHotFixLoaded(); }
void LoadHotFixAssembly() { appdomain = new AppDomain(); pdb = null; //编译模式 if (!Assets.runtimeMode) { if (File.Exists("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.dll")) { fs = new MemoryStream(DLLMgr.FileToByte("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.dll")); } else { Log.PrintWarning("DLL文件不存在"); return; } //查看是否有PDB文件 if (File.Exists("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.pdb")) { pdb = new MemoryStream(DLLMgr.FileToByte("Assets/HotUpdateResources/Dll/Hidden~/HotUpdateScripts.pdb")); } } else//解密加载 { var dllAsset = Assets.LoadAsset("HotUpdateScripts.bytes", typeof(TextAsset)); if (dllAsset.error != null) { Log.PrintError(dllAsset.error); return; } var dll = (TextAsset)dllAsset.asset; try { var original = CryptoHelper.AesDecrypt(dll.bytes, Key); fs = new MemoryStream(original); } catch (Exception ex) { Log.PrintError("加载热更DLL失败,可能是解密密码不正确"); Log.PrintError("加载热更DLL错误:\n" + ex.Message); return; } } try { appdomain.LoadAssembly(fs, pdb, new PdbReaderProvider()); } catch (Exception e) { Log.PrintError("加载热更DLL失败,请确保HotUpdateResources/Dll里面有HotUpdateScripts.bytes文件,并且Build Bundle后将DLC传入服务器"); Log.PrintError("加载热更DLL错误:\n" + e.Message); return; } InitILrt.InitializeILRuntime(appdomain); OnHotFixLoaded(); }