private static void SortandFix(List <ColomaEvent> eventlist, bool setuplog) { uint r = 11; if (!setuplog) { WindowsVersion.WindowsVersionInfo wvi = new WindowsVersion.WindowsVersionInfo(); WindowsVersion.GetWindowsBuildandRevision(wvi); r = wvi.revision; } // sort the list by date eventlist.Sort(); foreach (ColomaEvent evt in eventlist) { if (evt.Logname == "Setup") { r = evt.Revision; } else { evt.Revision = r; } } }
private static bool AddSetupLogToList(List <KBRevision> kbrlist, List <ColomaEvent> list, DateTime dt) { // this retrieves the build.revision and branch for the current client WindowsVersion.WindowsVersionInfo wvi = new WindowsVersion.WindowsVersionInfo(); WindowsVersion.GetWindowsBuildandRevision(wvi); uint revision = wvi.revision; bool setuplog = false; EventLogQuery query = new EventLogQuery("Setup", PathType.LogName); query.ReverseDirection = false; EventLogReader reader = new EventLogReader(query); EventRecord entry; while ((entry = reader.ReadEvent()) != null) { if ((entry.Level == (byte)StandardEventLevel.Critical) || (entry.Level == (byte)StandardEventLevel.Error) || (entry.Level == (byte)StandardEventLevel.Warning) || (entry.Id == 2)) { string msg = CleanUpMessage(entry.FormatDescription()); if (entry.Id == 2) { // this is a KB installed message, figure out which KB it is and update the revision of that entry string kb = "KB"; int i = msg.IndexOf(kb); setuplog = true; if (-1 != i) { // we found the kb article kb = msg.Substring(i, 9); foreach (KBRevision rev in kbrlist) { if (rev.Kb == kb) { revision = rev.Revision; } } } } list.Add(new ColomaEvent(wvi.branch, wvi.build, revision, entry.MachineName, DeviceId, Environment.UserName, "Setup", entry.LevelDisplayName, entry.Id, entry.TimeCreated.GetValueOrDefault(), entry.ProviderName, msg)); } } return(setuplog); }
static void AddStandardLogToList(EventLog log, List <ColomaEvent> list, DateTime dt) { WindowsVersion.WindowsVersionInfo wvi = new WindowsVersion.WindowsVersionInfo(); WindowsVersion.GetWindowsBuildandRevision(wvi); foreach (EventLogEntry entry in log.Entries) { if (entry.TimeGenerated > dt) { if ((entry.EntryType == EventLogEntryType.Error) || (entry.EntryType == EventLogEntryType.Warning)) { string msg = CleanUpMessage(entry.Message); list.Add(new ColomaEvent(wvi.branch, wvi.build, 0, entry.MachineName, Environment.UserName, log.LogDisplayName, entry.EntryType.ToString(), entry.TimeGenerated, entry.Source, msg)); } } } }
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--; } } } } }