/// <summary>
        /// Given an MSBuild Target node and associated XmlNamespaceManager, returns a list of VS project parser
        /// objects, one for each VS project specified in the Target. (There is unlikely to be more than one in any instance.)
        /// </summary>
        /// <param name="targetNode">MSBuild Target node</param>
        /// <param name="xmlnsManager">XML Namespace Manager needed to parse targetNode</param>
        /// <param name="projRootPath">Path to root FW folder</param>
        /// <param name="report">Enables error reports to be logged</param>
        /// <returns>List of VS project parsers if any specified in the target, or else null</returns>
        public static List <IBuildSystemParser> GetProjectParsers(XmlElement targetNode, XmlNamespaceManager xmlnsManager, string projRootPath, ReportSystem report)
        {
            var parsers = new List <IBuildSystemParser>();

            var msBuildNodes = targetNode.SelectNodes("msbuild:MSBuild", xmlnsManager);

            if (msBuildNodes == null)
            {
                return(parsers);
            }

            foreach (XmlElement msBuildNode in msBuildNodes)
            {
                var projectPath = msBuildNode.GetAttribute("Projects").Replace("$(fwrt)", projRootPath);
                // Was crashing with C:\fwrepo\fw\Lib\src\icu\source\allinone\allinone.sln
                if (projectPath.EndsWith(".sln"))
                {
                    continue;
                }
                try
                {
                    parsers.Add(GetProjectParser(projectPath));
                }
                catch (MissingAssemblyInfoException ex)
                {
                    report.AddSeriousIssue("Error: " + ex.Message);
                }
            }

            return(parsers);
        }
