internal DnSpyFile AddFile(DnSpyFile newFile, bool canAdd, bool delayLoad, bool canDispose = true) { lock (lockObj) { var file = FindByKey_NoLock(newFile.Key); if (file != null) { if (canDispose && newFile != file) { newFile.Dispose(); } return(file); } return(ForceAddFileToList_NoLock(newFile, canAdd, delayLoad, -1, canDispose)); } }
DnSpyFile DelayLoadFile_NoLock(DnSpyFile newFile, int index, bool canDispose) { bool startThread; lock (delayLoadedFiles) { var key = newFile.Key; Tuple <DnSpyFile, int> info; if (delayLoadedFiles.TryGetValue(key, out info)) { if (canDispose && info.Item1 != newFile) { newFile.Dispose(); } return(info.Item1); } delayLoadedFiles.Add(key, Tuple.Create(newFile, index)); startThread = delayLoadedFiles.Count == 1; } if (startThread) { options.Dispatcher.BeginInvoke(DispatcherPrio.Loaded, () => DelayLoadFileMainThread()); } return(newFile); }
public DnSpyFile Resolve(IAssembly assembly, ModuleDef sourceModule = null, bool delayLoad = false) { FrameworkRedirect.ApplyFrameworkRedirect(ref assembly, sourceModule); if (assembly.IsContentTypeWindowsRuntime) { return(ResolveWinMD(assembly, sourceModule, delayLoad)); } // WinMD files have a reference to mscorlib but its version is always 255.255.255.255 // since mscorlib isn't really loaded. The resolver only loads exact versions, so // we must change the version or the resolve will fail. if (assembly.Name == "mscorlib" && assembly.Version == invalidMscorlibVersion) { assembly = new AssemblyNameInfo(assembly) { Version = newMscorlibVersion } } ; return(ResolveNormal(assembly, sourceModule, delayLoad)); } DnSpyFile ResolveNormal(IAssembly assembly, ModuleDef sourceModule, bool delayLoad) { var existingFile = fileList.FindAssembly(assembly); if (existingFile != null) { return(existingFile); } var file = LookupFromSearchPaths(assembly, sourceModule, true); if (file != null) { return(fileList.AddFile(file, fileList.AssemblyLoadEnabled, delayLoad)); } if (fileList.UseGAC) { var gacFile = GacInterop.FindAssemblyInNetGac(assembly); if (gacFile != null) { return(fileList.GetOrCreate(gacFile, fileList.AssemblyLoadEnabled, true, delayLoad)); } foreach (var path in GacInfo.OtherGacPaths) { file = TryLoadFromDir(assembly, true, path); if (file != null) { return(fileList.AddFile(file, fileList.AssemblyLoadEnabled, delayLoad)); } } } file = LookupFromSearchPaths(assembly, sourceModule, false); if (file != null) { return(fileList.AddFile(file, fileList.AssemblyLoadEnabled, delayLoad)); } return(null); } DnSpyFile LookupFromSearchPaths(IAssembly asmName, ModuleDef sourceModule, bool exactCheck) { DnSpyFile file; string sourceModuleDir = null; if (sourceModule != null && File.Exists(sourceModule.Location)) { sourceModuleDir = Path.GetDirectoryName(sourceModule.Location); file = TryLoadFromDir(asmName, exactCheck, sourceModuleDir); if (file != null) { return(file); } } var ary = asmSearchPathsArray; foreach (var path in ary) { file = TryLoadFromDir(asmName, exactCheck, path); if (file != null) { return(file); } } return(null); } DnSpyFile TryLoadFromDir(IAssembly asmName, bool exactCheck, string dirPath) { string baseName; try { baseName = Path.Combine(dirPath, asmName.Name); } catch (ArgumentException) { // eg. invalid chars in asmName.Name return(null); } return(TryLoadFromDir2(asmName, exactCheck, baseName + ".dll") ?? TryLoadFromDir2(asmName, exactCheck, baseName + ".exe")); } DnSpyFile TryLoadFromDir2(IAssembly asmName, bool exactCheck, string filename) { if (!File.Exists(filename)) { return(null); } DnSpyFile file = null; bool error = true; try { file = fileList.CreateDnSpyFile(filename); file.IsAutoLoaded = true; var asm = file.AssemblyDef; if (asm == null) { return(null); } bool b = exactCheck ? AssemblyNameComparer.CompareAll.Equals(asmName, asm) : AssemblyNameComparer.NameAndPublicKeyTokenOnly.Equals(asmName, asm); if (!b) { return(null); } error = false; return(file); } finally { if (error) { if (file != null) { file.Dispose(); } } } } DnSpyFile ResolveWinMD(IAssembly assembly, ModuleDef sourceModule, bool delayLoad) { var existingFile = fileList.FindAssembly(assembly); if (existingFile != null) { return(existingFile); } foreach (var winmdPath in GacInfo.WinmdPaths) { string file; try { file = Path.Combine(winmdPath, assembly.Name + ".winmd"); } catch (ArgumentException) { continue; } if (File.Exists(file)) { return(fileList.GetOrCreate(file, fileList.AssemblyLoadEnabled, true, delayLoad)); } } return(null); } }