Esempio n. 1
0
 public ColomaEvent( string branch,
     uint build,
     KBRevision mostRecentKb,
     string machineName,
     string deviceId,
     string userName,
     string logName,
     string level,
     long id,
     DateTime timeCreated,
     string source,
     string Message)
 {
     this.branch = branch;
     this.Build = build;
     this.MostRecentKb = mostRecentKb;
     this.machineName = machineName;
     this.deviceId = deviceId;
     this.userName = userName;
     this.Logname = logName;
     this.level = level;
     this.TimeCreated = timeCreated;
     this.source = source;
     this.message = Message;
     this.instanceid = id;
 }
Esempio n. 2
0
        private static Dictionary<string, KBRevision> QueryUpdates()
        {
            Dictionary<string, KBRevision> installedUpdates = new Dictionary<string, KBRevision>();

            try
            {
                // TODO: Use a different WMI client that doesn't require WinRM

                CimSession cimSession = CimSession.Create("localhost");
                IEnumerable<CimInstance> enumeratedInstances = cimSession.EnumerateInstances(@"root\cimv2", "Win32_QuickFixEngineering");
                foreach (CimInstance cimInstance in enumeratedInstances)
                {
                    DateTime date;
                    if (!DateTime.TryParse(cimInstance.CimInstanceProperties["InstalledOn"].Value.ToString(), CultureInfo.CurrentCulture.DateTimeFormat, DateTimeStyles.AssumeUniversal, out date))
                    {
                        long time;
                        if (!long.TryParse("0x" + cimInstance.CimInstanceProperties["InstalledOn"].Value.ToString(), out time)) // This may only be needed for Win7...
                        {
                            continue;
                        }

                        date = DateTime.FromFileTimeUtc(time);
                    }

                    KBRevision rev = new KBRevision();
                    rev.Kb = cimInstance.CimInstanceProperties["HotFixID"].Value.ToString();
                    rev.InstallDate = date;

                    installedUpdates[rev.Kb] = rev;
                }
            }
            catch (Exception)
            {
                // This probably means WinRM is not enabled. The MI .Net interface uses WinRM to communicate with WMI
                // The user would need to run "winrm quickconfig" to setup the winrm service and firewall exceptions
            }

            return installedUpdates;
        }
Esempio n. 3
0
        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--;
                        }
                    }
                }
            }
        }
Esempio n. 4
0
 public KBRevision(KBRevision other)
 {
     this.Kb = other.Kb;
     this.InstallDate = other.InstallDate;
     this.FoundInSetupLog = other.FoundInSetupLog;
 }