/// <summary> /// Returns true if FreeStyleProject instances are equal /// </summary> /// <param name="other">Instance of FreeStyleProject to be compared</param> /// <returns>Boolean</returns> public bool Equals(FreeStyleProject other) { if (other is null) { return(false); } if (ReferenceEquals(this, other)) { return(true); } return (( Class == other.Class || Class != null && Class.Equals(other.Class) ) && ( Name == other.Name || Name != null && Name.Equals(other.Name) ) && ( Url == other.Url || Url != null && Url.Equals(other.Url) ) && ( Color == other.Color || Color != null && Color.Equals(other.Color) ) && ( Actions == other.Actions || Actions != null && Actions.SequenceEqual(other.Actions) ) && ( Description == other.Description || Description != null && Description.Equals(other.Description) ) && ( DisplayName == other.DisplayName || DisplayName != null && DisplayName.Equals(other.DisplayName) ) && ( DisplayNameOrNull == other.DisplayNameOrNull || DisplayNameOrNull != null && DisplayNameOrNull.Equals(other.DisplayNameOrNull) ) && ( FullDisplayName == other.FullDisplayName || FullDisplayName != null && FullDisplayName.Equals(other.FullDisplayName) ) && ( FullName == other.FullName || FullName != null && FullName.Equals(other.FullName) ) && ( Buildable == other.Buildable || Buildable != null && Buildable.Equals(other.Buildable) ) && ( Builds == other.Builds || Builds != null && Builds.SequenceEqual(other.Builds) ) && ( FirstBuild == other.FirstBuild || FirstBuild != null && FirstBuild.Equals(other.FirstBuild) ) && ( HealthReport == other.HealthReport || HealthReport != null && HealthReport.SequenceEqual(other.HealthReport) ) && ( InQueue == other.InQueue || InQueue != null && InQueue.Equals(other.InQueue) ) && ( KeepDependencies == other.KeepDependencies || KeepDependencies != null && KeepDependencies.Equals(other.KeepDependencies) ) && ( LastBuild == other.LastBuild || LastBuild != null && LastBuild.Equals(other.LastBuild) ) && ( LastCompletedBuild == other.LastCompletedBuild || LastCompletedBuild != null && LastCompletedBuild.Equals(other.LastCompletedBuild) ) && ( LastFailedBuild == other.LastFailedBuild || LastFailedBuild != null && LastFailedBuild.Equals(other.LastFailedBuild) ) && ( LastStableBuild == other.LastStableBuild || LastStableBuild != null && LastStableBuild.Equals(other.LastStableBuild) ) && ( LastSuccessfulBuild == other.LastSuccessfulBuild || LastSuccessfulBuild != null && LastSuccessfulBuild.Equals(other.LastSuccessfulBuild) ) && ( LastUnstableBuild == other.LastUnstableBuild || LastUnstableBuild != null && LastUnstableBuild.Equals(other.LastUnstableBuild) ) && ( LastUnsuccessfulBuild == other.LastUnsuccessfulBuild || LastUnsuccessfulBuild != null && LastUnsuccessfulBuild.Equals(other.LastUnsuccessfulBuild) ) && ( NextBuildNumber == other.NextBuildNumber || NextBuildNumber != null && NextBuildNumber.Equals(other.NextBuildNumber) ) && ( QueueItem == other.QueueItem || QueueItem != null && QueueItem.Equals(other.QueueItem) ) && ( ConcurrentBuild == other.ConcurrentBuild || ConcurrentBuild != null && ConcurrentBuild.Equals(other.ConcurrentBuild) ) && ( Scm == other.Scm || Scm != null && Scm.Equals(other.Scm) )); }
/// <summary> /// Gets the hash code /// </summary> /// <returns>Hash code</returns> public override int GetHashCode() { unchecked // Overflow is fine, just wrap { var hashCode = 41; // Suitable nullity checks etc, of course :) if (Class != null) { hashCode = hashCode * 59 + Class.GetHashCode(); } if (Name != null) { hashCode = hashCode * 59 + Name.GetHashCode(); } if (Url != null) { hashCode = hashCode * 59 + Url.GetHashCode(); } if (Color != null) { hashCode = hashCode * 59 + Color.GetHashCode(); } if (Actions != null) { hashCode = hashCode * 59 + Actions.GetHashCode(); } if (Description != null) { hashCode = hashCode * 59 + Description.GetHashCode(); } if (DisplayName != null) { hashCode = hashCode * 59 + DisplayName.GetHashCode(); } if (DisplayNameOrNull != null) { hashCode = hashCode * 59 + DisplayNameOrNull.GetHashCode(); } if (FullDisplayName != null) { hashCode = hashCode * 59 + FullDisplayName.GetHashCode(); } if (FullName != null) { hashCode = hashCode * 59 + FullName.GetHashCode(); } if (Buildable != null) { hashCode = hashCode * 59 + Buildable.GetHashCode(); } if (Builds != null) { hashCode = hashCode * 59 + Builds.GetHashCode(); } if (FirstBuild != null) { hashCode = hashCode * 59 + FirstBuild.GetHashCode(); } if (HealthReport != null) { hashCode = hashCode * 59 + HealthReport.GetHashCode(); } if (InQueue != null) { hashCode = hashCode * 59 + InQueue.GetHashCode(); } if (KeepDependencies != null) { hashCode = hashCode * 59 + KeepDependencies.GetHashCode(); } if (LastBuild != null) { hashCode = hashCode * 59 + LastBuild.GetHashCode(); } if (LastCompletedBuild != null) { hashCode = hashCode * 59 + LastCompletedBuild.GetHashCode(); } if (LastFailedBuild != null) { hashCode = hashCode * 59 + LastFailedBuild.GetHashCode(); } if (LastStableBuild != null) { hashCode = hashCode * 59 + LastStableBuild.GetHashCode(); } if (LastSuccessfulBuild != null) { hashCode = hashCode * 59 + LastSuccessfulBuild.GetHashCode(); } if (LastUnstableBuild != null) { hashCode = hashCode * 59 + LastUnstableBuild.GetHashCode(); } if (LastUnsuccessfulBuild != null) { hashCode = hashCode * 59 + LastUnsuccessfulBuild.GetHashCode(); } if (NextBuildNumber != null) { hashCode = hashCode * 59 + NextBuildNumber.GetHashCode(); } if (QueueItem != null) { hashCode = hashCode * 59 + QueueItem.GetHashCode(); } if (ConcurrentBuild != null) { hashCode = hashCode * 59 + ConcurrentBuild.GetHashCode(); } if (Scm != null) { hashCode = hashCode * 59 + Scm.GetHashCode(); } return(hashCode); } }
private static void AddLogToList(List<ColomaEvent> list, DateTime dt, Dictionary<string, KBRevision> installedUpdates) { // this retrieves the build.revision and branch for the current client WindowsVersion.WindowsVersionInfo wvi = new WindowsVersion.WindowsVersionInfo(); WindowsVersion.GetWindowsBuildandRevision(wvi); FirstBuild firstBuildEvent = new FirstBuild { index = 0, build = wvi.build }; KBRevision currentKb = new KBRevision(); uint currentBuild = wvi.build; Guid servicingProvider = new Guid("BD12F3B8-FC40-4A61-A307-B7A013A069C1"); string structuredQuery = string.Format(System.Globalization.CultureInfo.InvariantCulture, Coloma.structuredQueryTemplate, dt.ToUniversalTime()); EventLogQuery query = new EventLogQuery(null, PathType.LogName, structuredQuery); query.ReverseDirection = false; EventLogReader reader = new EventLogReader(query); // The Event Log can only return a maximum of 2 MB at a time, but it does not actually limit itself to this when collecting <BatchSize> events. // If the number of requested events exceeds 2 MB of event data an exception will be throw (System.Diagnostics.Eventing.Reader.EventLogException: The data area passed to a system call is too small). // Since an event is at most 64 KB, 30 events is a conservative limit to ensure the 2 MB limit is never crossed. // Setting a smaller batch size does have a small performance impact, but not enough to notice in this scenario. reader.BatchSize = 30; EventRecord entry; while ((entry = reader.ReadEvent()) != null) { var entryTimeCreated = entry.TimeCreated ?? DateTime.Now; var entryMachineName = entry.MachineName; var entryLogName = entry.LogName; var entryId = entry.Id; var entryProviderName = entry.ProviderName; string entryLevelDisplayName = ""; try { entryLevelDisplayName = entry.LevelDisplayName; } catch { if (entry.Level != null) entryLevelDisplayName = ((StandardEventLevel) entry.Level).ToString(); } string entryMessage = CleanUpMessage(entry.FormatDescription()); if (entryMessage == null && entry.Properties.Count > 0) { string entryProperties = String.Join(", ", entry.Properties.Select(p => String.Format("'{0}'", p.Value))); entryMessage = String.Format(Coloma.descNotFoundMsgTemplate, entryId, entryProviderName, entryProperties); } if (entryId == 2 && entry.ProviderId.HasValue && entry.ProviderId.Value == servicingProvider) { if (entry.Properties.Count == 5 && entry.Properties[2].Value.ToString() == "Installed") { string kb = entry.Properties[0].Value.ToString(); KBRevision KBRev; if(installedUpdates.TryGetValue(kb, out KBRev)) { // Update InstallDate with a more precise time KBRev.InstallDate = entryTimeCreated; KBRev.FoundInSetupLog = true; currentKb = KBRev; } else { currentKb = new KBRevision { InstallDate = entryTimeCreated, Kb = kb, FoundInSetupLog = true }; installedUpdates.Add(kb, new KBRevision(currentKb)); } } } else if (entryId == 6009 && entry.ProviderName == "EventLog") { if (firstBuildEvent.index == 0 && entry.Properties.Count == 5) { uint.TryParse(entry.Properties[1].Value.ToString(), out currentBuild); // If the boot event indicates an earlier build, remember it so we can set all the prior events to this build number if (firstBuildEvent.build != currentBuild) { firstBuildEvent.index = list.Count + 1; firstBuildEvent.build = currentBuild; } // Else the event indicates no build number change, so don't bother checking later boot events either else { firstBuildEvent.index = -1; } } // This event doesn't go into the log file continue; } list.Add(new ColomaEvent(wvi.branch, currentBuild, currentKb, entryMachineName, DeviceId, Environment.UserName, entryLogName, entryLevelDisplayName, entryId, entryTimeCreated, entryProviderName, entryMessage)); } IEnumerable<KBRevision> orderedUpdates = installedUpdates.Select(kb => kb.Value).OrderBy(kb => kb.InstallDate); IEnumerable<KBRevision> missingUpdates = orderedUpdates.Where(kb => !kb.FoundInSetupLog); IEnumerator<KBRevision> currentMissingEnum = missingUpdates.GetEnumerator(); currentMissingEnum.MoveNext(); IEnumerator<KBRevision> nextInstalled = orderedUpdates.GetEnumerator(); nextInstalled.MoveNext(); DateTime nextInstallTime = DateTime.Now; Action getNextInstallTime = new Action(() => { if (nextInstalled.Current != null && currentMissingEnum != null && currentMissingEnum.Current != null) { do { if (nextInstalled.Current.Kb == currentMissingEnum.Current.Kb) { if (nextInstalled.MoveNext()) { nextInstallTime = nextInstalled.Current.InstallDate; // Install times from WMI only include the date, so skip ahead to the next install that falls on a later date or has a more precise time from a setup event while (!nextInstalled.Current.FoundInSetupLog && nextInstallTime >= currentMissingEnum.Current.InstallDate && nextInstallTime < currentMissingEnum.Current.InstallDate.AddDays(1)) { if (nextInstalled.MoveNext()) { nextInstallTime = nextInstalled.Current.InstallDate; } else { nextInstallTime = DateTime.Now; break; } } } else { nextInstallTime = DateTime.Now; break; } break; } } while (nextInstalled.MoveNext()); } }); getNextInstallTime(); int fixupsRemaining = (firstBuildEvent.index > 0 ? 1 : 0) + (missingUpdates.Any() ? 1 : 0); foreach (var evt in list) { if (fixupsRemaining == 0) { break; } // If there was a EventLog 6009 event with a different build number, go back and set all the events before it to have that build number // This is highly unlikely to ever happen under the current OS-swap upgrade mechanism because the logs get cleared during each upgrade if (firstBuildEvent.index > 0) { firstBuildEvent.index--; if (firstBuildEvent.index <= 0) { fixupsRemaining--; } else { evt.Build = firstBuildEvent.build; } } // If there are installed KBs found via WMI that were not in the Setup log, go back and set all the events between the KB installation time // and the next KB installation time to use this KB number. if (currentMissingEnum != null && currentMissingEnum.Current != null) { if (evt.TimeCreated >= currentMissingEnum.Current.InstallDate && evt.TimeCreated < nextInstallTime) { evt.MostRecentKb = new KBRevision(currentMissingEnum.Current); // Since the installations times from WMI are only accurate to the day, append a * to the KB name for any events that fall on that day, to indicate uncertainty. if (evt.TimeCreated >= evt.MostRecentKb.InstallDate && evt.TimeCreated < evt.MostRecentKb.InstallDate.AddDays(1)) { evt.MostRecentKb.Kb += "*"; } } else if (evt.TimeCreated >= nextInstallTime) { if (currentMissingEnum.MoveNext()) { getNextInstallTime(); } else { currentMissingEnum = null; fixupsRemaining--; } } } } }