private void ValidateEntryPoint(string directory, string handler) { var parts = handler.Split("::"); if (parts.Length != 3) { LogError("'Handler' attribute has invalid value"); return; } try { var lambdaFunctionAssemblyName = parts[0]; var lambdaFunctionClassName = parts[1]; var lambdaFunctionEntryPointName = parts[2]; using (var resolver = new CustomAssemblyResolver(directory)) using (var lambdaFunctionAssembly = AssemblyDefinition.ReadAssembly(Path.Combine(directory, $"{lambdaFunctionAssemblyName}.dll"), new ReaderParameters { AssemblyResolver = resolver })) { if (lambdaFunctionAssembly == null) { LogError("could not load assembly"); return; } var functionClassType = lambdaFunctionAssembly.MainModule.GetType(lambdaFunctionClassName); if (functionClassType == null) { LogError($"could not find type '{lambdaFunctionClassName}' in assembly"); return; } FindMethod(functionClassType, lambdaFunctionEntryPointName); // local functions void FindMethod(TypeDefinition methodClassType, string methodName) { again: var functionMethod = methodClassType.Methods.FirstOrDefault(method => method.Name == methodName); if (functionMethod == null) { if ((methodClassType.BaseType == null) || (methodClassType.BaseType.FullName == "System.Object")) { LogError($"could not find method '{methodName}' in class '{lambdaFunctionClassName}'"); return; } methodClassType = methodClassType.BaseType.Resolve(); goto again; } } } } catch (Exception e) { if (Settings.VerboseLevel >= VerboseLevel.Exceptions) { LogError(e); } else { LogWarn("unable to validate function entry-point due to an internal error"); } } }
public static AssemblyDefinition ToDefinition(this Assembly assembly) { var assemblyFile = new FileInfo(assembly.Location); var resolver = new CustomAssemblyResolver(assemblyFile.Directory, NullLogger <CustomAssemblyResolver> .Instance); var readerParameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; return(AssemblyDefinition.ReadAssembly(assemblyFile.FullName, readerParameters)); }
public static AssemblyDefinition ToDefinition(this Assembly assembly) { var assemblyFile = _fileSystem.FileInfo.FromFileName(assembly.Location); var depsJsonUtils = new DepsJsonUtils(new FileSystem()); var resolver = new CustomAssemblyResolver(assemblyFile.Directory, NullLogger <CustomAssemblyResolver> .Instance, depsJsonUtils); var readerParameters = new ReaderParameters { ReadSymbols = true, AssemblyResolver = resolver }; return(AssemblyDefinition.ReadAssembly(assemblyFile.FullName, readerParameters)); }
/// <summary> /// Creates a new instance of this type. /// </summary> /// <param name="assemblyFileNames">The set of assemblies to use</param> /// <param name="assemblySearchPaths">Optional set of paths to search for referenced assemblies.</param> /// <param name="logger">Optional logger to use to report errors or warnings</param> public SharedAssemblies(IEnumerable <string> assemblyFileNames, IEnumerable <string> assemblySearchPaths, ILogger logger) { if (assemblyFileNames == null) { throw new ArgumentNullException("assemblyFileNames"); } _logger = logger; _sharedTypeByName = new Dictionary <string, TypeInfo>(StringComparer.Ordinal); _resolver = new CustomAssemblyResolver(assemblySearchPaths ?? Enumerable.Empty <string>()); _resolver.ResolveFailure += _resolver_ResolveFailure; LoadAssemblies(assemblyFileNames, logger); }
/// <summary> /// set up the AppDomain for the type to map in the containing assembly assemblyToMap /// </summary> /// <param name="assemblyToMap">the assembly containing the type to map</param> private static void SetupAppDomain(Assembly assemblyToMap) { AppDomain curDomain = AppDomain.CurrentDomain; curDomain.AppendPrivatePath(curDomain.BaseDirectory); // directory of the assembly containing the typ to map // make sure to probe in directory containing type to map, if not found itself ... string directoryName = new FileInfo(assemblyToMap.Location).DirectoryName; CustomAssemblyResolver resolver = new CustomAssemblyResolver(directoryName); ResolveEventHandler hndlr = new ResolveEventHandler(resolver.AssemblyResolve); curDomain.AssemblyResolve += hndlr; }
public MarshalCodeGenerator(string inputFile) { var assemblyResolver = new CustomAssemblyResolver(); assemblyDefinition = AssemblyDefinition.ReadAssembly(inputFile, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = true }); // TODO: Remove hardcoded relative paths assemblyResolver.Register(assemblyDefinition); assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyDefinition.MainModule.FullyQualifiedName)); assemblyResolver.AddSearchDirectory(@"..\..\..\..\src\mcs\class\lib\net_4_5".Replace('\\', Path.DirectorySeparatorChar)); }
public AssemblyExplorerQuery( Assembly oAssembly, IAssemblyQueryFilter oQueryFilter, string customizationDir) : base(oAssembly.GetName().Name, new string[] { }) { m_sAssemblyName = oAssembly.GetName().Name; m_customAssemblyResolver = new CustomAssemblyResolver(new BasicConfiguration().eFlowBinPath); m_customAssemblyResolver.CustomizationDir = customizationDir; m_AssemblyTypes = QueryAssemblyTypes(oAssembly, oQueryFilter); m_referencedAssemblies = QueryReferencedAssemblies(oAssembly); }
public LambdaAssemblyLoadContext(string lambdaPath) : #if !NETCOREAPP2_1 base("LambdaContext") { _builtInResolver = new AssemblyDependencyResolver(lambdaPath); #else base() { #endif _customResolver = new CustomAssemblyResolver(this, lambdaPath); _customDefaultContextResolver = new CustomAssemblyResolver(AssemblyLoadContext.Default, lambdaPath); AssemblyLoadContext.Default.Resolving += OnDefaultAssemblyLoadContextResolving; }
public TisEventsManager( ITransactionalStorage oApplicationResources, string sApplicationName, CustomAssemblyResolver customAssemblyResolver, DictionaryWithEvents <string, ITisInvokeType> invokeTypes) { m_sApplicationName = sApplicationName; m_oApplicationResources = oApplicationResources; m_oCustomAssemblyResolver = customAssemblyResolver; m_invokeTypes = invokeTypes; DataContractSerializer eventsDataContractSerializer = new DataContractSerializer(typeof(TisEventBindingsMngr), new Type[] { typeof(EventBindingInfoMngr) }); m_eventsStorage = new ObjectStorage( m_oApplicationResources, new ObjectReadDelegate(eventsDataContractSerializer.ReadObject), new ObjectWriteDelegate(eventsDataContractSerializer.WriteObject)); InitTransactionManager(sApplicationName); }
private static AssemblyDefinition LoadAssembly(string inputFile) { // Force PdbReader to be referenced typeof(Mono.Cecil.Pdb.PdbReader).ToString(); var assemblyResolver = new CustomAssemblyResolver(); // Check if there is a PDB var readPdb = File.Exists(System.IO.Path.ChangeExtension(inputFile, "pdb")); var assemblyDefinition = AssemblyDefinition.ReadAssembly(inputFile, new ReaderParameters { AssemblyResolver = assemblyResolver, ReadSymbols = readPdb }); // Register self to assembly resolver assemblyResolver.Register(assemblyDefinition); assemblyResolver.AddSearchDirectory(Path.GetDirectoryName(assemblyDefinition.MainModule.FullyQualifiedName)); assemblyResolver.AddSearchDirectory(@"..\..\..\..\src\mcs\class\lib\net_4_5"); return(assemblyDefinition); }
/// <summary>setup assembly resolution: consider all directories of /r files /// and current directory as assembly containing directories</summary> private void SetupAssemblyResolver() { ArrayList searchDirectoryList = new ArrayList(); searchDirectoryList.Add(new DirectoryInfo(".").FullName); foreach (Assembly refAsm in m_commandLine.ReferencedAssemblies) { string asmDir = new FileInfo(refAsm.Location).Directory.FullName; if (!searchDirectoryList.Contains(asmDir)) { searchDirectoryList.Add(asmDir); } } AppDomain curDomain = AppDomain.CurrentDomain; curDomain.AppendPrivatePath(curDomain.BaseDirectory); CustomAssemblyResolver resolver = new CustomAssemblyResolver(searchDirectoryList); ResolveEventHandler hndlr = new ResolveEventHandler(resolver.AssemblyResolve); curDomain.AssemblyResolve += hndlr; }
public void Create(ProgressHandler progress) { var modFilePath = GetFolderPath() + Path.DirectorySeparatorChar + "Mod" + Path.DirectorySeparatorChar + Id + ".dll"; if (!File.Exists(modFilePath)) { Debug.Log("Mod: " + Id, "Couldn't find the compiled mod dll at \"" + modFilePath + "\".", Debug.Type.Error); SetProgress(progress, "Error.FileNotFound"); return; } var modInfoPath = GetFolderPath() + Path.DirectorySeparatorChar + "ModInfo.xml"; if (!File.Exists(modInfoPath)) { Debug.Log("Mod: " + Id, "Couldn't find the mod configuration at \"" + modInfoPath + "\".", Debug.Type.Error); SetProgress(progress, "Error.FileNotFound"); return; } var libraryFolder = Game.ModLibrary.GetLibraryFolder(); var baseModLibPath = libraryFolder + Path.DirectorySeparatorChar + "BaseModLib.dll"; if (!File.Exists(baseModLibPath)) { Debug.Log("Mod: " + Id, "Couldn't find BaseModLib.dll at \"" + baseModLibPath + "\".", Debug.Type.Error); SetProgress(progress, "Error.FileNotFound"); return; } ModuleDefinition modModule; ModuleDefinition baseModLib; try { SetProgress(progress, 0f, "Preparing"); baseModLib = ModuleDefinition.ReadModule(baseModLibPath); SetProgress(progress, 5f); var assemblyResolver = new CustomAssemblyResolver(); assemblyResolver.AddPath(Configuration.GetPath("ModLib") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar); modModule = ModuleDefinition.ReadModule(modFilePath, new ReaderParameters { AssemblyResolver = assemblyResolver }); SetProgress(progress, 10f); } catch (Exception e) { Debug.Log("Mod: " + Id, "One of the assemblies is corrupted: " + e, Debug.Type.Error); SetProgress(progress, "Error.CorruptAssembly"); return; } var mod = new Mod(Game, ""); mod.HeaderData = new Mod.Header(mod, File.ReadAllText(modInfoPath)); mod.Module = modModule; var stream = new MemoryStream(); mod.Module.Write(stream); stream.Position = 0; mod.OriginalModule = ModuleDefinition.ReadModule(stream); SetProgress(progress, 15f); try { var baseModLibRemap = new Dictionary <MethodReference, MethodReference>(); foreach (var baseModLibType in baseModLib.Types) { foreach (var method in baseModLibType.Methods) { if (method.HasCustomAttributes && method.CustomAttributes[0].AttributeType.Name == "AddModname") { foreach (var method2 in baseModLibType.Methods) { if (!method2.HasCustomAttributes && method2.Name == method.Name && method2.Parameters.Count > method.Parameters.Count) { var add = true; for (var i = 0; i < method.Parameters.Count; i++) { var param = method.Parameters[i]; if (param.ParameterType.FullName != method2.Parameters[i].ParameterType.FullName) { add = false; } } if (add) { baseModLibRemap.Add(method, method2); } } } } } } SetProgress(progress, 20f, "FetchingTypes"); var injectableClasses = new Dictionary <string, string>(); var assemblyTypes = new Dictionary <string, Dictionary <string, TypeDefinition> >(); for (var i = 0; i < Game.GameConfiguration.IncludeAssemblies.Count; i++) { var assembly = libraryFolder + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.IncludeAssemblies[i]); var module = ModuleDefinition.ReadModule(assembly); var key = Path.GetFileNameWithoutExtension(assembly); assemblyTypes.Add(key, new Dictionary <string, TypeDefinition>()); foreach (var type in module.Types) { if (!ModLib.CheckName(type.Namespace, Game.GameConfiguration.ExcludeNamespaces) && !ModLib.CheckName(type.FullName, Game.GameConfiguration.ExcludeTypes) && !ModLib.CheckName(type.FullName, Game.GameConfiguration.NoFamily)) { assemblyTypes[key].Add(type.FullName, type); if (!injectableClasses.ContainsKey(type.FullName)) { injectableClasses.Add(type.FullName, key); } } } SetProgress(progress, 20f + (i / (float)Game.GameConfiguration.IncludeAssemblies.Count) * 30f); } SetProgress(progress, 50f, "ConvertingClasses"); var newClasses = new Dictionary <string, TypeDefinition>(); for (var i = 0; i < modModule.Types.Count; i++) { var type = modModule.Types[i]; if (type.FullName == "<Module>") { continue; } foreach (var method in type.Methods) { if (method?.Body != null) { for (var j = 0; j < method.Body.Instructions.Count; j++) { var methodIl = method.Body.GetILProcessor(); var instruction = method.Body.Instructions[j]; if (instruction.OpCode == OpCodes.Call && instruction.Operand != null) { foreach (var map in baseModLibRemap) { if (((MethodReference)instruction.Operand).FullName == map.Key.FullName) { instruction.Operand = type.Module.Import(map.Value); var newInstruction = methodIl.Create(OpCodes.Ldstr, Id); methodIl.InsertBefore(instruction, newInstruction); } } } } } } var assemblyName = ""; if (type.BaseType != null && injectableClasses.ContainsKey(type.BaseType.FullName)) { assemblyName = injectableClasses[type.BaseType.FullName]; } if (assemblyName == "" || !assemblyTypes[assemblyName].ContainsKey(type.BaseType.FullName)) { var addClass = new Mod.Header.AddClass(mod) { Type = type }; mod.HeaderData.AddAddClass(addClass); } else { foreach (var field in type.Fields) { var addField = new Mod.Header.AddField(mod) { Field = field, AssemblyName = assemblyName }; mod.HeaderData.AddAddField(addField); } foreach (var method in type.Methods) { if (method == null) { continue; } var priority = int.MaxValue; if (method.CustomAttributes != null) { foreach (var attribute in method.CustomAttributes) { if (attribute.AttributeType.Name == "Priority") { priority = (int)attribute.ConstructorArguments[0].Value; } } } var inject = false; if (method.IsVirtual || method.IsStatic || method.IsConstructor) { foreach (var m in assemblyTypes[assemblyName][type.BaseType.FullName].Methods.Where(o => o.Name == method.Name)) { // Only compare methods with same parameter count if (method.Parameters.Count == m.Parameters.Count) { // No need to compare parameterless methods if (method.Parameters.Count == 0) { inject = true; break; } // Comapare parameters if (!m.Parameters.Where((param, pi) => param.ParameterType.FullName != method.Parameters[pi].ParameterType.FullName).Any()) { inject = true; break; } } } } if (inject) { var injectInto = new Mod.Header.InjectInto(mod) { Method = method, Priority = priority, AssemblyName = assemblyName }; mod.HeaderData.AddInjectInto(injectInto); } else { var addMethod = new Mod.Header.AddMethod(mod) { Method = method, AssemblyName = assemblyName }; mod.HeaderData.AddAddMethod(addMethod); } } } SetProgress(progress, 50f + (i / (float)modModule.Types.Count) * 30f); } foreach (var aref in modModule.AssemblyReferences) { if (aref.Name == "mscorlib" || aref.Name == "System") { aref.Version = new System.Version("2.0.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } if (aref.Name == "System.Core") { aref.Version = new System.Version("3.5.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } if (aref.Name == "System.Xml") { aref.Version = new System.Version("2.0.0.0"); aref.PublicKeyToken = new byte[] { 0xB7, 0x7A, 0x5C, 0x56, 0x19, 0x34, 0xE0, 0x89 }; } } } catch (Exception e) { Debug.Log("Mod: " + Id, "An unexpected error occured while parsing the assembly: " + e, Debug.Type.Error); SetProgress(progress, "Error.UnexpectedError"); return; } var modResourcesPath = GetFolderPath() + Path.DirectorySeparatorChar + "Resources/"; if (!Directory.Exists(modResourcesPath)) { Directory.CreateDirectory(modResourcesPath); } if (Directory.GetFiles(modResourcesPath).Length > 0 || Directory.GetDirectories(modResourcesPath).Length > 0) { var newZipFile = new ZipFile(); newZipFile.AddDirectory(modResourcesPath); newZipFile.Comment = "Automaticlly created resources zip file."; mod.Resources = newZipFile; } try { SetProgress(progress, 90f, "SavingMod"); var modFolder = Path.GetFullPath(Configuration.GetPath("mods") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id); if (!Directory.Exists(modFolder)) { Directory.CreateDirectory(modFolder); } mod.FileName = Path.GetFullPath(modFolder + Path.DirectorySeparatorChar + mod.UniqueId + ".mod"); if (mod.Save()) { var key = mod.Id + "-" + mod.HeaderData.GetVersion(); if (Mod.Mods.ContainsKey(key)) { if (Mod.Mods[key].FileName != mod.FileName) { Mod.Mods[key].Remove(); } //Mod.Mods[key] = mod; } /*else * { * Mod.Mods.Add(key, mod); * }*/ SetProgress(progress, 100f, "Finish"); } else { Debug.Log("Mod: " + Id, "Could not save the mod.", Debug.Type.Error); SetProgress(progress, "Error.Save"); } } catch (Exception e) { Debug.Log("Mod: " + Id, "An error occured while saving the mod: " + e, Debug.Type.Error); SetProgress(progress, "Error.Save"); } }
static int Main(string[] args) { if (args.Length < 1) { Usage("Not enough arguments"); return ERROR_BAD_COMMAND; } // control verbosity bool quiet = false; if (args[0] == "--quiet" || args[0] == "-q") { quiet = true; logger.Level = Logger.LogLevel.WARNING; args = args.Skip(1).ToArray(); } else if (args[0] == "--debug") { logger.Level = Logger.LogLevel.DEBUG; args = args.Skip(1).ToArray(); } // again, check if we have enough arguments if (args.Length < 1) { Usage("Not enough arguments"); return ERROR_BAD_COMMAND; } // should we return an error code if pinvokes exist? bool treatPInvokeAsError = false; if (args[0] == "--treat-pinvoke-as-error") { treatPInvokeAsError = true; args = args.Skip(1).ToArray(); } // again, check if we have enough arguments if (args.Length < 1) { Usage("Not enough arguments"); return ERROR_BAD_COMMAND; } // first arg is the path to the main assembly being processed string fileName = args[0]; if (!File.Exists(fileName)) { // if the file doesn't exist, it might be a directory // TODO: handle directories if (Directory.Exists(fileName)) { logger.Error("{0} appears to be a directory; .NET assemblies only, please.", fileName); return ERROR_NOT_DOTNET; } logger.Error("Couldn't find {0}. Are you sure it exists?", fileName); return ERROR_NOT_THERE; } // check that the main file is a dot net assembly // this gives a clearer error message than the "one or more..." error try { System.Reflection.AssemblyName.GetAssemblyName(fileName); } catch (System.BadImageFormatException) { logger.Error("{0} is not a .NET assembly.", fileName); return ERROR_NOT_DOTNET; } // load module and assembly resolver ModuleDefinition module; CustomAssemblyResolver customResolver; try { // second arg and onwards should be paths to reference assemblies // instantiate custom assembly resolver that loads reference assemblies into cache // note: ONLY these assemblies will be available to the resolver customResolver = new CustomAssemblyResolver(args.Skip(1)); // load the plugin module (with the custom assembly resolver) // TODO: perhaps we should load the plugin assembly then iterate through all modules module = ModuleDefinition.ReadModule(fileName, new ReaderParameters { AssemblyResolver = customResolver }); } catch (BadImageFormatException) { logger.Error("One (or more) of the files specified is not a .NET assembly"); return ERROR_NOT_DOTNET; } catch (FileNotFoundException e) { logger.Error("Couldn't find {0}. Are you sure it exists?", e.FileName); return ERROR_NOT_THERE; } if (module.Assembly.Name.Name == "") { logger.Error ("Assembly has no name. This is unexpected."); return ERROR_UNHANDLED_EXCEPTION; } // extract cached reference assemblies from custom assembly resolver // we'll query these later to make sure we only attempt to resolve a reference when the // definition is defined in an assembly in this list IDictionary<string, AssemblyDefinition> cache = customResolver.Cache; // print assembly name logger.Info("{0}\n", module.Assembly.FullName); // print assembly references (buildtime) if (module.AssemblyReferences.Count > 0) { logger.Info("Assembly references:", module.Assembly.Name.Name); foreach (AssemblyNameReference reference in module.AssemblyReferences) { logger.Info(" {0}", reference.FullName); } } logger.Info(""); // print cached assembly names (i.e. runtime references) if (args.Length > 1) { logger.Info("Cached assemblies:"); foreach (var assembly in args.Skip(1)) { logger.Info(" {0}", AssemblyDefinition.ReadAssembly(assembly).FullName); } } else // no reference assemblies. Grab the skipping rope { logger.Warning("Empty resolution cache (no reference assemblies specified"); } logger.Info(""); // mixed-mode? bool isMixed = (module.Attributes & ModuleAttributes.ILOnly) != ModuleAttributes.ILOnly; logger.Info("Mixed-mode? {0}\n", isMixed); // global failure/pinvoke trackers for setting return code bool failure = false; bool pinvoke = false; List<TypeDefinition> types = GetAllTypesAndNestedTypes(module.Types); // iterate over all the TYPES foreach (TypeDefinition type in types) { Pretty.Class("{0}", type.FullName); // iterate over all the METHODS that have a method body foreach (MethodDefinition method in type.Methods) { Pretty.Method("{0}", method.FullName); if (!method.HasBody) // skip if no body continue; // iterate over all the INSTRUCTIONS foreach (var instruction in method.Body.Instructions) { // skip if no operand if (instruction.Operand == null) continue; logger.Debug( "Found instruction at {0} with code: {1}", instruction.Offset, instruction.OpCode.Code); string instructionString = instruction.Operand.ToString() // for sake of consistency .Replace("{", "{{").Replace("}", "}}"); // escape curly brackets // get the scope (the name of the assembly in which the operand is defined) IMetadataScope scope = GetOperandScope(instruction.Operand); if (scope != null) { // pinvoke? ModuleReference nativeModule; bool isPInvoke = IsPInvoke(instruction.Operand, out nativeModule); if (isPInvoke && nativeModule != null) { Pretty.Instruction(ResolutionStatus.PInvoke, nativeModule.Name, instructionString); pinvoke = true; continue; } // skip if scope is not in the list of cached reference assemblies if (!cache.ContainsKey(scope.Name)) { if (!quiet) Pretty.Instruction(ResolutionStatus.Skipped, scope.Name, instructionString); continue; } logger.Debug("{0} is on the list so let's try to resolve it", scope.Name); // try to resolve operand // this is the big question - does the field/method/class exist in one of // the cached reference assemblies bool success = TryResolve(instruction.Operand); if (success) { if (!quiet) Pretty.Instruction(ResolutionStatus.Success, scope.Name, instructionString); } else { Pretty.Instruction(ResolutionStatus.Failure, scope.Name, instructionString); failure = true; // set global failure (non-zero exit code) } } } } // check that all abstract methods in the base type (where appropriate) have been implemented // note: base type resolved against the referenced assemblies failure |= CheckAbstractMethods(type) == false; } // exit code if (failure) return ERROR_COMPAT; else if (pinvoke && treatPInvokeAsError) return ERROR_PINVOKE; else return 0; // a-ok }
public void Create(ProgressHandler progress = null) { var libraryPath = GetLibraryFolder(); Directory.CreateDirectory(libraryPath); /** Remove old files **/ SetProgress(progress, 0, "RemovingOldFiles"); var oldFiles = Directory.GetFiles(libraryPath); var removedFiles = 0; foreach (var file in oldFiles) { var attr = File.GetAttributes(file); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { Directory.Delete(file, true); } else { File.Delete(file); } removedFiles++; } Debug.Log("Modlib: " + Game.GameConfiguration.Id, "Removed " + removedFiles + " files and directories."); SetProgress(progress, 1f, "CreatingModToolkit"); var baseModLibPath = Configuration.GetPath("Libraries") + Path.DirectorySeparatorChar + "BaseModLib.dll"; if (!File.Exists(baseModLibPath)) { Debug.Log("Modlib: " + Game.GameConfiguration.Id, "Couldn't find BaseModLib.dll.", Debug.Type.Error); SetProgress(progress, "Error.BaseModLibNotFound"); return; } var baseModLib = ModuleDefinition.ReadModule(baseModLibPath); foreach (var type in baseModLib.Types) { var changeMethods = new List <string>(); foreach (var method in type.Methods) { if (method.HasCustomAttributes) { if (method.CustomAttributes[0].AttributeType.Name == "AddModname") { changeMethods.Add(method.Name); } } } foreach (var method in type.Methods) { if (changeMethods.Contains(method.Name)) { method.IsPrivate = false; method.IsFamily = false; method.IsAssembly = false; method.IsFamilyAndAssembly = false; method.IsPublic = true; Debug.Log("Modlib: " + Game.GameConfiguration.Id, "Changed the accessibility of " + method.FullName + " in BaseModLib.dll"); } } } var mscorlibPublicKeyToken = new byte[] { 0x7C, 0xEC, 0x85, 0xD7, 0xBE, 0xA7, 0x79, 0x8E }; var systemXmlPublicKeyToken = new byte[] { 0x31, 0xBF, 0x38, 0x56, 0xAD, 0x36, 0x4E, 0x35 }; foreach (var assemblyReference in baseModLib.AssemblyReferences) { if ((assemblyReference.Name.StartsWith("System") || assemblyReference.Name.StartsWith("mscorlib"))) { assemblyReference.Version = new System.Version("2.0.5.0"); if (assemblyReference.Name == "System.Xml.Linq") { assemblyReference.PublicKeyToken = systemXmlPublicKeyToken; } else { assemblyReference.PublicKeyToken = mscorlibPublicKeyToken; } Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed assembly reference token of " + assemblyReference.Name + " in BaseModLib.dll."); } } CreationTime = DateTime.Now; GameVersion = Game.BackupVersion.Id; ModApiVersion = Version.Descriptor; var metaXml = new XDocument(); var rootElement = new XElement("Meta"); rootElement.Add(new XElement("GameVersion", GameVersion)); rootElement.Add(new XElement("ModAPIVersion", ModApiVersion)); rootElement.Add(new XElement("CreationTime", CreationTime.Ticks + "")); metaXml.Add(rootElement); var metaResource = new EmbeddedResource("Meta", ManifestResourceAttributes.Public, Encoding.UTF8.GetBytes(metaXml.ToString())); baseModLib.Resources.Add(metaResource); baseModLib.Write(libraryPath + Path.DirectorySeparatorChar + "BaseModLib.dll"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Successfully parsed BaseModLib.dll and copied in mod library."); SetProgress(progress, 5f, "ModifyingAssemblies"); var assemblyResolver = new CustomAssemblyResolver(); assemblyResolver.AddPath(Configuration.GetPath("OriginalGameFiles") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar); assemblyResolver.AddPath(libraryPath); var searchFolders = new List <string>(); for (var i = 0; i < Game.GameConfiguration.IncludeAssemblies.Count; i++) { var assemblyPath = Configuration.GetPath("OriginalGameFiles") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.IncludeAssemblies[i]); var folder = Path.GetDirectoryName(assemblyPath); if (!searchFolders.Contains(folder)) { Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Added folder \"" + folder + "\" to assembly resolver."); searchFolders.Add(folder); } } for (var i = 0; i < Game.GameConfiguration.CopyAssemblies.Count; i++) { var assemblyPath = Configuration.GetPath("OriginalGameFiles") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.CopyAssemblies[i]); var folder = Path.GetDirectoryName(assemblyPath); if (!searchFolders.Contains(folder)) { Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Added folder \"" + folder + "\" to assembly resolver."); searchFolders.Add(folder); } } for (var i = 0; i < searchFolders.Count; i++) { assemblyResolver.AddPath(searchFolders[i]); } for (var i = 0; i < Game.GameConfiguration.IncludeAssemblies.Count; i++) { var assemblyPath = Configuration.GetPath("OriginalGameFiles") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.IncludeAssemblies[i]); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "======================================================================"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "======================== NEW ASSEMBLY ========================"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "======================================================================"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, assemblyPath); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "======================================================================"); if (File.Exists(assemblyPath)) { try { var module = ModuleDefinition.ReadModule(assemblyPath, new ReaderParameters { AssemblyResolver = assemblyResolver }); foreach (var type in module.Types) { if (string.IsNullOrEmpty(type.Namespace)) { Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Validating root namespace type " + type.FullName); } if ((string.IsNullOrEmpty(type.Namespace) || !CheckName(type.Namespace, Game.GameConfiguration.ExcludeNamespaces)) && !CheckName(type.Name, Game.GameConfiguration.ExcludeTypes) && !CheckName(type.FullName, Game.GameConfiguration.NoFamily)) { if (string.IsNullOrEmpty(type.Namespace)) { Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Processing root namespace type " + type.FullName); } if (type.IsAbstract && type.IsSealed) { type.IsAbstract = false; type.IsSealed = false; type.IsBeforeFieldInit = true; var constructor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Public | MethodAttributes.HideBySig, type.Module.TypeSystem.Void); type.Methods.Add(constructor); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Added public constructor to abstract class " + constructor.FullName); } if (type.IsNotPublic) { type.IsPublic = true; } var constructors = type.GetConstructors().ToArray(); if (constructors.Length == 0) { var constructor = new MethodDefinition(".ctor", MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Public | MethodAttributes.HideBySig, type.Module.TypeSystem.Void); type.Methods.Add(constructor); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Added public constructor " + constructor.FullName); } else { foreach (var constructor in constructors) { constructor.IsPublic = true; Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed non-public constructor " + constructor.FullName + " to public"); } } foreach (var m in type.Methods) { if (!m.IsConstructor) { if (!m.IsGetter && !m.IsSetter && !m.IsStatic) { m.IsVirtual = true; } if (m.IsPrivate) { m.IsFamily = true; Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed private method " + m.FullName + " to protectded"); } else if (m.IsAssembly) { m.IsAssembly = false; m.IsPublic = true; Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed internal method " + m.FullName + " to public"); } } } foreach (var f in type.Fields) { if (f.IsPrivate) { f.IsFamily = true; Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed private field " + f.FullName + " to protectded"); } else if (f.IsAssembly) { f.IsAssembly = false; f.IsPublic = true; Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Changed internal field " + f.FullName + " to public"); } } } } var savePath = Path.GetFullPath(libraryPath + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.IncludeAssemblies[i])); Directory.CreateDirectory(Path.GetDirectoryName(savePath)); module.Write(savePath); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Saved modified \"" + module.Name + "\" into " + savePath + ""); } catch (Exception e) { Debug.Log("ModLib: " + Game.GameConfiguration.Id, "File couldnt be parsed: \"" + assemblyPath + "\". Exception: " + e, Debug.Type.Error); SetProgress(progress, "Error.ModifyAssemblyException"); return; } Debug.Log("ModLib: " + Game.GameConfiguration.Id, "Successfully parsed file: \"" + assemblyPath + "\" and copied in mod library."); } else { SetProgress(progress, "Error.ModifyAssemblyFileNotFound"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "File not found: \"" + assemblyPath + "\".", Debug.Type.Error); return; } SetProgress(progress, 5f + (i / (float)Game.GameConfiguration.IncludeAssemblies.Count) * 75f); } SetProgress(progress, 80f, "CopyingAssemblies"); for (var i = 0; i < Game.GameConfiguration.CopyAssemblies.Count; i++) { var copyFrom = Configuration.GetPath("OriginalGameFiles") + Path.DirectorySeparatorChar + Game.GameConfiguration.Id + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.CopyAssemblies[i]); var copyTo = Path.GetFullPath(libraryPath + Path.DirectorySeparatorChar + Game.ParsePath(Game.GameConfiguration.CopyAssemblies[i])); if (File.Exists(copyFrom)) { Directory.CreateDirectory(Path.GetDirectoryName(copyTo)); File.Copy(copyFrom, copyTo, true); } else { SetProgress(progress, "Error.CopyAssemblyFileNotFound"); Debug.Log("ModLib: " + Game.GameConfiguration.Id, "File not found: \"" + copyFrom + "\".", Debug.Type.Error); return; } SetProgress(progress, 80f + (i / (float)Game.GameConfiguration.CopyAssemblies.Count) * 20f); } Exists = true; SetProgress(progress, 100f, "Finish"); }
public static void GetAssemblyLocation( Assembly oRootAssembly, ArrayBuilder oAssemblyList, AssemblyName[] SystemAssemblies, bool bCustomOnly, bool bWithDependencies, bool includeRootAssembly = true, CustomAssemblyResolver assemblyResolver = null) { if (assemblyResolver != null) { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(assemblyResolver.AssemblyResolveHandler); } try { if (!bCustomOnly || IsCustomAssembly( SystemAssemblies, oRootAssembly.GetName())) { if (includeRootAssembly) { oAssemblyList.AddIfNotExists(oRootAssembly.Location); } if (bWithDependencies) { AssemblyName[] Dependencies = oRootAssembly.GetReferencedAssemblies(); foreach (AssemblyName oAssemblyName in Dependencies) { try { if (!bCustomOnly || IsCustomAssembly( SystemAssemblies, oAssemblyName)) { Assembly oDependentAssembly = Assembly.Load(oAssemblyName); // Check for circullar references if (!oAssemblyList.Contains(oDependentAssembly.Location)) { GetAssemblyLocation(oDependentAssembly, oAssemblyList, SystemAssemblies, bCustomOnly, bWithDependencies, true, assemblyResolver); } } } catch (Exception oExc) { Log.WriteException(oExc); } } } } } finally { if (assemblyResolver != null) { AppDomain.CurrentDomain.AssemblyResolve -= new ResolveEventHandler(assemblyResolver.AssemblyResolveHandler); } } }
/// <summary>setup assembly resolution: consider all directories of /r files /// and current directory as assembly containing directories</summary> private void SetupAssemblyResolver() { ArrayList searchDirectoryList = new ArrayList(); searchDirectoryList.Add(new DirectoryInfo(".").FullName); foreach (Assembly refAsm in m_commandLine.ReferencedAssemblies) { string asmDir = new FileInfo(refAsm.Location).Directory.FullName; if (!searchDirectoryList.Contains(asmDir)) { searchDirectoryList.Add(asmDir); } } AppDomain curDomain = AppDomain.CurrentDomain; curDomain.AppendPrivatePath(curDomain.BaseDirectory); CustomAssemblyResolver resolver = new CustomAssemblyResolver(searchDirectoryList); ResolveEventHandler hndlr = new ResolveEventHandler(resolver.AssemblyResolve); curDomain.AssemblyResolve += hndlr; }
static int Main(string[] args) { if (args.Length < 1) { Usage("Not enough arguments"); return(ERROR_BAD_COMMAND); } // control verbosity if (args[0] == "--quiet" || args[0] == "-q") { quiet = true; logger.Level = Logger.LogLevel.WARNING; args = args.Skip(1).ToArray(); } else if (args[0] == "--debug") { logger.Level = Logger.LogLevel.DEBUG; args = args.Skip(1).ToArray(); } // again, check if we have enough arguments if (args.Length < 1) { Usage("Not enough arguments"); return(ERROR_BAD_COMMAND); } // should we return an error code if pinvokes exist? bool treatPInvokeAsError = false; if (args[0] == "--treat-pinvoke-as-error") { treatPInvokeAsError = true; args = args.Skip(1).ToArray(); } // again, check if we have enough arguments if (args.Length < 1) { Usage("Not enough arguments"); return(ERROR_BAD_COMMAND); } // first arg is the path to the main assembly being processed string fileName = args[0]; if (!File.Exists(fileName)) { // if the file doesn't exist, it might be a directory // TODO: handle directories if (Directory.Exists(fileName)) { logger.Error("{0} appears to be a directory; .NET assemblies only, please.", fileName); return(ERROR_NOT_DOTNET); } logger.Error("Couldn't find {0}. Are you sure it exists?", fileName); return(ERROR_NOT_THERE); } // check that the main file is a dot net assembly // this gives a clearer error message than the "one or more..." error try { System.Reflection.AssemblyName.GetAssemblyName(fileName); } catch (System.BadImageFormatException) { logger.Error("{0} is not a .NET assembly.", fileName); return(ERROR_NOT_DOTNET); } // load module and assembly resolver ModuleDefinition module; CustomAssemblyResolver customResolver; try { // second arg and onwards should be paths to reference assemblies // instantiate custom assembly resolver that loads reference assemblies into cache // note: ONLY these assemblies will be available to the resolver customResolver = new CustomAssemblyResolver(args.Skip(1)); // load the plugin module (with the custom assembly resolver) // TODO: perhaps we should load the plugin assembly then iterate through all modules module = ModuleDefinition.ReadModule(fileName, new ReaderParameters { AssemblyResolver = customResolver }); } catch (BadImageFormatException) { logger.Error("One (or more) of the files specified is not a .NET assembly"); return(ERROR_NOT_DOTNET); } catch (FileNotFoundException e) { logger.Error("Couldn't find {0}. Are you sure it exists?", e.FileName); return(ERROR_NOT_THERE); } if (module.Assembly.Name.Name == "") { logger.Error("Assembly has no name. This is unexpected."); return(ERROR_UNHANDLED_EXCEPTION); } // extract cached reference assemblies from custom assembly resolver // we'll query these later to make sure we only attempt to resolve a reference when the // definition is defined in an assembly in this list cache = customResolver.Cache; // print assembly name logger.Info("{0}\n", module.Assembly.FullName); // print assembly references (buildtime) if (module.AssemblyReferences.Count > 0) { logger.Info("Assembly references:", module.Assembly.Name.Name); foreach (AssemblyNameReference reference in module.AssemblyReferences) { logger.Info(" {0}", reference.FullName); } } logger.Info(""); // print cached assembly names (i.e. runtime references) if (args.Length > 1) { logger.Info("Cached assemblies:"); foreach (var assembly in args.Skip(1)) { logger.Info(" {0}", AssemblyDefinition.ReadAssembly(assembly).FullName); } } else // no reference assemblies. Grab the skipping rope { logger.Warning("Empty resolution cache (no reference assemblies specified)"); } logger.Info(""); // mixed-mode? bool isMixed = (module.Attributes & ModuleAttributes.ILOnly) != ModuleAttributes.ILOnly; logger.Info("Mixed-mode? {0}\n", isMixed); // global failure/pinvoke trackers for setting return code bool failure = false; bool pinvoke = false; List <TypeDefinition> types = GetAllTypesAndNestedTypes(module.Types); // iterate over all the TYPES foreach (TypeDefinition type in types) { Pretty.Class("{0}", type.FullName); // iterate over all the METHODS that have a method body foreach (MethodDefinition method in type.Methods) { Pretty.Method("{0}", method.FullName); if (!method.HasBody) // skip if no body { continue; } // iterate over all the INSTRUCTIONS foreach (var instruction in method.Body.Instructions) { // skip if no operand if (instruction.Operand == null) { continue; } logger.Debug( "Found instruction at {0} with code: {1}", instruction.Offset, instruction.OpCode.Code); string instructionString = instruction.Operand.ToString() // for sake of consistency .Replace("{", "{{").Replace("}", "}}"); // escape curly brackets // get the scope (the name of the assembly in which the operand is defined) IMetadataScope scope = GetOperandScope(instruction.Operand); if (scope != null) { // pinvoke? ModuleReference nativeModule; bool isPInvoke = IsPInvoke(instruction.Operand, out nativeModule); if (isPInvoke && nativeModule != null) { Pretty.Instruction(ResolutionStatus.PInvoke, nativeModule.Name, instructionString); pinvoke = true; continue; } // skip if scope is not in the list of cached reference assemblies if (!cache.ContainsKey(scope.Name)) { Pretty.Instruction(ResolutionStatus.Skipped, scope.Name, instructionString); continue; } logger.Debug("{0} is on the list so let's try to resolve it", scope.Name); logger.Debug(instruction.Operand.ToString()); // try to resolve operand // this is the big question - does the field/method/class exist in one of // the cached reference assemblies bool success = TryResolve(instruction.Operand, type); if (success || CheckMultidimensionalArray(instruction, method, type, scope)) { Pretty.Instruction(ResolutionStatus.Success, scope.Name, instructionString); } else { Pretty.Instruction(ResolutionStatus.Failure, scope.Name, instructionString); failure = true; // set global failure (non-zero exit code) } } } } // check that all abstract methods in the base type (where appropriate) have been implemented // note: base type resolved against the referenced assemblies failure |= CheckAbstractMethods(type) == false; } // exit code if (failure) { return(ERROR_COMPAT); } if (pinvoke && treatPInvokeAsError) { return(ERROR_PINVOKE); } return(0); // a-ok }
/// <summary> /// Preloads a test for a process, this just sets the test object to the appropriate path. /// </summary> /// <param name="test"></param> /// <param name="paths"></param> private void TestPreLoader_Process(ReliabilityTest test, string[] paths) { Console.WriteLine("Preloading for process mode"); string realpath = ReliabilityConfig.ConvertPotentiallyRelativeFilenameToFullPath(test.BasePath, test.Assembly); Debug.Assert(test.TestObject == null); if (File.Exists(realpath)) { test.TestObject = realpath; } else if (File.Exists((string)test.Assembly)) { test.TestObject = test.Assembly; } else { foreach (string path in paths) { string fullPath = ReliabilityConfig.ConvertPotentiallyRelativeFilenameToFullPath(path, (string)test.Assembly); if (File.Exists(fullPath)) { test.TestObject = fullPath; break; } } } if (test.TestObject == null) { Console.WriteLine("Couldn't find path for {0}", test.Assembly); } #if PROJECTK_BUILD if (test.EntryPointMethod == null) { CustomAssemblyResolver resolver = new CustomAssemblyResolver(); // test.Assembly is with the extension. LoadFromAssemblyName needs it without. string strAssemblyNameWithoutExt = Path.ChangeExtension(test.Assembly, null); Assembly testAssembly = resolver.LoadFromAssemblyName(new AssemblyName(strAssemblyNameWithoutExt)); Type[] testTypes = AssemblyExtensions.GetTypes(testAssembly); MethodInfo methodInfo = null; if (testTypes != null) { foreach (Type t in testTypes) { methodInfo = t.GetMethod("Main"); if (methodInfo != null) { //Console.WriteLine(t.FullName + " contains the entrypoint"); break; } } } test.EntryPointMethod = methodInfo; } #endif }
/// <summary> /// set up the AppDomain for the type to map in the containing assembly assemblyToMap /// </summary> /// <param name="assemblyToMap">the assembly containing the type to map</param> private static void SetupAppDomain(Assembly assemblyToMap) { AppDomain curDomain = AppDomain.CurrentDomain; curDomain.AppendPrivatePath(curDomain.BaseDirectory); // directory of the assembly containing the typ to map // make sure to probe in directory containing type to map, if not found itself ... string directoryName = new FileInfo(assemblyToMap.Location).DirectoryName; CustomAssemblyResolver resolver = new CustomAssemblyResolver(directoryName); ResolveEventHandler hndlr = new ResolveEventHandler(resolver.AssemblyResolve); curDomain.AssemblyResolve += hndlr; }