Пример #2
0
        /// <summary>
        /// Tests whether the given file's size, date/time, version and MD5 hash are
        /// consistent with details in the library, so that a patch will succeed.
        /// For example, if the file's date/time is more recent than that stored in
        /// the Library, yet the file version has not changed, that is not allowed.
        /// </summary>
        /// <param name="file">Element from FileLibrary.xml</param>
        private void TestLibraryFileDetails(XmlElement file)
        {
            var filePath     = file.GetAttribute("Path");
            var fullFilePath = Path.Combine(_projRootPath, filePath.Replace("\\${config}\\", "\\" + _buildType + "\\"));

            if (!File.Exists(fullFilePath))
            {
                return;                 // This should have been dealt with in Patchcorrections.wxs by now.
            }
            var libDate    = file.GetAttribute("Date");
            var libVersion = file.GetAttribute("Version");
            //var libSize = file.GetAttribute("Size");
            var libMd5 = file.GetAttribute("MD5");

            var fileVersionInfo = FileVersionInfo.GetVersionInfo(fullFilePath);
            var fileVersion     = "";

            if (fileVersionInfo.FileVersion != null)
            {
                fileVersion = fileVersionInfo.FileMajorPart + "." + fileVersionInfo.FileMinorPart + "." +
                              fileVersionInfo.FileBuildPart + "." + fileVersionInfo.FilePrivatePart;
            }
            var fi = new FileInfo(fullFilePath);

            //var realSize = fi.Length;
            var realDateTime = fi.LastWriteTime.ToString(CultureInfo.InvariantCulture);
            var realVersion  = fileVersion;
            var realMd5      = CalcFileMd5(fullFilePath);

            // If the files are not identical, the versions must also be different (if present):
            if (realMd5 != libMd5 && libVersion != "" && realVersion != "")
            {
                if (realVersion == libVersion)
                {
                    _report.AddSeriousIssue("ERROR #1: File " + filePath + " has been modified since the last release, but its version remains at " + realVersion + ". Patching will fail.");
                }
                else
                {
                    // Although the version may have changed, the installer ignores the last segment (private part)
                    // so we need to warn the user if that is the only part that changed:
                    var realVersionTrunc = fileVersionInfo.FileMajorPart + "." + fileVersionInfo.FileMinorPart + "." +
                                           fileVersionInfo.FileBuildPart;
                    var libVersionTrunc = "";
                    var libVsplit       = libVersion.Split('.');
                    for (int i = 0; i < Math.Min(3, libVsplit.Length); i++)
                    {
                        if (i > 0)
                        {
                            libVersionTrunc += ".";
                        }
                        libVersionTrunc += libVsplit[i];
                    }

                    if (realVersionTrunc == libVersionTrunc)
                    {
                        _report.AddSeriousIssue("ERROR #8: File " + filePath + " has a version number (" + realVersion + ") that has only changed in the 4th segment since the last release (" + libVersion + "). The 4th version segment is ignored by the installer. Patching will fail.");
                    }
                }
            }

            // The date of the file must not precede that in the library (we will allow up to 24 hours' precedence):
            var libDateTime         = DateTime.Parse(libDate, CultureInfo.InvariantCulture);
            var fileDateTime        = DateTime.Parse(realDateTime, CultureInfo.InvariantCulture);
            var timeBetweenVersions = fileDateTime.Subtract(libDateTime);

            if (timeBetweenVersions.TotalHours < -24)
            {
                _report.AddSeriousIssue("ERROR #2: File " + filePath + " has a date/time stamp (" + realDateTime + ") that is earlier than a previously released version (" + libDate + "). Patching may fail.");
            }

            if (realVersion == "0.0.0.0" && !_versionZeroFiles.Any(path => fullFilePath.ToLowerInvariant().Contains(path.Replace("\\${config}\\", "\\" + _buildType + "\\").ToLowerInvariant())))
            {
                _report.AddSeriousIssue("WARNING #3: File " + filePath + " has a version number of 0.0.0.0. That is very silly, and I don't like it. You'll only regret it later.");
            }

            // The version number must not be lower in the latest version than it was in the previous one:
            if (libVersion.Length > 0 && realVersion.Length == 0)
            {
                _report.AddSeriousIssue("ERROR #9: File " + filePath + " had a version of " + libVersion +
                                        " in the last release. The version information has since been removed. Patching will fail.");
            }
            else
            {
                try
                {
                    if (ParseVersion(realVersion) < ParseVersion(libVersion))
                    {
                        _report.AddSeriousIssue("ERROR #6: File " + filePath + " had a version of " + libVersion +
                                                " in the last release. The version has since been lowered to " + realVersion + ". Patching will fail.");
                    }
                }
                catch (Exception e)
                {
                    _report.AddSeriousIssue("ERROR #7: File " + filePath + " has invalid version number (possibly in FileLibrary.xml): " + e.Message);
                }
            }
        }
        /// <summary>
        /// Given an MSBuild Target node and associated XmlNamespaceManager, returns a list of VS project parser
        /// objects, one for each VS project specified in the Target. (There is unlikely to be more than one in any instance.)
        /// </summary>
        /// <param name="targetNode">MSBuild Target node</param>
        /// <param name="xmlnsManager">XML Namespace Manager needed to parse targetNode</param>
        /// <param name="projRootPath">Path to root FW folder</param>
        /// <param name="report">Enables error reports to be logged</param>
        /// <returns>List of VS project parsers if any specified in the target, or else null</returns>
        public static List<IBuildSystemParser> GetProjectParsers(XmlElement targetNode, XmlNamespaceManager xmlnsManager, string projRootPath, ReportSystem report)
        {
            var parsers = new List<IBuildSystemParser>();

            var msBuildNodes = targetNode.SelectNodes("msbuild:MSBuild", xmlnsManager);
            if (msBuildNodes == null)
                return parsers;

            foreach (XmlElement msBuildNode in msBuildNodes)
            {
                var projectPath = msBuildNode.GetAttribute("Projects").Replace("$(fwrt)", projRootPath);
                // Was crashing with C:\fwrepo\fw\Lib\src\icu\source\allinone\allinone.sln
                if (projectPath.EndsWith(".sln"))
                    continue;
                try
                {
                    parsers.Add(GetProjectParser(projectPath));
                }
                catch (MissingAssemblyInfoException ex)
                {
                    report.AddSeriousIssue("Error: " + ex.Message);
                }
            }

            return parsers;
        }