public bool Equals(DllManipulatorOptions other) { return(other.dllPathPattern == dllPathPattern && other.assemblyNames.SequenceEqual(assemblyNames) && other.loadingMode == loadingMode && other.posixDlopenFlags == posixDlopenFlags && other.threadSafe == threadSafe && other.enableCrashLogs == enableCrashLogs && other.crashLogsDir == crashLogsDir && other.crashLogsStackTrace == crashLogsStackTrace && other.mockAllNativeFunctions == mockAllNativeFunctions && other.onlyInEditor == onlyInEditor && other.enableInEditMode == enableInEditMode); }
/// <summary> /// Will unload/forget all dll's and reset the state /// </summary> public static void Reset() { UnloadAll(); ForgetAllDlls(); ClearCrashLogs(); _customLoadedTriggers?.Clear(); _customAfterUnloadTriggers?.Clear(); _customBeforeUnloadTriggers?.Clear(); Options = null; }
public DllManipulatorOptions CloneTo(DllManipulatorOptions other) { other.dllPathPattern = dllPathPattern; other.assemblyNames = assemblyNames.Select(item => (string)item.Clone()).ToList(); other.loadingMode = loadingMode; other.posixDlopenFlags = posixDlopenFlags; other.threadSafe = threadSafe; other.enableCrashLogs = enableCrashLogs; other.crashLogsDir = crashLogsDir; other.crashLogsStackTrace = crashLogsStackTrace; other.mockAllNativeFunctions = mockAllNativeFunctions; other.onlyInEditor = onlyInEditor; other.enableInEditMode = enableInEditMode; return(other); }
private void DrawOptions(DllManipulatorOptions options) { var guiEnabledStack = new Stack <bool>(); guiEnabledStack.Push(GUI.enabled); if (EditorApplication.isPlaying) { GUI.enabled = false; } options.mockAllNativeFunctions = EditorGUILayout.Toggle(TARGET_ALL_NATIVE_FUNCTIONS_GUI_CONTENT, options.mockAllNativeFunctions); if (EditorGUILayout.Toggle(TARGET_ONLY_EXECUTING_ASSEMBLY_GUI_CONTENT, options.assemblyPaths.Length == 0)) { options.assemblyPaths = new string[0]; } else { var prevIndent1 = EditorGUI.indentLevel; EditorGUI.indentLevel++; if (_allKnownAssemblies == null || _lastKnownAssembliesRefreshTime + ASSEMBLIES_REFRESH_INTERVAL < DateTime.Now) { var playerCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Player) .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath)); var editorCompiledAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor) .Select(a => PathUtils.NormallizeUnityAssemblyPath(a.outputPath)); var assemblyAssets = Resources.FindObjectsOfTypeAll <PluginImporter>() .Where(p => !p.isNativePlugin) .Select(p => PathUtils.NormallizeUnityAssemblyPath(p.assetPath)); string[] defaultAssemblyPrefixes = { "UnityEngine.", "UnityEditor.", "Unity.", "com.unity.", "Mono.", "nunit." }; _allKnownAssemblies = playerCompiledAssemblies .Concat(assemblyAssets) .Concat(editorCompiledAssemblies) .OrderBy(path => Array.FindIndex(defaultAssemblyPrefixes, p => path.Substring(path.LastIndexOf('/') + 1).StartsWith(p))) .ToArray(); _lastKnownAssembliesRefreshTime = DateTime.Now; } if (options.assemblyPaths.Length == 0) { var first = GetFirstAssemblyToList(_allKnownAssemblies); if (first != null) { options.assemblyPaths = new[] { first } } ; } _showTargetAssemblies = EditorGUILayout.Foldout(_showTargetAssemblies, TARGET_ASSEMBLIES_GUI_CONTENT); if (_showTargetAssemblies) { var prevIndent2 = EditorGUI.indentLevel; EditorGUI.indentLevel++; var selectedAssemblies = options.assemblyPaths.Where(p => _allKnownAssemblies.Any(a => PathUtils.DllPathsEqual(a, p))).ToList(); var notSelectedAssemblies = _allKnownAssemblies.Except(selectedAssemblies).ToArray(); DrawList(selectedAssemblies, i => { var values = new[] { selectedAssemblies[i] } .Concat(notSelectedAssemblies) .Select(a => a.Substring(a.LastIndexOf('/') + 1)) .ToArray(); var selectedIndex = EditorGUILayout.Popup(0, values); return(selectedIndex == 0 ? selectedAssemblies[i] : notSelectedAssemblies[selectedIndex - 1]); }, notSelectedAssemblies.Length > 0, () => notSelectedAssemblies[0]); options.assemblyPaths = selectedAssemblies.ToArray(); EditorGUI.indentLevel = prevIndent2; } EditorGUI.indentLevel = prevIndent1; } options.onlyInEditor = EditorGUILayout.Toggle(ONLY_IN_EDITOR, options.onlyInEditor); options.dllPathPattern = EditorGUILayout.TextField(DLL_PATH_PATTERN_GUI_CONTENT, options.dllPathPattern); options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode); #if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags); #endif guiEnabledStack.Push(GUI.enabled); if (options.loadingMode != DllLoadingMode.Preload) { options.threadSafe = false; GUI.enabled = false; } options.threadSafe = EditorGUILayout.Toggle(THREAD_SAFE_GUI_CONTENT, options.threadSafe); GUI.enabled = guiEnabledStack.Pop(); options.enableCrashLogs = EditorGUILayout.Toggle(CRASH_LOGS_GUI_CONTENT, options.enableCrashLogs); if (options.enableCrashLogs) { var prevIndent = EditorGUI.indentLevel; EditorGUI.indentLevel += 1; options.crashLogsDir = EditorGUILayout.TextField(CRASH_LOGS_DIR_GUI_CONTENT, options.crashLogsDir); options.crashLogsStackTrace = EditorGUILayout.Toggle(CRASH_LOGS_STACK_TRACE_GUI_CONTENT, options.crashLogsStackTrace); EditorGUI.indentLevel = prevIndent; } GUI.enabled = guiEnabledStack.Pop(); }
private void DrawOptions(DllManipulatorOptions options) { options.onlyInEditor = EditorGUILayout.Toggle(ONLY_IN_EDITOR, options.onlyInEditor); options.enableInEditMode = EditorGUILayout.Toggle(ENABLE_IN_EDIT_MODE, options.enableInEditMode); EditorGUILayout.Separator(); EditorGUILayout.LabelField("Managed Side", EditorStyles.boldLabel); options.mockAllNativeFunctions = EditorGUILayout.Toggle(TARGET_ALL_NATIVE_FUNCTIONS_GUI_CONTENT, options.mockAllNativeFunctions); if (EditorGUILayout.Toggle(ONLY_ASSEMBLY_CSHARP_GUI_CONTENT, options.assemblyNames.Count == 0)) { options.assemblyNames.Clear(); } else { var prevIndent1 = EditorGUI.indentLevel; EditorGUI.indentLevel++; if (_possibleTargetAssemblies == null || _lastKnownAssembliesRefreshTime + ASSEMBLIES_REFRESH_INTERVAL < DateTime.Now) { RefreshPossibleTargetAssemblies(); } if (options.assemblyNames.Count == 0) { options.assemblyNames.AddRange(DllManipulator.DEFAULT_ASSEMBLY_NAMES); } _showTargetAssemblies = EditorGUILayout.Foldout(_showTargetAssemblies, TARGET_ASSEMBLIES_GUI_CONTENT); if (_showTargetAssemblies) { var prevIndent2 = EditorGUI.indentLevel; EditorGUI.indentLevel++; DrawList(options.assemblyNames, i => { var result = EditorGUILayout.TextField(options.assemblyNames[i]); // Show a pop up for quickly selecting an assembly var selectedId = EditorGUILayout.Popup(0, new[] { "Find" }.Concat(_possibleTargetAssemblies).ToArray(), GUILayout.Width(80)); if (selectedId > 0) { result = _possibleTargetAssemblies[selectedId - 1]; } return(result); }, true, () => "", () => { options.assemblyNames = options.assemblyNames .Concat(_possibleTargetAssemblies).Distinct().ToList(); }); EditorGUI.indentLevel = prevIndent2; } EditorGUI.indentLevel = prevIndent1; } EditorGUILayout.Separator(); EditorGUILayout.LabelField("Native Side", EditorStyles.boldLabel); options.dllPathPattern = EditorGUILayout.TextField(DLL_PATH_PATTERN_GUI_CONTENT, options.dllPathPattern); options.loadingMode = (DllLoadingMode)EditorGUILayout.EnumPopup(DLL_LOADING_MODE_GUI_CONTENT, options.loadingMode); #if UNITY_STANDALONE_LINUX || UNITY_STANDALONE_OSX options.posixDlopenFlags = (PosixDlopenFlags)EditorGUILayout.EnumPopup(POSIX_DLOPEN_FLAGS_GUI_CONTENT, options.posixDlopenFlags); #endif var guiEnabled = GUI.enabled; if (options.loadingMode != DllLoadingMode.Preload) { options.threadSafe = false; GUI.enabled = false; } options.threadSafe = EditorGUILayout.Toggle(THREAD_SAFE_GUI_CONTENT, options.threadSafe); GUI.enabled = guiEnabled; options.enableCrashLogs = EditorGUILayout.Toggle(CRASH_LOGS_GUI_CONTENT, options.enableCrashLogs); if (options.enableCrashLogs) { var prevIndent = EditorGUI.indentLevel; EditorGUI.indentLevel += 1; options.crashLogsDir = EditorGUILayout.TextField(CRASH_LOGS_DIR_GUI_CONTENT, options.crashLogsDir); options.crashLogsStackTrace = EditorGUILayout.Toggle(CRASH_LOGS_STACK_TRACE_GUI_CONTENT, options.crashLogsStackTrace); EditorGUI.indentLevel = prevIndent; } }
/// <summary> /// Initialization. /// Finds and mocks relevant native function declarations. /// If <see cref="DllLoadingMode.Preload"/> option is specified, loads all DLLs specified by these functions. /// Options have to be configured before calling this method. /// </summary> internal static void Initialize(DllManipulatorOptions options, int unityMainThreadId, string assetsPath) { // Make a deep copy of the options so we can edit them in DllManipulatorScript independently Options = new DllManipulatorOptions(); options.CloneTo(Options); _unityMainThreadId = unityMainThreadId; _assetsPath = assetsPath; LowLevelPluginManager.ResetStubPlugin(); IEnumerable <string> assemblyPathsTemp = Options.assemblyNames; if (!assemblyPathsTemp.Any()) { assemblyPathsTemp = DEFAULT_ASSEMBLY_NAMES; } assemblyPathsTemp = assemblyPathsTemp.Concat(INTERNAL_ASSEMBLY_NAMES); var allAssemblies = AppDomain.CurrentDomain.GetAssemblies(); var assemblies = allAssemblies.Where(a => !a.IsDynamic && assemblyPathsTemp.Any(p => p == Path.GetFileNameWithoutExtension(a.Location))).ToArray(); var missingAssemblies = assemblyPathsTemp.Except(assemblies.Select(a => Path.GetFileNameWithoutExtension(a.Location))); foreach (var assembly in missingAssemblies.Except(DEFAULT_ASSEMBLY_NAMES)) { Debug.LogError($"Could not find assembly: {assembly}"); } foreach (var assembly in assemblies) { var allTypes = assembly.GetTypes(); foreach (var type in allTypes) { foreach (var method in type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) { if (method.IsDefined(typeof(DllImportAttribute))) { if (method.IsDefined(typeof(DisableMockingAttribute))) { continue; } if (method.DeclaringType.IsDefined(typeof(DisableMockingAttribute))) { continue; } if (Options.mockAllNativeFunctions || method.IsDefined(typeof(MockNativeDeclarationAttribute)) || method.DeclaringType.IsDefined(typeof(MockNativeDeclarationsAttribute))) { MockNativeFunction(method); } } else { if (method.IsDefined(typeof(NativeDllLoadedTriggerAttribute))) { RegisterTriggerMethod(method, ref _customLoadedTriggers, method.GetCustomAttribute <NativeDllLoadedTriggerAttribute>()); } if (method.IsDefined(typeof(NativeDllBeforeUnloadTriggerAttribute))) { RegisterTriggerMethod(method, ref _customBeforeUnloadTriggers, method.GetCustomAttribute <NativeDllBeforeUnloadTriggerAttribute>()); } if (method.IsDefined(typeof(NativeDllAfterUnloadTriggerAttribute))) { RegisterTriggerMethod(method, ref _customAfterUnloadTriggers, method.GetCustomAttribute <NativeDllAfterUnloadTriggerAttribute>()); } } } } } if (Options.loadingMode == DllLoadingMode.Preload) { LoadAll(); } }