private static string CalculateRelativePath(ProjectFile projectFile, string fromPath, string toPath)
        {
            var fromNodes = fromPath.ToLowerInvariant().Split("\\".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            var toNodes = toPath.ToLowerInvariant().Split("\\".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            int index = 0;
            var master = string.Empty;
            while (fromNodes[index] == toNodes[index])
            {
                master += fromNodes[index] + "\\";
                ++index;
            }

            var relativePath = projectFile.CalculateRelativePath(master);
            for (int i = index; i < toNodes.Length; ++i)
            {
                relativePath += toNodes[i] + "\\";
            }
            return relativePath;
        }
        private static void ChangeReferences(IEnumerable<FileSystemInfo> projectFiles, string projectRootPath, string binariesPath, string targetFrameworkVersion, ReferenceChangeMode sysRuntimeMode, ReferenceChangeMode specificVersionMode, string[] targetProjects)
        {
            var duplicates = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var singleProject in projectFiles)
            {
                var changed = false;
                var projectFile = new ProjectFile(singleProject.FullName);
                var relativePath = projectFile.CalculateRelativePath(projectRootPath);
                var assemblyName = projectFile.GetAssemblyName();
                var projectGuid = projectFile.GetProjectId();
                var currentDirectory = Path.GetDirectoryName(singleProject.FullName);
                if (currentDirectory == null)
                    throw new Exception("Unable to resolve project directory");

                if (duplicates.ContainsKey(projectGuid))
                {
                    throw new Exception(
                        $"Projects has duplicate ids.\n{duplicates[projectGuid]}\n{singleProject.FullName}");
                }

                duplicates.Add(projectGuid, singleProject.FullName);

                var projectReferences = projectFile.ProjectReferences;

                foreach (var reference in projectReferences)
                {
                    var referedProject = Path.GetFullPath(Path.Combine(currentDirectory, reference.Include));
                    var referedProjectFile = new ProjectFile(referedProject);
                    var referedAssemblyName = referedProjectFile.GetAssemblyName();
                    var referedOutputPath = referedProjectFile.GetOutputPath();

                    var referredDirectoryName = Path.GetDirectoryName(referedProject);
                    if (referredDirectoryName == null)
                        throw new Exception("Unable to resolve reffered directory name.");

                    var toPath = Path.GetFullPath(Path.Combine(referredDirectoryName, referedOutputPath));
                    var outputDir = CalculateRelativePath(projectFile, singleProject.FullName, toPath);

                    var hintPath = $"{outputDir}{referedAssemblyName}.dll";
                    projectFile.AddReference(reference.Name, hintPath);
                }

                var outputPath = relativePath + binariesPath;
                if (!outputPath.EndsWith("\\"))
                {
                    outputPath += "\\";
                }

                var isTargetProject = IsTargetProject(assemblyName, targetProjects, projectFile);

                changed |= projectFile.SetReferencePrivacy(isTargetProject, new[] { "\\packages\\", outputPath });
                changed |= projectFile.SetReferenceSpecificVersion(specificVersionMode);
                changed |= projectFile.RemoveProjectReferences();

                if (sysRuntimeMode == ReferenceChangeMode.Add)
                    changed |= projectFile.AddSystemRuntimeReference();
                else if (sysRuntimeMode == ReferenceChangeMode.Remove)
                    changed |= projectFile.RemoveSystemRuntimeReference();

                if (!string.IsNullOrWhiteSpace(targetFrameworkVersion))
                {
                    changed |= projectFile.SetTargetFrameworkVersion(targetFrameworkVersion);
                }

                changed |= projectFile.RemoveNuget();

                if (changed)
                {
                    ConsoleLogger.Default.Info($"Replacing {singleProject.FullName}");
                    projectFile.Save();
                }
            }
        }
        private static void ChangeOutputPath(IEnumerable<FileSystemInfo> projectFiles, string projectPath, string binariesPath, string[] targetProjects)
        {
            foreach (var singleProject in projectFiles)
            {
                var projectFile = new ProjectFile(singleProject.FullName);
                var relativePath = projectFile.CalculateRelativePath(projectPath);
                var assemblyName = projectFile.GetAssemblyName();

                var outputPath = relativePath + binariesPath;
                if (!outputPath.EndsWith("\\"))
                {
                    outputPath += "\\";
                }

                var isTargetProject = IsTargetProject(assemblyName, targetProjects, projectFile);
                var changed = projectFile.SetOutputPath(!isTargetProject ? outputPath : "bin\\");

                if (changed)
                {
                    projectFile.Save();
                }
            }
        }