/// <summary>
        /// Loads the project.
        /// </summary>
        /// <returns></returns>
        public VSProject LoadProject()
        {
            if (this.project == null)
            {
                // NOTE: if using XmlReader, property $(MSBuildProjectDirectory) is set to executable location, not project
                //using (XmlReader reader = new XmlTextReader(projectLocation))
                {
                    this.projectDocument = new Microsoft.Build.Evaluation.Project(/*reader*/projectLocation);
                    
                    this.project = new VSProject();
                    this.project.ProjectFileLocation = projectLocation;

                    this.project.ProjectId = new Guid(this.GetEvaluatedProperty(this.projectDocument, "ProjectGuid", true));
                    this.project.AssemblyName = this.GetEvaluatedProperty(this.projectDocument, "AssemblyName", false);
                    this.project.RootNamespace = this.GetEvaluatedProperty(this.projectDocument, "RootNamespace", false);
                    string outputTypeProperty = this.GetEvaluatedProperty(this.projectDocument, "OutputType", false);
                    this.project.OutputType = (VSProjectOutputType)Enum.Parse(typeof(VSProjectOutputType), outputTypeProperty, true);
                    this.project.OutputPath = this.GetEvaluatedProperty(this.projectDocument, "OutputPath", false);
                    this.project.AssemblyOriginatorKeyFile = this.GetEvaluatedProperty(this.projectDocument, "AssemblyOriginatorKeyFile", true);

                    if (string.IsNullOrEmpty(project.AssemblyName))
                        project.AssemblyName = project.RootNamespace;
                    
                    string projectFileFolder = Path.GetDirectoryName(projectLocation) ?? ".";
                    this.outputFolder = Path.GetFullPath(FileSystem.PathHelper.PathCombine(projectFileFolder, this.project.OutputPath));
                    this.project.ResolvedOutput = FileSystem.PathHelper.PathCombine(this.outputFolder, this.project.AssemblyName);

                    if (this.project.OutputType == VSProjectOutputType.Exe || this.project.OutputType == VSProjectOutputType.WinExe)
                        this.project.ResolvedOutput += ".exe";
                    else
                        this.project.ResolvedOutput += ".dll";
                    
                    this.fileReferences = new List<VSProjectReference>(50);
                    this.projectReferences = new List<VSProjectReference>(5);
                    
                    this.GetReferences(this.projectDocument, ref this.fileReferences, ref this.projectReferences);
                    this.silverlightProjectReferences = this.GetSilverlightReferences(this.projectDocument);

                    List<VSProjectReference> references = new List<VSProjectReference>(fileReferences.Count + projectReferences.Count + silverlightProjectReferences.Count);
                    references.AddRange(fileReferences);
                    references.AddRange(projectReferences);
                    references.AddRange(silverlightProjectReferences);
                    project.References = references.ToArray();

                    this.includeFiles = this.GetIncludedFiles(this.projectDocument);

                    this.project.IsLauncher = this.project.OutputType != VSProjectOutputType.Library;
                    var webconfig = Path.Combine(projectFileFolder, "Web.config");
                    if (File.Exists(webconfig))
                        this.project.IsLauncher = true;
                }
            }

            return this.project;
        }
        /// <summary>
        /// Loads the project.
        /// </summary>
        /// <returns></returns>
        public VSProject LoadProject()
        {
            if (this.project == null)
            {
                this.projectDocument = new XmlDocument();
                this.projectDocument.Load(projectLocation);

                this.project = new VSProject();
                this.project.ProjectFileLocation = projectLocation;

                this.project.ProjectId = new Guid(SelectSingleValue(this.projectDocument, "ProjectGuid", true));
                this.project.AssemblyName = SelectSingleValue(this.projectDocument, "AssemblyName");
                this.project.RootNamespace = SelectSingleValue(this.projectDocument, "RootNamespace", true);
                string outputTypeProperty = SelectSingleValue(this.projectDocument, "OutputType", true);
                this.project.OutputType = (VSProjectOutputType) Enum.Parse(typeof (VSProjectOutputType), outputTypeProperty, true);
                this.project.OutputPath = SelectSingleValue(this.projectDocument, "OutputPath");
                this.project.AssemblyOriginatorKeyFile = SelectSingleValue(this.projectDocument, "AssemblyOriginatorKeyFile");

                if (string.IsNullOrEmpty(project.AssemblyName))
                    project.AssemblyName = project.RootNamespace;

                string projectFileFolder = Path.GetDirectoryName(projectLocation) ?? ".";
                this.outputFolder = Path.GetFullPath(FileSystem.PathHelper.PathCombine(projectFileFolder, this.project.OutputPath));
                this.project.ResolvedOutput = FileSystem.PathHelper.PathCombine(this.outputFolder, this.project.AssemblyName);

                if (this.project.OutputType == VSProjectOutputType.Exe || this.project.OutputType == VSProjectOutputType.WinExe)
                    this.project.ResolvedOutput += ".exe";
                else
                    this.project.ResolvedOutput += ".dll";

                this.fileReferences = GetFileReferences(this.projectDocument);
                this.projectReferences = GetProjectReferences(this.projectDocument);
                this.silverlightProjectReferences = GetSilverlightProjectReferences(this.projectDocument);

                List<VSProjectReference> references = new List<VSProjectReference>(fileReferences.Count + projectReferences.Count + silverlightProjectReferences.Count);
                references.AddRange(fileReferences);
                references.AddRange(projectReferences);
                references.AddRange(silverlightProjectReferences);
                project.References = references.ToArray();

                this.includeFiles = this.GetIncludedFiles();

                this.project.IsLauncher = this.project.OutputType != VSProjectOutputType.Library;
                var webconfig = Path.Combine(projectFileFolder, "Web.config");
                if (File.Exists(webconfig))
                    this.project.IsLauncher = true;
            }

            return this.project;
        }
        private List<Guid> GetCurrentProjectReferences(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, HashSet<string> thirdPartyFileMap, HashSet<string> usedThirdParties, List<Guid> checkedProjects)
        {
            ReferenceCacheItem cacheItem;
            if (!ProjectReferenceCache.TryGetValue(project.ProjectId, out cacheItem))
            {
                if (checkedProjects.Contains(project.ProjectId))
                {
                    StringBuilder builder = new StringBuilder();

                    for (int i = checkedProjects.Count - 1; i >= 0; i--)
                    {
                        Guid checkedProject = checkedProjects[i];
                        builder.Insert(0, projectLoader.GetProjectById(checkedProject).ProjectFileLocation + Environment.NewLine);
                        if (checkedProject == project.ProjectId)
                            break;
                    }

                    builder.AppendLine(project.ProjectFileLocation);

                    throw new SolutionGeneratorException("Circular reference detected! {1}Projects: {1}{0}", builder, Environment.NewLine);
                }
                checkedProjects.Add(project.ProjectId);

                cacheItem = new ReferenceCacheItem
                {
                    References = new List<Guid>(),
                    UsedThirdParties = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
                };

                if (project.References != null)
                {
                    List<VSProject> referencedProjects = new List<VSProject>();
                    foreach (VSProjectReference reference in project.References)
                    {
                        if (thirdPartyFileMap.Contains(reference.ResolvedHintPath))
                        {
                            cacheItem.UsedThirdParties.Add(reference.ResolvedHintPath);
                            continue;
                        }

                        if (SystemReferenceFileMap.Contains(reference.ResolvedInclude))
                        {
                            continue;
                        }

                        if (reference.ResolvedInclude.StartsWith("Microsoft.", StringComparison.InvariantCultureIgnoreCase))
                        {
                            continue;
                        }

                        ResolveProject(projectSetup, projectLoader, project, reference, referencedProjects);
                    }

                    foreach (VSProject referencedProject in referencedProjects)
                    {
                        if (!cacheItem.References.Contains(referencedProject.ProjectId))
                            cacheItem.References.Add(referencedProject.ProjectId);
                    }
                }

                //cacheItem.UsedThirdParties.UnionWith(usedThirdParties);
                ProjectReferenceCache.Add(project.ProjectId, cacheItem);
            }

            usedThirdParties.UnionWith(cacheItem.UsedThirdParties);
            return cacheItem.References;
        }
        private void ResolveProject(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, VSProjectReference reference, List<VSProject> referencedProjects)
        {
            VSProject vsProject;
            if (reference.IsProjectReference)
            {
                // resolve by ID
                vsProject = projectLoader.GetProjectById(reference.ProjectReferenceId);
            }
            else if (reference.IsSilverlightReference)
            {
                vsProject = projectLoader.GetProjectById(reference.ProjectReferenceId);
            }
            else
            {
                // resolve by output path
                vsProject = projectLoader.GetProjectByOutput(reference.ResolvedHintPath);
            }

            if (vsProject != null)
            {
                referencedProjects.Add(vsProject);
            }
            else
            {
                // fall back scenario, check assembly name in current project output path
                string outputDirectory = Path.GetDirectoryName(project.ResolvedOutput) ?? ".";
                string currentFolderAssembly = Path.Combine(outputDirectory, reference.ResolvedInclude) + ".dll";
                vsProject = projectLoader.GetProjectByOutput(currentFolderAssembly);

                if (vsProject== null)
                {
                    currentFolderAssembly = Path.Combine(outputDirectory, reference.ResolvedInclude) + ".exe";
                    vsProject = projectLoader.GetProjectByOutput(currentFolderAssembly);
                }

                if (vsProject == null)
                {
                    if (projectSetup.WhenReferenceNotResolved == ProjectSetupBehavior.Fail)
                    {
                        throw new SolutionGeneratorException(
                            "Reference {0} was not resolved. {3}Project {1}. {3}Expected location = {2}{3}",
                            reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, Environment.NewLine);
                    }
                    if (projectSetup.WhenReferenceNotResolved == ProjectSetupBehavior.Warn)
                    {
                        Logger.Warn(
                            "Reference {0} was not resolved. {3}Project {1}. {3}Expected location = {2}{3}",
                            reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, Environment.NewLine);
                    }
                }
                else
                {
                    if (projectSetup.WhenReferenceResolvedInDifferentLocation == ProjectSetupBehavior.Fail)
                    {
                        throw new SolutionGeneratorException(
                            "Reference {0} was not resolved. {4}Project {1}. {4}Expected location = {2}{4}However it was found in project output folder {3}.{4}",
                            reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, outputDirectory, Environment.NewLine);
                    }
                    if (projectSetup.WhenReferenceResolvedInDifferentLocation == ProjectSetupBehavior.Warn)
                    {
                        Logger.Warn(
                            "Reference {0} was not resolved. {4}Project {1}. {4}Expected location = {2}{4}However it was found in project output folder {3}.{4}",
                            reference.ResolvedInclude, project.ProjectFileLocation, reference.ResolvedHintPath, outputDirectory, Environment.NewLine);
                    }
                }
            }
        }
        public List<Guid> GetProjectDependencies(ProjectSetup projectSetup, ProjectLoader projectLoader, VSProject project, string[] thirdPartyFolders, HashSet<string> usedThirdParties)
        {
            HashSet<string> thirdPartyFileMap;
            if (thirdPartyFolders != null && thirdPartyFolders.Length > 0)
            {
                string key = string.Join(":", thirdPartyFolders);

                if (!ThirdPartyFileCache.TryGetValue(key, out thirdPartyFileMap))
                {
                    thirdPartyFileMap = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);

                    List<string> thirdPartyFiles = FileSearcher.Scan("*.dll", thirdPartyFolders);
                    thirdPartyFileMap.UnionWith(thirdPartyFiles);
                    ThirdPartyFileCache.Add(key, thirdPartyFileMap);
                }
            }
            else
            {
                thirdPartyFileMap = new HashSet<string>();
            }

            List<Guid> checkedProjects = new List<Guid>();

            var completeReferences = GetCurrentProjectReferences(projectSetup, projectLoader, project, thirdPartyFileMap, usedThirdParties, checkedProjects);
            return completeReferences;
        }