static EtwProviderSelectionViewModel() { _providers = TraceEventProviders.GetPublishedProviders().Select(g => new Provider { Name = TraceEventProviders.GetProviderName(g), Guid = g }).ToArray(); }
//Level 4 is default -- after keywords public ProviderBrowser(Window parent, Action <string, string, string> update) { Owner = parent; m_keyStrings = new List <String>(); m_selectedKeys = new List <string>(); m_keys = new Dictionary <string, ProviderDataItem>(); m_processNames = new List <String>(); m_updateParent = update; m_level = "Verbose"; InitializeComponent(); ProviderNameFilter.Focus(); LevelListBox.Items.Add("Always"); LevelListBox.Items.Add("Critical"); LevelListBox.Items.Add("Error"); LevelListBox.Items.Add("Warning"); LevelListBox.Items.Add("Informational"); LevelListBox.Items.Add("Verbose"); LevelListBox.SelectedItem = "Verbose"; var processInfos = new ProcessInfos(); m_processNames.Add("*"); foreach (var process in processInfos.Processes) { // If the name is null, it is likely a system process, it will not have managed code, so don't bother. if (process.Name == null) { continue; } // if (process.ProcessID == myProcessId) // continue; /*// Only show processes with GC heaps. * if (!allProcs && !m_procsWithHeaps.ContainsKey(process.ProcessID)) * continue;*/ m_processNames.Add(process.ToString()); } ProcessNameListBox.ItemsSource = m_processNames; // Get Provider names m_providerNames = new List <String>(); foreach (Guid guid in TraceEventProviders.GetPublishedProviders()) { m_providerNames.Add(TraceEventProviders.GetProviderName(guid)); //keyStrings.Add(TraceEventProviders.GetProviderKeywords(guid).ToString()); } // setup GUI controls. ProviderNameListBox.ItemsSource = m_providerNames; KeyNameListBox.ItemsSource = m_keyStrings; }
private static void List() { if ((options.List & ListFlags.CLR) != 0) { Console.WriteLine("\nSupported CLR keywords (use with --clr):\n"); foreach (var keyword in Enum.GetNames(typeof(ClrTraceEventParser.Keywords))) { Console.WriteLine($"\t{keyword}"); } } if ((options.List & ListFlags.Kernel) != 0) { Console.WriteLine("\nSupported kernel keywords (use with --kernel):\n"); foreach (var keyword in Enum.GetNames(typeof(KernelTraceEventParser.Keywords))) { Console.WriteLine($"\t{keyword}"); } } if ((options.List & ListFlags.Registered) != 0) { Console.WriteLine("\nRegistered or enabled providers (use with --other):\n"); foreach (var provider in TraceEventProviders.GetRegisteredOrEnabledProviders() .Select(guid => TraceEventProviders.GetProviderName(guid)) .OrderBy(n => n)) { Console.WriteLine($"\t{provider}"); } } if ((options.List & ListFlags.Published) != 0) { Console.WriteLine("\nPublished providers (use with --other):\n"); foreach (var provider in TraceEventProviders.GetPublishedProviders() .Select(guid => TraceEventProviders.GetProviderName(guid)) .OrderBy(n => n)) { Console.WriteLine($"\t{provider}"); } } if ((options.List & ListFlags.Framework) != 0) { Console.WriteLine("\nPublished providers (use with --framework):\n"); foreach (var keyword in Enum.GetNames(typeof(FrameworkEventSourceTraceEventParser.Keywords))) { Console.WriteLine($"\t{keyword}"); } } }
private void DoProcessSelected(object sender, SelectionChangedEventArgs e) { var selectedItem = ProcessNameListBox.SelectedItem; if (selectedItem != null) { m_keyStrings = new List <String>(); m_selectedKeys = new List <string>(); m_providerNames = new List <String>(); m_selectedProvider = null; m_providerNames = new List <String>(); if (selectedItem.ToString() == "*") { foreach (Guid guid in TraceEventProviders.GetPublishedProviders()) { m_providerNames.Add(TraceEventProviders.GetProviderName(guid)); } } else { //if (selectedItem.ToString() == "*") // TemplateProperty; // else m_selectedProcess = selectedItem.ToString(); int begin = m_selectedProcess.IndexOf("|"); int end = m_selectedProcess.IndexOf("| Alive", begin + 1); m_selectedProcess = m_selectedProcess.Substring(begin + 8, end - begin - 8); foreach (var provider in TraceEventProviders.GetRegisteredProvidersInProcess(int.Parse(m_selectedProcess))) { m_providerNames.Add(TraceEventProviders.GetProviderName(provider)); } KeyNameListBox.ItemsSource = m_keyStrings; } ProviderNameListBox.ItemsSource = m_providerNames; updateDisplays(); } }
private static void GetRegisteredProvidersInProcess() { new List <string>(TraceEventProviders.GetRegisteredProvidersInProcess(System.Diagnostics.Process.GetCurrentProcess().Id) .Select(p => TraceEventProviders.GetProviderName(p))).ForEach(name => Debug.WriteLine(name)); }
public static EtwManifest ParseWmiEventTraceClass(Guid provider) { // we make a best effort attempt to fit the metadata of this Legacy (MOF) provider into the instrumentation manifest format // we need to find the EventTrace class where the Guid class qualifier matches our provider Guid // afaik you can't query for qualifiers...just classes and properties. :-/ // so we loop through all of the EventTrace classes and compare var providerSearcher = new ManagementObjectSearcher("root\\WMI", $"SELECT * FROM meta_class WHERE __superclass = 'EventTrace'", null); ManagementClass providerClass = null; foreach (ManagementClass candidateProviderClass in providerSearcher.Get()) { foreach (QualifierData qd in candidateProviderClass.Qualifiers) { if (qd.Name.ToLower() == "guid" && new Guid((string)qd.Value) == provider) { providerClass = candidateProviderClass; break; // found } } if (providerClass != null) { break; // found } } if (providerClass == null) { throw new ApplicationException($"Provider {provider} has no corresponding EventTrace class in WMI Repository"); // not found } var manifest = new EtwManifest(string.Empty) { ProviderGuid = provider, ProviderSymbol = (string)providerClass["__CLASS"] }; var events = new SortedDictionary <string, EtwEvent>(); var templates = new List <EtwTemplate>(); var stringTable = new Dictionary <string, string>(); // the provider name is usually in the Description Qualifier for the EventTrace class (but not always?) // and the keywords are properties for the EventTrace class // but we can already get both of these easily from Microsoft.Diagnostics.Tracing manifest.ProviderName = TraceEventProviders.GetProviderName(provider); manifest.Keywords = TraceEventProviders.GetProviderKeywords(provider).Select(info => new EtwKeyword { Name = info.Name, Mask = info.Value, Message = info.Description }).ToArray(); // event details are in the grandchildren of the top-level (EventTrace) provider class // WMI EventTrace children ~ a versioned category grouping // WMI EventTrace grandchildren ~ instrumentation manifest templates // note - event version can be set on the category and/or the event var templateNames = new SortedSet <string>(); var taskSearcher = new ManagementObjectSearcher("root\\WMI", $"SELECT * FROM meta_class WHERE __superclass = '{providerClass["__CLASS"]}'", null); foreach (ManagementClass categoryVersionClass in taskSearcher.Get()) { var categoryVersion = 0; var category = string.Empty; var categoryDescription = string.Empty; var displayName = string.Empty; foreach (QualifierData qd in categoryVersionClass.Qualifiers) { if (qd.Value.GetType() == typeof(Int32) && qd.Name.ToLower() == "eventversion") { categoryVersion = (Int32)qd.Value; } else if (qd.Value.GetType() == typeof(String) && qd.Name.ToLower() == "guid") { category = (string)qd.Value; } else if (qd.Value.GetType() == typeof(String) && qd.Name.ToLower() == "description") { categoryDescription = (string)qd.Value; } else if (qd.Value.GetType() == typeof(String) && qd.Name.ToLower() == "displayname") { displayName = (string)qd.Value; } } var templateSearcher = new ManagementObjectSearcher("root\\WMI", $"SELECT * FROM meta_class WHERE __superclass = '{categoryVersionClass["__CLASS"]}'", null); foreach (ManagementClass templateClass in templateSearcher.Get()) { // EventTypeName qualifier ~ OpCode var template = (string)templateClass["__CLASS"]; var eventType = string.Empty; var version = categoryVersion; var description = categoryDescription; foreach (QualifierData qd in templateClass.Qualifiers) { if (qd.Value.GetType() == typeof(Int32) && qd.Name.ToLower() == "eventversion") { version = (Int32)qd.Value; // override category version with specific event version } else if (qd.Value.GetType() == typeof(String) && qd.Name.ToLower() == "eventtypename") { eventType = (string)qd.Value; } else if (qd.Value.GetType() == typeof(String) && qd.Name.ToLower() == "description") { description = (string)qd.Value; } } if (!string.IsNullOrEmpty(categoryDescription)) { stringTable.Add(template, categoryDescription); } // EventType -> id(s) var ids = new SortedSet <Int32>(); foreach (QualifierData qd in templateClass.Qualifiers) { if (qd.Name.ToLower() == "eventtype") { if (qd.Value.GetType() == typeof(Int32)) { ids.Add((Int32)qd.Value); } else if (qd.Value.GetType().IsArray) { foreach (var element in (Array)qd.Value) { if (element.GetType() == typeof(Int32)) { ids.Add((Int32)element); } } } break; } } // sort by category, id, version foreach (var id in ids) { events.Add($"{category}{id,6}{version,6}", new EtwEvent { Value = id, Symbol = template, Opcode = eventType, Version = version, Template = template, Keyword = description, Task = category }); } // create a template from the properties var templateData = new SortedDictionary <int, EtwTemplateData>(); foreach (PropertyData pd in templateClass.Properties) { foreach (QualifierData qd in pd.Qualifiers) { if (qd.Value.GetType() == typeof(Int32) && qd.Name.ToLower() == "wmidataid") { var id = (int)qd.Value; templateData[id] = new EtwTemplateData { Name = pd.Name, Type = pd.Type.ToString() }; break; } } } templates.Add(new EtwTemplate(template, templateData.Values.ToArray())); } } manifest.Events = events.Values.ToArray(); manifest.Templates = templates.ToArray(); manifest.StringTable = stringTable; return(manifest); }
static void Main() { /* * output all ETW events in a single line 'grep-able' format per provider * * Microsoft.Diagnostics.Tracing does the heavy lifting and provides us with a (partial) ETW manifest, * but lallousx86's WEPExplorer provides improved metadata for providers that are also * Eventlog Providers (i.e. channel, message template). * Unfortunately it it doesn't output event names, so we need to combine both. * * This ticket would remove the need for the dependency on WEPExplorer - * https://github.com/microsoft/perfview/issues/1067 * * And these two tickets would improve the quality of the generated manifest XML * https://github.com/microsoft/perfview/issues/1068 * https://github.com/microsoft/perfview/issues/1069 * * For convenience, I also use the manifest parsing code from EtwExplorer. * And was about to contribute back my MOF parsing code. */ /* * you need to separately build WEPExplorer and copy cli.exe to your working directory * https://github.com/lallousx86/WinTools/tree/master/WEPExplorer */ var useWEPExplorer = File.Exists(WinTools.Cli.CLI_PATH); if (!useWEPExplorer) { Console.WriteLine($"{Cli.CLI_PATH} from WEPExplorer is missing - Eventlog provider data will be incomplete"); } var outputDir = "output"; var manifestOutputDir = Path.Combine(outputDir, "manifest"); var mofOutputDir = Path.Combine(outputDir, "mof"); var unknownOutputDir = Path.Combine(outputDir, "unknown"); Directory.CreateDirectory(outputDir); Directory.CreateDirectory(manifestOutputDir); Directory.CreateDirectory(mofOutputDir); Directory.CreateDirectory(unknownOutputDir); var product = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ProductName", "").ToString(); var release = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "ReleaseId", "").ToString(); var build = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "BuildLabEx", "").ToString(); using (var windowsVersionFile = new StreamWriter(Path.Combine(outputDir, "version.txt"))) { windowsVersionFile.WriteLine($"{product} {release} ({build})"); } foreach (var provider in TraceEventProviders.GetPublishedProviders()) { var name = TraceEventProviders.GetProviderName(provider); // use the provider name as the output filename, but... // ':' is not a valid filename character - use a dash instead // and I just don't like spaces in filenames - use an underscore instead var tsvFilename = $"{name}.tsv".Replace(' ', '_').Replace(':', '-'); bool foundProviderDetails = false; EtwManifest manifest = null; // is this is manifest-based provider? string manifestXML = string.Empty; try { manifestXML = RegisteredTraceEventParser.GetManifestForRegisteredProvider(provider); using (var tsvFile = new StreamWriter(Path.Combine(manifestOutputDir, tsvFilename))) { // Summary: // Given a provider GUID that has been registered with the operating system, get // a string representing the ETW manifest for that provider. Note that this manifest // is not as rich as the original source manifest because some information is not // actually compiled into the binary manifest that is registered with the OS. // a few hacky escaping fixes so that we can parse the xml... if (name == "Microsoft-Windows-AppXDeployment-Server") { manifestXML = manifestXML.Replace("\"any\"", ""any""); } if (name == "Microsoft-Windows-GroupPolicy") { manifestXML = manifestXML.Replace("\"No loopback mode\"", ""No loopback mode""); manifestXML = manifestXML.Replace("\"Merge\"", ""Merge""); manifestXML = manifestXML.Replace("\"Replace\"", ""Replace""); } if (name == "Microsoft-Windows-NetworkProvider") { manifestXML = manifestXML.Replace("<Property>", "<Property>"); manifestXML = manifestXML.Replace("<Value>", "<Value>"); manifestXML = manifestXML.Replace("<Integer>", "<Integer>"); manifestXML = manifestXML.Replace("<Quoted String>", "<Quoted String>"); } if (name == "Microsoft-Windows-Ntfs") { manifestXML = manifestXML.Replace("\"CHKDSK /SCAN\"", ""CHKDSK /SCAN""); manifestXML = manifestXML.Replace("\"CHKDSK /SPOTFIX\"", ""CHKDSK /SPOTFIX""); manifestXML = manifestXML.Replace("\"CHKDSK /F\"", ""CHKDSK /F""); manifestXML = manifestXML.Replace("\"REPAIR-VOLUME <drive:> -SCAN\"", ""REPAIR-VOLUME <drive:> -SCAN""); manifestXML = manifestXML.Replace("\"REPAIR-VOLUME <drive:>\"", ""REPAIR-VOLUME <drive:>""); manifestXML = manifestXML.Replace("<unknown>", "<unknown>"); } manifest = ManifestParser.Parse(manifestXML); foundProviderDetails = true; tsvFile.WriteLine($"provider\tevent_id\tversion\tevent(fields)\topcode\tkeywords\ttask\tlevel\tevtlog_channel\tevtlog_message"); foreach (var evt in manifest.Events) { var fields = string.Empty; try { foreach (var param in manifest.Templates.First(t => t.Id == evt.Template).Items) { if (fields != string.Empty) { fields += ", "; } fields += $"{param.Type} {param.Name}"; } } catch (InvalidOperationException) { } // no fields var Channel = string.Empty; var Message = string.Empty; if (useWEPExplorer) { // add channel and message from WEPExplorer (if available) var xmlNode = WEPExplorer.GetProviderMetadataXml(name); try { if (xmlNode != null && xmlNode.HasChildNodes) { foreach (XmlNode xnEvent in xmlNode.SelectNodes($"/{WEPExplorer.XML_PROVIDERS}/{WEPExplorer.XML_PROVIDER}/{WEPExplorer.XML_EVENT_METADATA}/{WEPExplorer.XML_EVENT}[{WEPExplorer.XML_ID}={evt.Value}][{WEPExplorer.XML_VERSION}={evt.Version}]")) { Channel = WEPExplorer.xnGetText(xnEvent, WEPExplorer.XML_CHANNEL); Message = WEPExplorer.xnGetText(xnEvent, WEPExplorer.XML_MESSAGE).Replace("\r", @"\r").Replace("\n", @"\n"); } } } catch { var errorFilename = "ERROR_WEPExplorer.xml"; Console.WriteLine($"WEPExplorer XML PARSE FAILURE - name={name} file={errorFilename}"); using (var errorFile = new StreamWriter(Path.Combine(outputDir, errorFilename))) { errorFile.WriteLine(xmlNode.OuterXml); } } } var etwEvent = $"{name}\t{evt.Value}\t{evt.Version}\t{evt.Symbol}({fields})\t{evt.Opcode}\t{evt.Keyword}\t{evt.Task}\t{evt.Level}\t{Channel}\t{Message}"; etwEvent = etwEvent.Replace(""", "\"").Replace("<", "<").Replace(">", ">"); tsvFile.WriteLine(etwEvent); } } } catch (Exception e) { if (manifestXML.Length != 0) { var errorFilename = "ERROR_Manifest.xml"; Console.WriteLine($"MANIFEST PARSE FAILURE - name={name} size={manifestXML.Length} file={errorFilename}"); using (var errorFile = new StreamWriter(Path.Combine(outputDir, errorFilename))) { errorFile.WriteLine(manifestXML); } throw e; } } // is this a legacy (MOF-based) provider manifest = null; try { manifest = ManifestParser.ParseWmiEventTraceClass(provider); } catch (ApplicationException) { } if (manifest != null) { foundProviderDetails = true; using (var tsv_file = new StreamWriter(Path.Combine(mofOutputDir, tsvFilename))) { tsv_file.WriteLine($"provider\tcategory\tevent_id\tversion\tevent(fields)\tevent_type\tdescription"); foreach (var evt in manifest.Events) { var fields = string.Empty; try { foreach (var param in manifest.Templates.First(t => t.Id == evt.Template).Items) { if (!string.IsNullOrEmpty(fields)) { fields += ", "; } fields += $"{param.Type} {param.Name}"; } } catch (InvalidOperationException) { } // no fields var etwEvent = $"{name}\t{evt.Task}\t{evt.Value}\t{evt.Version}\t{evt.Symbol}({fields})\t{evt.Opcode}\t{evt.Keyword}"; etwEvent = etwEvent.Replace(""", "\"").Replace("<", "<").Replace(">", ">"); tsv_file.WriteLine(etwEvent); } } } // no manifest and no MOF... if (!foundProviderDetails) { using (var tsv_file = new StreamWriter(Path.Combine(unknownOutputDir, tsvFilename))) { tsv_file.WriteLine($"provider"); tsv_file.WriteLine(name); } } } Console.WriteLine("All done"); }
/// <summary> /// Main function (entry point) /// </summary> /// <param name="args">Provider Name as first parameter, Output file as second parameter</param> static int Main(string[] args) { if (args.Length == 1) { foreach (var providerName in TraceEventProviders.GetPublishedProviders().Select(x => TraceEventProviders.GetProviderName(x))) { Console.WriteLine("Create dissector for provider " + providerName); if (providerName == "TPM") { continue; } // Ignore this provider during install // because we made it by hand to handle // upper layer if (providerName == "Microsoft-Windows-NDIS-PacketCapture") { continue; } if (System.Environment.OSVersion.Version.Major == 6 && System.Environment.OSVersion.Version.Minor == 1) { if (providerName == "Microsoft-Windows-UIAutomationCore") { Console.WriteLine("Ignore provider " + providerName + " on Windows 7"); continue; } } Directory.CreateDirectory(args[0]); CreateDissectorFromProvider(providerName, Path.Combine(args[0], providerName.Replace("-", "_").Replace(" ", "_") + ".lua")); } } else if (args.Length == 2) { CreateDissectorFromProvider(args[0], args[1]); return(0); } else { PrintUsage(); } return(0); }