public StringsTabViewModel(EtwManifest manifest) { Debug.Assert(manifest != null); _manifest = manifest; Strings = _manifest.StringTable.Select(pair => new Item { Name = pair.Key, Value = pair.Value }).ToArray(); }
public EtwEventViewModel(EtwEvent evt, EtwManifest manifest) { Event = evt; _manifest = 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"); }
public SummaryTabViewModel(EtwManifest manifest) { _manifest = manifest; }
public KeywordsTabViewModel(EtwManifest manifest) { Keywords = manifest.Keywords; }
public EventsTabViewModel(EtwManifest manifest) { _manifest = manifest; Events = _manifest.Events.Select(evt => new EtwEventViewModel(evt, _manifest)).ToArray(); }