/// <summary>
        /// Localiza o caminho do arquivo.
        /// </summary>
        /// <param name="parent"></param>
        /// <param name="file"></param>
        /// <param name="extAdd"></param>
        /// <param name="currentFullName"></param>
        /// <returns></returns>
        private string FindPath(AsmData parent, string file, string extAdd, string currentFullName)
        {
            string          result;
            PathRedirection redirects;
            string          parentDir = _workingDir;

            if ((parent != null) && !string.IsNullOrEmpty(parent.Path))
            {
                parentDir = System.IO.Path.GetDirectoryName(parent.Path);
            }
            string tmpPath = file + extAdd;

            if (System.IO.File.Exists(tmpPath))
            {
                return(tmpPath);
            }
            tmpPath = System.IO.Path.Combine(parentDir, file + extAdd);
            if (System.IO.File.Exists(tmpPath))
            {
                return(tmpPath);
            }
            string ret = System.IO.Path.Combine(parentDir, file + extAdd);

            if (!_probingPaths.TryGetValue(parent.AssemblyFullName, out redirects))
            {
                return(ret);
            }
            foreach (string currentDir in redirects.Directories)
            {
                string targetDir = currentDir;
                if (!System.IO.Path.IsPathRooted(currentDir))
                {
                    targetDir = System.IO.Path.Combine(parentDir, currentDir);
                }
                if (System.IO.File.Exists(System.IO.Path.Combine(targetDir, file + extAdd)))
                {
                    string targetPath = System.IO.Path.Combine(targetDir, file + extAdd);
                    return(targetPath);
                }
            }
            result = ret;
            return(result);
        }
        /// <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>
        /// 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");
            }
        }