public object GetView(IPackageContent selectedFile, IReadOnlyList <IPackageContent> peerFiles) { var tempFile = Path.GetTempFileName(); try { using (var str = selectedFile.GetStream()) using (var fileStream = File.OpenWrite(tempFile)) { str.CopyTo(fileStream); } var assemblyMetadata = AssemblyMetadataReader.ReadMetaData(tempFile); AssemblyDebugDataViewModel debugDataViewModel = null; if (assemblyMetadata.DebugData != null) { debugDataViewModel = new AssemblyDebugDataViewModel(assemblyMetadata.DebugData); } // No debug data to display if (assemblyMetadata != null && debugDataViewModel == null) { var orderedAssemblyDataEntries = assemblyMetadata.GetMetadataEntriesOrderedByImportance(); var grid = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries); return(new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = grid, }); } else if (assemblyMetadata != null && debugDataViewModel != null) { var orderedAssemblyDataEntries = assemblyMetadata.GetMetadataEntriesOrderedByImportance(); // Tab control with two pages var tc = new TabControl() { Items = { new TabItem { Header = "Assembly Attributes", Content = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries) } }, new TabItem { Header = "Embedded PDB Data", Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = new Controls.PdbFileViewer { DataContext = debugDataViewModel } } } } }; return(tc); } } catch { } finally { if (File.Exists(tempFile)) { try { File.Delete(tempFile); } catch { } } } return(new Grid()); }
public object GetView(IPackageContent selectedFile, IReadOnlyList <IPackageContent> peerFiles) { DiagnosticsClient.TrackEvent("AssemblyFileViewer"); try { using var str = selectedFile.GetStream(); using var tempFile = new TemporaryFile(str); var debugData = (selectedFile as PackageFile)?.DebugData; var assemblyMetadata = AssemblyMetadataReader.ReadMetaData(tempFile.FileName); if (debugData == null) { if (assemblyMetadata?.DebugData.HasDebugInfo == true) { debugData = assemblyMetadata.DebugData; } } AssemblyDebugDataViewModel?debugDataViewModel = null; if (debugData != null) { debugDataViewModel = new AssemblyDebugDataViewModel(Task.FromResult(debugData)); } // No debug data to display if (assemblyMetadata != null && debugDataViewModel == null) { var orderedAssemblyDataEntries = GetMetadataEntriesOrderedByImportance(assemblyMetadata); var grid = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries); return(new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = grid, }); } else if (assemblyMetadata != null && debugDataViewModel != null) { var orderedAssemblyDataEntries = GetMetadataEntriesOrderedByImportance(assemblyMetadata); // Tab control with three pages var tc = new TabControl() { Items = { new TabItem { Header = "Assembly Attributes", Content = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries) } }, new TabItem { Header = "PDB Info", Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = new Controls.PdbInfoViewer { DataContext = debugDataViewModel } } }, new TabItem { Header = "PDB Sources", Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = new Controls.PdbSourcesViewer { DataContext = debugDataViewModel } } } } }; return(tc); } } catch { } return(new Grid()); }
public object GetView(string extension, Stream stream) { var tempFile = Path.GetTempFileName(); var grid = new Grid(); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); try { using (var fileStream = File.OpenWrite(tempFile)) { stream.CopyTo(fileStream); } var assemblyMetadata = AssemblyMetadataReader.ReadMetaData(tempFile); if (assemblyMetadata != null) { var orderedAssemblyDataEntries = assemblyMetadata.GetMetadataEntriesOrderedByImportance(); foreach (var data in orderedAssemblyDataEntries) { var label = new TextBlock { Text = data.Key + ':', FontWeight = FontWeights.SemiBold, Margin = new Thickness(3, 3, 10, 0) }; Grid.SetRow(label, grid.RowDefinitions.Count); Grid.SetColumn(label, 0); var value = new TextBlock { Text = data.Value, Margin = new Thickness(0, 3, 3, 0) }; Grid.SetRow(value, grid.RowDefinitions.Count); Grid.SetColumn(value, 1); grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) }); grid.Children.Add(label); grid.Children.Add(value); } } } catch { } finally { if (File.Exists(tempFile)) { try { File.Delete(tempFile); } catch { } } } return(grid); }
private async Task CalculateValidity(IReadOnlyList <PackageFile> files) { var filesWithPdb = (from pf in files let ext = Path.GetExtension(pf.Path) where ".dll".Equals(ext, StringComparison.OrdinalIgnoreCase) || ".exe".Equals(ext, StringComparison.OrdinalIgnoreCase) || ".winmd".Equals(ext, StringComparison.OrdinalIgnoreCase) select new FileWithPdb { Primary = pf, Pdb = pf.GetAssociatedFiles().FirstOrDefault(af => ".pdb".Equals(Path.GetExtension(af.Path), StringComparison.OrdinalIgnoreCase)) }) .ToList(); var sourceLinkErrors = new List <(PackageFile file, string errors)>(); var noSourceLink = new List <PackageFile>(); var noSymbols = new List <FileWithDebugData>(); var untrackedSources = new List <FileWithDebugData>(); var nonDeterministic = new List <PackageFile>(); var allFilePaths = filesWithPdb.ToDictionary(pf => pf.Primary.Path); var pdbChecksumValid = true; foreach (var file in filesWithPdb.ToArray()) // work on array as we'll remove items that are satellite assemblies as we go { // Skip satellite assemblies if (IsSatelliteAssembly(file.Primary.Path)) { filesWithPdb.Remove(allFilePaths[file.Primary.Path]); continue; } // If we have a PDB, try loading that first. If not, may be embedded. // Local checks first if (file.Pdb != null) { var filePair = new FileWithDebugData(file.Primary, null); if (!ValidatePdb(filePair, file.Pdb.GetStream(), noSourceLink, sourceLinkErrors, untrackedSources, nonDeterministic)) { pdbChecksumValid = false; noSymbols.Add(filePair); } } else // No PDB, see if it's embedded { try { using var str = file.Primary.GetStream(); using var tempFile = new TemporaryFile(str); var assemblyMetadata = AssemblyMetadataReader.ReadMetaData(tempFile.FileName); if (assemblyMetadata?.DebugData.HasDebugInfo == true) { // we have an embedded pdb if (!assemblyMetadata.DebugData.HasSourceLink) { noSourceLink.Add(file.Primary); } if (assemblyMetadata.DebugData.SourceLinkErrors.Count > 0) { // Has source link errors sourceLinkErrors.Add((file.Primary, string.Join("\n", assemblyMetadata.DebugData.SourceLinkErrors))); } // Check for non-embedded sources if (assemblyMetadata.DebugData.UntrackedSources.Count > 0) { var filePair = new FileWithDebugData(file.Primary, assemblyMetadata.DebugData); untrackedSources.Add(filePair); } // Check for deterministic sources if (!assemblyMetadata.DebugData.SourcesAreDeterministic) { nonDeterministic.Add(file.Primary); } } else // no embedded pdb, try to look for it elsewhere { noSymbols.Add(new FileWithDebugData(file.Primary, assemblyMetadata?.DebugData)); } } catch // an error occured, no symbols { noSymbols.Add(new FileWithDebugData(file.Primary, null)); } } } var requireExternal = false; // See if any pdb's are missing and check for a snupkg on NuGet.org. if (noSymbols.Count > 0 && _publishedOnNuGetOrg) { // try to get on NuGet.org // https://www.nuget.org/api/v2/symbolpackage/Newtonsoft.Json/12.0.3 -- Will redirect try { #pragma warning disable CA2234 // Pass system uri objects instead of strings var response = await _httpClient.GetAsync($"https://www.nuget.org/api/v2/symbolpackage/{_package.Id}/{_package.Version.ToNormalizedString()}").ConfigureAwait(false); #pragma warning restore CA2234 // Pass system uri objects instead of strings if (response.IsSuccessStatusCode) // we'll get a 404 if none { requireExternal = true; using var getStream = await response.Content.ReadAsStreamAsync(); using var tempFile = new TemporaryFile(getStream, ".snupkg"); using var package = new ZipPackage(tempFile.FileName); // Look for pdb's for the missing files var dict = package.GetFiles().ToDictionary(k => k.Path); foreach (var file in noSymbols.ToArray()) // from a copy so we can remove as we go { // file to look for var pdbpath = Path.ChangeExtension(file.File.Path, ".pdb"); if (dict.TryGetValue(pdbpath, out var pdbfile)) { // Validate if (ValidatePdb(file, pdbfile.GetStream(), noSourceLink, sourceLinkErrors, untrackedSources, nonDeterministic)) { noSymbols.Remove(file); } else { pdbChecksumValid = false; } } } } } catch // Could not check, leave status as-is { } } // Check for Microsoft assemblies on the Microsoft symbol server if (noSymbols.Count > 0) { var microsoftFiles = noSymbols.Where(f => f.DebugData != null && IsMicrosoftFile(f.File)).ToList(); foreach (var file in microsoftFiles) { var pdbStream = await GetSymbolsAsync(file.DebugData !.SymbolKeys); if (pdbStream != null) { requireExternal = true; // Found a PDB for it if (ValidatePdb(file, pdbStream, noSourceLink, sourceLinkErrors, untrackedSources, nonDeterministic)) { noSymbols.Remove(file); } else { pdbChecksumValid = false; } } } } if (noSymbols.Count == 0 && noSourceLink.Count == 0 && sourceLinkErrors.Count == 0) { if (untrackedSources.Count > 0) { SourceLinkResult = SymbolValidationResult.HasUntrackedSources; var sb = new StringBuilder("Contains untracked sources:\n"); sb.AppendLine("To Fix:"); sb.AppendLine("<EmbedUntrackedSources>true</EmbedUntrackedSources>"); foreach (var untracked in untrackedSources) { sb.AppendLine($"Assembly: {untracked.File.Path}"); foreach (var source in untracked.DebugData !.UntrackedSources) { sb.AppendLine($" {source}"); } sb.AppendLine(); } SourceLinkErrorMessage = sb.ToString(); } else if (filesWithPdb.Count == 0) { SourceLinkResult = SymbolValidationResult.NothingToValidate; SourceLinkErrorMessage = "No files found to validate"; } else if (requireExternal) { SourceLinkResult = SymbolValidationResult.ValidExternal; SourceLinkErrorMessage = null; } else { SourceLinkResult = SymbolValidationResult.Valid; SourceLinkErrorMessage = null; } } else { var found = false; var sb = new StringBuilder(); if (noSourceLink.Count > 0) { SourceLinkResult = SymbolValidationResult.NoSourceLink; sb.AppendLine($"Missing Source Link for:\n{string.Join("\n", noSourceLink.Select(p => p.Path)) }"); found = true; } if (sourceLinkErrors.Count > 0) { SourceLinkResult = SymbolValidationResult.InvalidSourceLink; if (found) { sb.AppendLine(); } foreach (var(file, errors) in sourceLinkErrors) { sb.AppendLine($"Source Link errors for {file.Path}:\n{string.Join("\n", errors) }"); } found = true; } if (noSymbols.Count > 0) // No symbols "wins" as it's more severe { SourceLinkResult = SymbolValidationResult.NoSymbols; if (found) { sb.AppendLine(); } if (!pdbChecksumValid) { sb.AppendLine("Some PDB's checksums do not match their PE files and are shown as missing."); } sb.AppendLine($"Missing Symbols for:\n{string.Join("\n", noSymbols.Select(p => p.File.Path)) }"); } SourceLinkErrorMessage = sb.ToString(); } if (SourceLinkResult == SymbolValidationResult.NothingToValidate) { DeterministicResult = DeterministicResult.NothingToValidate; DeterministicErrorMessage = null; } else if (SourceLinkResult == SymbolValidationResult.NoSymbols) { DeterministicResult = DeterministicResult.NonDeterministic; DeterministicErrorMessage = "Missing Symbols"; } else if (nonDeterministic.Count > 0) { DeterministicResult = DeterministicResult.NonDeterministic; var sb = new StringBuilder(); sb.AppendLine("Ensure that the following properties are enabled for CI builds\nand you're using at least the 2.1.300 SDK:"); sb.AppendLine("<Deterministic>true</Deterministic>"); sb.AppendLine("<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>"); sb.AppendLine(); sb.AppendLine("The following assemblies have not been compiled with deterministic settings:"); foreach (var file in nonDeterministic) { sb.AppendLine(file.Path); } DeterministicErrorMessage = sb.ToString(); } else if (SourceLinkResult == SymbolValidationResult.HasUntrackedSources) { DeterministicResult = DeterministicResult.HasUntrackedSources; DeterministicErrorMessage = null; } else { DeterministicResult = DeterministicResult.Valid; DeterministicErrorMessage = null; } }
public object GetView(IPackageContent selectedFile, IReadOnlyList <IPackageContent> peerFiles) { DiagnosticsClient.TrackEvent("AssemblyFileViewer"); try { using var str = selectedFile.GetStream(); using var tempFile = new TemporaryFile(str); var debugData = (selectedFile as PackageFile)?.DebugData; var assemblyMetadata = AssemblyMetadataReader.ReadMetaData(tempFile.FileName); if (debugData == null) { if (assemblyMetadata?.DebugData.HasDebugInfo == true) { debugData = assemblyMetadata.DebugData; } } AssemblyDebugDataViewModel?debugDataViewModel = null; if (debugData != null) { debugDataViewModel = new AssemblyDebugDataViewModel(Task.FromResult(debugData)); } #if !HAS_UNO // No debug data to display if (assemblyMetadata != null && debugDataViewModel == null) { var orderedAssemblyDataEntries = GetMetadataEntriesOrderedByImportance(assemblyMetadata); var grid = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries); return(new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = grid, }); } else if (assemblyMetadata != null && debugDataViewModel != null) { var orderedAssemblyDataEntries = GetMetadataEntriesOrderedByImportance(assemblyMetadata); // Tab control with three pages var tc = new TabControl() { #if HAS_UNO IsAddTabButtonVisible = false, TabItems = #else Items = #endif { new TabItem { Header = "Assembly Attributes", Content = new ScrollViewer() { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = CreateAssemblyMetadataGrid(orderedAssemblyDataEntries) } }, new TabItem { Header = "PDB Info", Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = new Controls.PdbInfoViewer { DataContext = debugDataViewModel } } }, new TabItem { Header = "PDB Sources", Content = new ScrollViewer { HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, VerticalScrollBarVisibility = ScrollBarVisibility.Auto, Content = new Controls.PdbSourcesViewer { DataContext = debugDataViewModel } } } } }; return(tc); } #else // returning UIElement from here works. // however due to performance issues, we are just // returning the datacontext and letting the xaml to handle the view. // also, the ui layout is vastely different compared to the #if-block above return(new AssemblyFileContent() { Metadata = assemblyMetadata ?.SelectOrDefault(GetMetadataEntriesOrderedByImportance) .ToArray(), DebugData = debugDataViewModel, }); #endif } catch (Exception e) { #if HAS_UNO this.Log().Error("Failed to generate view", e); #endif } #if !HAS_UNO return(new Grid()); #else // the empty object is needed for branching via type-checking return(new AssemblyFileContent()); #endif }