/// <summary> /// Recupera os redirecionamentos das versões. /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static Dictionary <string, List <Redirection> > GetVersionRedirections(string fileName) { var ret = new Dictionary <string, List <Redirection> >(); var config = new System.Xml.XmlDocument(); config.Load(fileName); foreach (System.Xml.XmlNode dependentAssemblyTag in config.GetElementsByTagName("dependentAssembly")) { if (((dependentAssemblyTag.ParentNode.Name == "assemblyBinding") && (dependentAssemblyTag.ParentNode.ParentNode != null)) && (dependentAssemblyTag.ParentNode.ParentNode.Name == "runtime")) { Redirection red = new Redirection(); foreach (System.Xml.XmlNode node in dependentAssemblyTag.ChildNodes) { if (node.Name == "assemblyIdentity") { var name = new System.Reflection.AssemblyName(node.Attributes["name"].Value); if (node.Attributes["processorArchitecture"] != null) { name.ProcessorArchitecture = (System.Reflection.ProcessorArchitecture)Enum.Parse(typeof(System.Reflection.ProcessorArchitecture), node.Attributes["processorArchitecture"].Value, true); } red.AssemblyIdentity = name; continue; } if (node.Name == "bindingRedirect") { BindingRedirect redirect = new BindingRedirect(); if (node.Attributes["oldVersion"] != null) { System.Xml.XmlAttribute attr = node.Attributes["oldVersion"]; if (attr.Value.Contains("-")) { string[] versions = attr.Value.Split(new char[] { '-' }); redirect.OldVersionMin = new Version(versions[0]); redirect.OldVersionMax = new Version(versions[1]); } else { redirect.OldVersionMax = new Version(attr.Value); redirect.OldVersionMin = new Version(attr.Value); } } if (node.Attributes["newVersion"] != null) { redirect.NewVersion = new Version(node.Attributes["newVersion"].Value); } red.BindingRedirection = redirect; } } if (ret.ContainsKey(red.AssemblyIdentity.Name)) { ret[red.AssemblyIdentity.Name].Add(red); } else { var aux = new List <Redirection>(); aux.Add(red); ret.Add(red.AssemblyIdentity.Name, aux); } } } if (ret.Count > 0) { return(ret); } return(null); }
/// <summary> /// Analiza o assembly informado. /// </summary> /// <param name="asmName"></param> /// <param name="parent"></param> /// <param name="domain"></param> /// <param name="throwWhenMissing"></param> private void AnalyzeAssembly(System.Reflection.AssemblyName asmName, AsmData parent, AppDomain domain, bool throwWhenMissing) { bool redirectionApplied = false; string additionalInfo = string.Empty; System.Reflection.AssemblyName analyzedAssembly = asmName; Dictionary <string, List <Redirection> > asmRedirections = this.GetRedirections(asmName); if (asmRedirections != null) { analyzedAssembly = Redirection.GetCorrectAssemblyName(asmName, asmRedirections); redirectionApplied = analyzedAssembly.Version != asmName.Version; } bool invalid = false; bool isInGac = false; AsmData gacAssemblyData = null; System.Reflection.Assembly asm = null; string file = analyzedAssembly.FullName; try { if (_gac != null) { foreach (AsmData item in _gac) { if (item.AssemblyFullName.Contains(analyzedAssembly.FullName)) { isInGac = true; gacAssemblyData = item; break; } } } } catch (Exception) { } if (_cache.ContainsKey(analyzedAssembly.FullName) && !_parentsStack.Contains(analyzedAssembly.FullName)) { AsmData cachedItem = _cache[analyzedAssembly.FullName]; parent.References.Add(cachedItem); return; } string asmLocation = null; AsmData currentAsmData = null; bool gacAssemblySet = false; if (!isInGac) { string extAdd = ""; if (file.LastIndexOf(", Version=") != -1) { file = file.Substring(0, file.LastIndexOf(", Version=")); } if ((System.IO.Path.GetExtension(file) != ".exe") && (System.IO.Path.GetExtension(file) != ".dll")) { extAdd = ".dll"; } string tmpPath = this.FindPath(parent, file, extAdd, analyzedAssembly.FullName); if (System.IO.File.Exists(tmpPath)) { TryLoad(domain, ref additionalInfo, ref invalid, ref asm, tmpPath); } asmLocation = tmpPath; } else { try { using (var stream = System.IO.File.OpenRead(gacAssemblyData.Path)) { var raw = new byte[stream.Length]; stream.Read(raw, 0, raw.Length); asm = domain.Load(raw); } asmLocation = gacAssemblyData.Path; if (!gacAssemblyData.AssemblyFullName.Contains(asm.FullName) && !asm.FullName.Contains(gacAssemblyData.AssemblyFullName)) { currentAsmData = gacAssemblyData; gacAssemblySet = true; asm = null; } } catch (System.IO.FileNotFoundException ex) { additionalInfo = "File " + ex.FileName + " could not be found."; } catch (System.IO.FileLoadException ex) { additionalInfo = "File " + ex.FileName + " could not be loaded. " + ex.FusionLog; } catch (BadImageFormatException ex) { additionalInfo = "Bad image format. " + ex.ToString() + "\r\n" + ex.FusionLog; } } if (currentAsmData == null) { currentAsmData = new AsmData(analyzedAssembly.Name, (asm == null) ? "" : System.IO.Path.GetFullPath(asmLocation)); currentAsmData.AssemblyFullName = analyzedAssembly.FullName; currentAsmData.Validity = AsmData.AsmValidity.Invalid; currentAsmData.InvalidAssemblyDetails = additionalInfo; currentAsmData.Architecture = this.GetArchitecture(currentAsmData.Path); } if ((!gacAssemblySet && (asm != null)) && (analyzedAssembly.Version != asm.GetName().Version)) { string message = string.Concat(new object[] { "Assembly was found with version ", asm.GetName().Version, " but parent references ", analyzedAssembly.Version }); currentAsmData.AdditionalInfo = message; asm = null; } if ((!gacAssemblySet && (asm != null)) && !invalid) { try { object[] attributes = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyProductAttribute), false); if (attributes.Length > 0) { currentAsmData.AssemblyProductName = ((System.Reflection.AssemblyProductAttribute)attributes[0]).Product; } } catch (InvalidOperationException) { currentAsmData.AssemblyProductName = "Product name could not be read."; } catch (System.IO.FileNotFoundException) { currentAsmData.AssemblyProductName = "Product name could not be read. Assembly was loaded but later could not be found."; } catch (Exception ex) { currentAsmData.AssemblyProductName = "Product name could not be read. Error: " + ex.Message; } } parent.References.Add(currentAsmData); if (invalid) { currentAsmData.Validity = AsmData.AsmValidity.ReferencesOnly; } if (_parentsStack.Contains(analyzedAssembly.FullName)) { string circ = this.GetParentsString(); currentAsmData.Validity = AsmData.AsmValidity.CircularDependency; if (!_circularDependencyWarningShown) { _circularDependencyWarningShown = true; } return; } if (asm != null) { currentAsmData.Path = asmLocation; currentAsmData.AssemblyFullName = asm.FullName; if (!invalid) { currentAsmData.Validity = redirectionApplied ? AsmData.AsmValidity.Redirected : AsmData.AsmValidity.Valid; currentAsmData.OriginalVersion = redirectionApplied ? asmName.Version.ToString() : string.Empty; } if (((asm.CodeBase != null) && System.Runtime.InteropServices.RuntimeEnvironment.FromGlobalAccessCache(asm)) && (currentAsmData.AssemblyProductName == "Microsoft\x00ae .NET Framework")) { return; } if ((currentAsmData.Validity != AsmData.AsmValidity.Invalid) && !this.ApplyArchitecture(currentAsmData.Architecture)) { currentAsmData.Validity = AsmData.AsmValidity.ReferencesOnly; currentAsmData.AdditionalInfo = currentAsmData.AdditionalInfo + "\r\nProcessorArchitecture mismatch"; } _parentsStack.Push(currentAsmData.AssemblyFullName); _cache.Add(analyzedAssembly.FullName, currentAsmData); foreach (System.Reflection.AssemblyName n in asm.GetReferencedAssemblies()) { this.AnalyzeAssembly(n, currentAsmData, domain, throwWhenMissing); } _parentsStack.Pop(); if (!System.IO.File.Exists(currentAsmData.Path)) { return; } } if (throwWhenMissing && !gacAssemblySet) { throw new Exception("returning from analysis"); } }
/// <summary> /// Analiza o assembly informado. /// </summary> /// <param name="assemblyName"></param> /// <param name="throwWhenMissing"></param> /// <returns></returns> public AsmData AnalyzeRootAssembly(string assemblyName, bool throwWhenMissing) { _cache = new Dictionary <string, AsmData>(); _circularDependencyWarningShown = false; _parentsStack = new Stack <string>(); _workingDir = Environment.CurrentDirectory; string fullPath = System.IO.Path.GetFullPath(assemblyName); AsmData ret = new AsmData(assemblyName, fullPath); var domain = AppDomain.CurrentDomain; try { if (!System.IO.File.Exists(assemblyName)) { ret.Path = ""; ret.Validity = AsmData.AsmValidity.Invalid; ret.AssemblyFullName = ""; return(ret); } System.Reflection.Assembly asm = null; try { using (var stream = System.IO.File.OpenRead(fullPath)) { var raw = new byte[stream.Length]; stream.Read(raw, 0, raw.Length); try { asm = domain.Load(raw); ret.Validity = AsmData.AsmValidity.Valid; } catch (Exception) { asm = System.Reflection.Assembly.ReflectionOnlyLoad(raw); ret.Validity = AsmData.AsmValidity.ReferencesOnly; } } } catch (Exception) { asm = null; ret.Validity = AsmData.AsmValidity.Invalid; } if (asm != null) { ret.AssemblyFullName = asm.FullName; ret.Path = fullPath; ret.Architecture = asm.GetName().ProcessorArchitecture; _currentLoadedArchitecture = ret.Architecture; string tempName = asm.GetName().Name; if (!this.assemblyNameToPathMap.ContainsKey(tempName)) { this.assemblyNameToPathMap.Add(tempName, asm.Location); } string cfgFilePath = Redirection.FindConfigFile(ret.Path); if (!string.IsNullOrEmpty(cfgFilePath) && !_allVersionRedirections.ContainsKey(fullPath)) { var versionRedirections = Redirection.GetVersionRedirections(cfgFilePath); PathRedirection pathRedirections = Redirection.GetPathRedirections(ret.AssemblyFullName, cfgFilePath); _allVersionRedirections.Add(fullPath, versionRedirections); _probingPaths.Add(ret.AssemblyFullName, pathRedirections); } var references = asm.GetReferencedAssemblies().ToList(); var fileName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(fullPath), string.Format("{0}.XmlSerializers{1}", System.IO.Path.GetFileNameWithoutExtension(fullPath), System.IO.Path.GetExtension(fullPath))); if (System.IO.File.Exists(fileName)) { references.Add(System.Reflection.AssemblyName.GetAssemblyName(fileName)); } _totalReferencedAssemblies = references.Count; _parentsStack.Push(ret.AssemblyFullName); foreach (System.Reflection.AssemblyName asmName in references) { this.AnalyzeAssembly(asmName, ret, domain, throwWhenMissing); _assembliesFinished++; if (_bgWorker != null) { _bgWorker.ReportProgress((100 * _assembliesFinished) / _totalReferencedAssemblies); } } _parentsStack.Pop(); } } finally { } return(ret); }
/// <summary> /// Recupera os redirecionamentos do Framework. /// </summary> /// <param name="assembliesInGac"></param> /// <param name="progressDialog"></param> /// <returns></returns> public Dictionary <string, List <Redirection> > GetFrameworkRedirections(List <AsmData> assembliesInGac, IAssemblyAnalyzerObserver progressDialog) { Dictionary <string, List <Redirection> > redirections = new Dictionary <string, List <Redirection> >(); try { progressDialog.ReportProgress(0, "Checking .NET Framework libraries...".GetFormatter()); int assembliesCount = 0; var upgrades = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\Policy\Upgrades"); if (upgrades == null) { return(redirections); } var bindingRedirects = new List <BindingRedirect>(); foreach (string targetVersion in upgrades.GetValueNames()) { string sourceVersion = upgrades.GetValue(targetVersion) as string; BindingRedirect redirect = new BindingRedirect(); redirect.NewVersion = new Version(targetVersion); if (sourceVersion.Contains("-")) { string[] versions = sourceVersion.Split(new char[] { '-' }); redirect.OldVersionMin = new Version(versions[0]); redirect.OldVersionMax = new Version(versions[1]); } else { redirect.OldVersionMax = new Version(sourceVersion); redirect.OldVersionMin = new Version(sourceVersion); } bindingRedirects.Add(redirect); } upgrades.Close(); foreach (AsmData assemblyDescription in assembliesInGac) { System.Reflection.Assembly asm = null; try { asm = System.Reflection.Assembly.Load(assemblyDescription.Name); } catch (Exception) { continue; } var assemblyName = asm.GetName(false); if (!redirections.ContainsKey(assemblyName.Name)) { object[] attributes = null; try { attributes = asm.GetCustomAttributes(typeof(System.Reflection.AssemblyProductAttribute), false); } catch (Exception) { } if ((attributes != null) && (attributes.Length > 0)) { var productAttribute = attributes[0] as System.Reflection.AssemblyProductAttribute; if ((productAttribute != null) && (productAttribute.Product == "Microsoft\x00ae .NET Framework")) { foreach (BindingRedirect bindingRedirect in bindingRedirects) { Redirection redirection = new Redirection(); redirection.AssemblyIdentity = assemblyName; redirection.BindingRedirection = bindingRedirect; if (assemblyName.Version <= redirection.BindingRedirection.NewVersion) { redirection.BindingRedirection.NewVersion = assemblyName.Version; } if (redirections.ContainsKey(redirection.AssemblyIdentity.Name)) { redirections[redirection.AssemblyIdentity.Name].Add(redirection); } else { var aux = new List <Redirection>(); aux.Add(redirection); redirections.Add(redirection.AssemblyIdentity.Name, aux); } } } } assembliesCount++; progressDialog.ReportProgress((int)((100.0 * assembliesCount) / ((double)assembliesInGac.Count)), "Checking .NET Framework libraries...".GetFormatter()); if (progressDialog.CancellationPending) { redirections.Clear(); return(redirections); } } } } catch (Exception) { } return(redirections); }