From b81783d9f0fc978b2449389e801b5fa129290526 Mon Sep 17 00:00:00 2001 From: Kir-Antipov Date: Sat, 13 Jul 2019 21:11:21 +0300 Subject: [PATCH] VisualDump 2.0 - You no longer need to call `DumpExtensions.EnableDumping()` to activate Dumping! (#4) - Fixed `IOException: The semaphore timeout period has expired` during some calls to DumpExtensions - `Visual Dump` initialization is much faster now! - Fixed Visual Studio 2019 installation exception (#2) --- DumpExtensions/DumpExtensions.cs | 151 ++-- DumpExtensions/DumpExtensions.csproj | 15 +- .../DefaultProviders/ArrayHTMLProvider.cs | 7 +- .../DefaultProviders/AssemblyHTMLProvider.cs | 4 +- .../DefaultProviders/BooleanHTMLProvider.cs | 6 +- .../DefaultProviders/CharHTMLProvider.cs | 3 +- .../CyclicalReferenceHTMLProvider.cs | 3 +- .../DefaultProviders/DataTableHTMLProvider.cs | 7 +- .../DefaultProviders/DateTimeHTMLProvider.cs | 3 +- .../DefaultProviders/EnumHTMLProvider.cs | 3 +- .../IEnumerableHTMLProvider.cs | 6 +- .../DefaultProviders/ImageHTMLProvider.cs | 32 +- .../DefaultProviders/ModuleHTMLProvider.cs | 4 +- .../DefaultProviders/NullHTMLProvider.cs | 6 +- .../DefaultProviders/NumberHTMLProvider.cs | 2 +- .../DefaultProviders/ObjectHTMLProvider.cs | 19 +- .../StringBuilderHTMLProvider.cs | 3 +- .../DefaultProviders/StringHTMLProvider.cs | 3 +- .../DefaultProviders/TypeHTMLProvider.cs | 3 +- DumpExtensions/HTMLProviders/HTMLProvider.cs | 34 +- DumpExtensions/Helpers/StackHelpers.cs | 15 + DumpExtensions/Helpers/WindowsInterop.cs | 71 ++ LICENSE.md | 676 ++++++++++++++++++ .../ToolWindows/VisualDumpContainer.cs | 30 +- VisualDump/Images/VSPackageIcon.ico | Bin 67646 -> 104016 bytes VisualDump/Models/HTMLServer.cs | 8 +- VisualDump/Models/PipeHTMLServer.cs | 24 +- VisualDump/Models/ProjectExplorer.cs | 6 +- VisualDump/Models/Reference.cs | 81 +++ VisualDump/Resources/VisualDumpPackage.ico | Bin 428446 -> 0 bytes .../Basic/VisualDump/DumpIfAny.snippet | 18 - .../Basic/VisualDump/DumpIfDebug.snippet | 4 +- .../Basic/VisualDump/DumpIfRelease.snippet | 4 +- .../CSharp/VisualDump/DumpIfAny.snippet | 18 - .../CSharp/VisualDump/DumpIfDebug.snippet | 4 +- .../CSharp/VisualDump/DumpIfRelease.snippet | 4 +- .../NuGetListener.cs} | 22 +- VisualDump/VSPackage.cs | 4 +- VisualDump/VSPackage.resx | 2 +- VisualDump/VisualDump.csproj | 22 +- VisualDump/source.extension.vsixmanifest | 4 +- logo-64.png | Bin 0 -> 2305 bytes 42 files changed, 1097 insertions(+), 234 deletions(-) create mode 100644 DumpExtensions/Helpers/StackHelpers.cs create mode 100644 DumpExtensions/Helpers/WindowsInterop.cs create mode 100644 LICENSE.md create mode 100644 VisualDump/Models/Reference.cs delete mode 100644 VisualDump/Resources/VisualDumpPackage.ico delete mode 100644 VisualDump/Snippets/Basic/VisualDump/DumpIfAny.snippet delete mode 100644 VisualDump/Snippets/CSharp/VisualDump/DumpIfAny.snippet rename VisualDump/{Models/NuGetWatcher.cs => VSHelpers/NuGetListener.cs} (80%) create mode 100644 logo-64.png diff --git a/DumpExtensions/DumpExtensions.cs b/DumpExtensions/DumpExtensions.cs index dd77f2a..704af9e 100644 --- a/DumpExtensions/DumpExtensions.cs +++ b/DumpExtensions/DumpExtensions.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Web; using System.Data; using System.Linq; @@ -7,25 +8,67 @@ using System.Numerics; using System.Reflection; using System.Collections; +using System.Diagnostics; +using VisualDump.Helpers; using System.ComponentModel; using VisualDump.ExtraTypes; using VisualDump.HTMLClients; using VisualDump.HTMLProviders; using System.Collections.Generic; using System.Collections.Concurrent; +using System.Text.RegularExpressions; +using System.Runtime.CompilerServices; using VisualDump.HTMLProviders.DefaultProviders; public static class DumpExtensions { #region Var - public static bool Enabled { get; private set; } - private static ConcurrentDictionary Providers { get; } + public static bool Enabled + { + get => _enabled; + private set + { + if (_enabled != value) + { + _enabled = value; + CloseClient(); + } + } + } + private static bool _enabled = true; + + private static HTMLClient Client + { + get + { + if (_client is null && Enabled) + { + if (string.IsNullOrEmpty(ServerName)) + ServerName = GetDefaultServerName(); + _client = (HTMLClient)Activator.CreateInstance(HTMLClientType, ServerName); + _client.WaitForConnection(MaxWaitTime); + } + return _client; + } + } + private static HTMLClient _client; + + private static Assembly EntryAssembly + { + get => _entryAssembly; + set => _entryAssembly = _entryAssembly ?? value; + } + private static Assembly _entryAssembly; - private static HTMLClient Client; private static string ServerName { get; set; } private static Type HTMLClientType { get; set; } = typeof(PipeHTMLClient); - + private static readonly Regex ProcessRegex = new Regex(@"(.+) - Microsoft Visual Studio", RegexOptions.IgnoreCase | RegexOptions.Compiled); + private static readonly Regex ProcessInActionRegex = new Regex(@"(.+) \(.+\) - Microsoft Visual Studio", RegexOptions.IgnoreCase | RegexOptions.Compiled); private const int MaxWaitTime = 5000; + + private static readonly object _sync = new object(); + + private static ConcurrentDictionary Providers { get; } #endregion #region Init @@ -63,42 +106,80 @@ static DumpExtensions() #endif [typeof(IEnumerable)] = new IEnumerableHTMLProvider() }; - HashSet defaultAssemblies = new HashSet { "mscorlib", "System", "System.Core", "System.Drawing", "System.Windows.Forms" }; - foreach (Type p in AppDomain.CurrentDomain.GetAssemblies().Where(x => !defaultAssemblies.Contains(x.GetName().Name)).SelectMany(x => x.GetExportedTypes().Where(y => IsHTMLProvider(y) && y.GetConstructors().Where(z => z.GetParameters().Length == 0).Count() == 1))) + foreach (Type p in AppDomain.CurrentDomain.GetAssemblies() + .Where(x => { + string name = x.GetName().Name; + return !name.StartsWith("System") && !name.StartsWith("Microsoft") && name != "mscorlib" && name != "netstandard"; + }) + .SelectMany(x => x.GetExportedTypes() + .Where(y => typeof(HTMLProvider).IsAssignableFrom(y) && y.GetConstructor(Type.EmptyTypes) != null))) Register(p); } #endregion #region Functions + [MethodImpl(MethodImplOptions.NoInlining)] public static void EnableDumping() { + EntryAssembly = Assembly.GetCallingAssembly(); Enabled = true; - SetServerName(string.IsNullOrEmpty(ServerName) ? Assembly.GetCallingAssembly().GetName().Name : ServerName); } - public static void DisableDumping() + public static void DisableDumping() => Enabled = false; + + private static string GetDefaultServerName() + { + string asmName = (EntryAssembly ?? Assembly.GetEntryAssembly()).GetName().Name; + Process activeDevenv = Process.GetProcesses().Where(x => x.ProcessName == "devenv").FirstOrDefault(x => x.EnumerateWindows().Select(WindowsInterop.GetWindowText).Where(title => !string.IsNullOrWhiteSpace(title)).Any(title => { + Match m = ProcessInActionRegex.Match(title); + m = m.Success ? m : ProcessRegex.Match(title); + return m.Success && m.Groups[1].Value == asmName; + })); + if (activeDevenv is null) + return asmName; + string searchPattern = $"VisualDump-{activeDevenv.Id}"; + return Directory.EnumerateFiles(@"\\.\pipe\") + .Select(Path.GetFileNameWithoutExtension) + .Where(x => x.StartsWith(searchPattern)) + .FirstOrDefault() ?? asmName; + } + private static void CloseClient() { - Enabled = false; - Client?.Dispose(); + lock (_sync) + { + if (_client != null) + { + _client.Dispose(); + _client = null; + } + } } - public static T Dump(this T Obj) => Dump(Obj, string.Empty, new object[0]); - public static T Dump(this T Obj, string Header) => Dump(Obj, Header, new object[0]); - public static T Dump(this T Obj, params object[] Args) => Dump(Obj, string.Empty, Args); - public static T Dump(this T Obj, string Header, params object[] Args) + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Dump(this T Obj) => Dump(Obj, string.Empty, new object[0], Assembly.GetCallingAssembly()); + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Dump(this T Obj, string Header) => Dump(Obj, Header, new object[0], Assembly.GetCallingAssembly()); + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Dump(this T Obj, params object[] Args) => Dump(Obj, string.Empty, Args, Assembly.GetCallingAssembly()); + [MethodImpl(MethodImplOptions.NoInlining)] + public static T Dump(this T Obj, string Header, params object[] Args) => Dump(Obj, Header, Args, Assembly.GetCallingAssembly()); + private static T Dump(T Obj, string Header, object[] Args, Assembly EntryAssembly) { if (Enabled) { - string html = GetProvider(Obj?.GetType()).ToHTML(Obj, Args); + string html = GetProvider(Obj?.GetType()).ToHTML(Obj, new Stack(), Args); if (!string.IsNullOrEmpty(Header)) html = WrapWithHeader(html, Header); - SendHTML(WrapWithWrapper(html)); + lock (_sync) + { + DumpExtensions.EntryAssembly = EntryAssembly; + Client?.Send(WrapWithWrapper(html)); + } } return Obj; } - private static void SendHTML(string HTML) => Client?.Send(HTML); - private static string WrapWithHeader(string HTML, string Header) => $"

{HttpUtility.HtmlEncode(Header)}

{HTML}
"; private static string WrapWithWrapper(string HTML) => $"
{HTML}
"; + private static string WrapWithHeader(string HTML, string Header) => $"

{HttpUtility.HtmlEncode(Header)}

{HTML}
"; internal static HTMLProvider GetProvider(Type T) { @@ -143,37 +224,25 @@ internal static bool Register(HTMLProvider Provider, Type T) } return false; } - private static bool IsHTMLProvider(Type T) - { - while (T.BaseType != null) - if (T.BaseType == typeof(HTMLProvider)) - return true; - else - T = T.BaseType; - return false; - } - private static void InitializeClient() + + [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] + public static void SetHTMLClient() where TClient : HTMLClient, new() { - Client?.Dispose(); - Client = (HTMLClient)Activator.CreateInstance(HTMLClientType, ServerName); - Client.WaitForConnection(MaxWaitTime); + HTMLClientType = typeof(TClient); + CloseClient(); } - [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] - public static void SetHTMLClient(Type T) + private static void SetHTMLClient(Type T) { - Type tmp = T.BaseType; - while (!(tmp is null) && tmp != typeof(HTMLClient)) - tmp = tmp.BaseType; - HTMLClientType = tmp is null ? throw new NotSupportedException() : T; - InitializeClient(); + HTMLClientType = typeof(HTMLClient).IsAssignableFrom(T) && T.GetConstructor(Type.EmptyTypes) != null ? T : throw new NotSupportedException(); + CloseClient(); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public static void SetServerName(string ServerName) { - DumpExtensions.ServerName = ServerName; - InitializeClient(); + DumpExtensions.ServerName = string.IsNullOrEmpty(ServerName) ? throw new ArgumentException(nameof(ServerName)) : ServerName; + CloseClient(); } -#endregion + #endregion } diff --git a/DumpExtensions/DumpExtensions.csproj b/DumpExtensions/DumpExtensions.csproj index cd22c11..10c6ed5 100644 --- a/DumpExtensions/DumpExtensions.csproj +++ b/DumpExtensions/DumpExtensions.csproj @@ -5,15 +5,18 @@ VisualDump true Kir_Antipov - This library is paired with the VisualDump extension for VisualStudio. -It allows you to view a visual dump of your objects during the debugging of the program in Visual Studio + This library is paired with the VisualDump 2.0 extension for VisualStudio. +It allows you to view a visual dump of your objects during the debugging of the program in Visual Studio 2017/2019 Kir_Antipov © 2019 - DateTime.Now.Year - Visual Dump VisualDump Dumping - https://raw.githubusercontent.com/Kir-Antipov/VisualDump/master/logo.png + Visual Dump VisualDump Dumping LINQPad + https://raw.githubusercontent.com/Kir-Antipov/VisualDump/master/logo-64.png https://github.com/Kir-Antipov/VisualDump https://github.com/Kir-Antipov/VisualDump - 1.0.1 - 1.0.1.0 + 2.0.0 + 2.0.0 + 7.3 + GPL-3.0-only + 2.0.0 diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/ArrayHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/ArrayHTMLProvider.cs index 47102ad..8109533 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/ArrayHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/ArrayHTMLProvider.cs @@ -1,13 +1,14 @@ using System; using System.Data; using System.Collections; +using System.Collections.Generic; using VisualDump.HTMLProviderArgs; namespace VisualDump.HTMLProviders.DefaultProviders { public class ArrayHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, arr => + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (arr, s) => { Type arrType = Obj.GetType(); Type elType = arr.GetType().GetElementType(); @@ -48,9 +49,9 @@ public override string ToHTML(object Obj, params object[] Args) => ToHTML DataTableDumpStyle.CountFields | DataTableDumpStyle.ShowRowIndices | DataTableDumpStyle.ShowColumnNames; - return GetProvider().ToHTML(table, arrType.Namespace.StartsWith("System") || elType.IsAnonymous() ? new DataTableArgs(style) : new DataTableArgs(style, fullType)); + return GetProvider().ToHTML(table, s, arrType.Namespace.StartsWith("System") || elType.IsAnonymous() ? new DataTableArgs(style) : new DataTableArgs(style, fullType)); } - return GetProvider().ToHTML(arr, Args); + return GetProvider().ToHTML(arr, s, Args); }); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/AssemblyHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/AssemblyHTMLProvider.cs index 38444f6..00c5373 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/AssemblyHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/AssemblyHTMLProvider.cs @@ -1,11 +1,13 @@ using System.Reflection; +using VisualDump.Helpers; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class AssemblyHTMLProvider : HTMLProvider { #region Functions - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, a => GetProvider().ToHTML(a.FullName)); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (a, s) => GetProvider().ToHTML(a.FullName, s.CloneAndPush(a))); #endregion } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/BooleanHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/BooleanHTMLProvider.cs index 63eb540..6ce13e1 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/BooleanHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/BooleanHTMLProvider.cs @@ -1,7 +1,9 @@ -namespace VisualDump.HTMLProviders.DefaultProviders +using System.Collections.Generic; + +namespace VisualDump.HTMLProviders.DefaultProviders { public class BooleanHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
{(x ? "true" : "false")}
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
{(x ? "true" : "false")}
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/CharHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/CharHTMLProvider.cs index c0a7e60..ae58182 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/CharHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/CharHTMLProvider.cs @@ -1,9 +1,10 @@ using System.Web; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class CharHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
'{HttpUtility.HtmlEncode(x)}'
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
'{HttpUtility.HtmlEncode(x)}'
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/CyclicalReferenceHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/CyclicalReferenceHTMLProvider.cs index 39450ca..dbf7084 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/CyclicalReferenceHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/CyclicalReferenceHTMLProvider.cs @@ -1,12 +1,13 @@ using System; using System.Text; using VisualDump.ExtraTypes; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class CyclicalReferenceHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, reference => + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (reference, stack) => { Type t = reference.CyclicalObject.GetType(); return new StringBuilder() diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/DataTableHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/DataTableHTMLProvider.cs index be6709d..7ff1b5a 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/DataTableHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/DataTableHTMLProvider.cs @@ -1,14 +1,17 @@ using System; using System.Data; using System.Text; +using VisualDump.Helpers; +using System.Collections.Generic; using VisualDump.HTMLProviderArgs; namespace VisualDump.HTMLProviders.DefaultProviders { public class DataTableHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, Args, (table, a) => + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, Args, (table, stack, a) => { + Stack newCallStack = stack.CloneAndPush(table); Type t = table.GetType(); bool showRowIndex = a.Style.HasFlag(DataTableDumpStyle.ShowRowIndices); bool showColName = a.Style.HasFlag(DataTableDumpStyle.ShowColumnNames); @@ -51,7 +54,7 @@ public override string ToHTML(object Obj, params object[] Args) => ToHTML").Append(i).Append(""); DataRow row = table.Rows[i]; for (int j = 0; j < table.Columns.Count; ++j) - Append("").Append(GetProvider(row[j]).ToHTML(row[j])).Append(""); + Append("").Append(GetProvider(row[j]).ToHTML(row[j], newCallStack)).Append(""); Append(""); } Append("") diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/DateTimeHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/DateTimeHTMLProvider.cs index 79f7c1a..a5e8d8e 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/DateTimeHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/DateTimeHTMLProvider.cs @@ -1,9 +1,10 @@ using System; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class DateTimeHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
{x}
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
{x}
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/EnumHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/EnumHTMLProvider.cs index 20c815b..8d2516d 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/EnumHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/EnumHTMLProvider.cs @@ -1,11 +1,12 @@ using System; using System.Linq; using System.Reflection; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class EnumHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
{x.GetType().Name}.{x} ({x.GetType().GetMembers().OfType().FirstOrDefault(y => y.Name == "value__")?.GetValue(x) ?? 0})
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
{x.GetType().Name}.{x} ({x.GetType().GetMembers().OfType().FirstOrDefault(y => y.Name == "value__")?.GetValue(x) ?? 0})
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/IEnumerableHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/IEnumerableHTMLProvider.cs index 3be7416..0f3cfe4 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/IEnumerableHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/IEnumerableHTMLProvider.cs @@ -2,14 +2,16 @@ using System.Linq; using System.Text; using System.Collections; +using VisualDump.Helpers; using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class IEnumerableHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, enumerable => + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (enumerable, stack) => { + Stack newCallStack = stack.CloneAndPush(enumerable); Type t = Obj.GetType(); StringBuilder builder = new StringBuilder(); StringBuilder Append(string data) => builder.Append(data); @@ -29,7 +31,7 @@ public override string ToHTML(object Obj, params object[] Args) => ToHTML") .Append("") - .Append(GetProvider(x).ToHTML(x, Args)) + .Append(GetProvider(x).ToHTML(x, newCallStack, Args)) .Append("") .Append(""); diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/ImageHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/ImageHTMLProvider.cs index e3ba5dd..6b279d5 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/ImageHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/ImageHTMLProvider.cs @@ -3,28 +3,32 @@ using System.IO; using System.Drawing; using System.Drawing.Imaging; +using System.Collections.Generic; using VisualDump.HTMLProviderArgs; namespace VisualDump.HTMLProviders.DefaultProviders { public class ImageHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, Args, (img, a) => + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, Args, (img, stack, a) => { - Bitmap[] bitmaps = new Bitmap[2]; - if (a.MaxSize != Size.Empty) + Bitmap[] bitmaps = new Bitmap[2]; + if (a.MaxSize != Size.Empty) + { + if (img.Width > a.MaxSize.Width) + img = bitmaps[0] = new Bitmap(img, new Size(a.MaxSize.Width, (int)Math.Floor(img.Height * (a.MaxSize.Width / (double)img.Width)))); + if (img.Height > a.MaxSize.Height) + img = bitmaps[1] = new Bitmap(img, new Size((int)Math.Floor(img.Width * (a.MaxSize.Height / (double)img.Height)), a.MaxSize.Height)); + } + using (Bitmap bit = new Bitmap(img)) { - if (img.Width > a.MaxSize.Width) - img = bitmaps[0] = new Bitmap(img, new Size(a.MaxSize.Width, (int)Math.Floor(img.Height * (a.MaxSize.Width / (double)img.Width)))); - if (img.Height > a.MaxSize.Height) - img = bitmaps[1] = new Bitmap(img, new Size((int)Math.Floor(img.Width * (a.MaxSize.Height / (double)img.Height)), a.MaxSize.Height)); - } - using (MemoryStream m = new MemoryStream()) - { - img.Save(m, ImageFormat.Png); - foreach (Bitmap x in bitmaps) - x?.Dispose(); - return $""; + using (MemoryStream m = new MemoryStream()) + { + bit.Save(m, ImageFormat.Png); + foreach (Bitmap x in bitmaps) + x?.Dispose(); + return $""; + } } }); } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/ModuleHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/ModuleHTMLProvider.cs index d8eb016..b7b751e 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/ModuleHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/ModuleHTMLProvider.cs @@ -1,11 +1,13 @@ using System.Reflection; +using VisualDump.Helpers; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class ModuleHTMLProvider : HTMLProvider { #region Functions - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => GetProvider().ToHTML(x.FullyQualifiedName)); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => GetProvider().ToHTML(x.FullyQualifiedName, s.CloneAndPush(x))); #endregion } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/NullHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/NullHTMLProvider.cs index 52f77bb..6bc8574 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/NullHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/NullHTMLProvider.cs @@ -1,7 +1,9 @@ -namespace VisualDump.HTMLProviders.DefaultProviders +using System.Collections.Generic; + +namespace VisualDump.HTMLProviders.DefaultProviders { public class NullHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => "
null
"; + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => "
null
"; } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/NumberHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/NumberHTMLProvider.cs index 782557d..ad93d6f 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/NumberHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/NumberHTMLProvider.cs @@ -15,6 +15,6 @@ public class NumberProvider : HTMLProvider typeof(decimal), typeof(BigInteger) }; - public override string ToHTML(object Obj, params object[] Args) => _available.Contains(Obj?.GetType()) ? $"
{Obj}
" : throw new NotSupportedException(); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => _available.Contains(Obj?.GetType()) ? $"
{Obj}
" : throw new NotSupportedException(); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/ObjectHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/ObjectHTMLProvider.cs index e114b3a..0233169 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/ObjectHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/ObjectHTMLProvider.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using System.Reflection; +using VisualDump.Helpers; using VisualDump.ExtraTypes; using System.Collections.Generic; @@ -9,15 +10,13 @@ namespace VisualDump.HTMLProviders.DefaultProviders { public class ObjectHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, new List()); - - private string ToHTML(object Obj, List CallStack) + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) { + Stack newCallStack = CallStack.CloneAndPush(Obj); if (Obj is null) - return GetProvider().ToHTML(Obj); + return GetProvider().ToHTML(Obj, newCallStack); if (CallStack.Any(x => ReferenceEquals(x, Obj))) - return GetProvider().ToHTML(new CyclicalReference(Obj)); - CallStack.Add(Obj); + return GetProvider().ToHTML(new CyclicalReference(Obj), newCallStack); Type t = Obj.GetType(); StringBuilder builder = new StringBuilder(); StringBuilder Append(string data) => builder.Append(data); @@ -53,15 +52,13 @@ string inspectMemberInfo(MemberInfo member) { HTMLProvider provider = GetProvider(getMemberType(member)); object inner = member is FieldInfo field ? field.GetValue(Obj) : ((PropertyInfo)member).GetValue(Obj); - if (provider is ObjectHTMLProvider objProvider) - return objProvider.ToHTML(inner, CallStack); if (CallStack.Any(x => ReferenceEquals(x, inner))) - return GetProvider().ToHTML(new CyclicalReference(inner)); - return provider.ToHTML(inner); + return GetProvider().ToHTML(new CyclicalReference(inner), newCallStack); + return provider.ToHTML(inner, newCallStack); } catch { - return GetProvider().ToHTML(null); + return GetProvider().ToHTML(null, newCallStack); } } Type getMemberType(MemberInfo member) => member is FieldInfo field ? field.FieldType : ((PropertyInfo)member).PropertyType; diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/StringBuilderHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/StringBuilderHTMLProvider.cs index 8e33872..6ab4ef7 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/StringBuilderHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/StringBuilderHTMLProvider.cs @@ -1,10 +1,11 @@ using System.Web; using System.Text; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class StringBuilderHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
\"{HttpUtility.HtmlEncode(x)}\" ({x.Length}/{x.Capacity})
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
\"{HttpUtility.HtmlEncode(x)}\" ({x.Length}/{x.Capacity})
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/StringHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/StringHTMLProvider.cs index 2c3be7b..59f88ba 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/StringHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/StringHTMLProvider.cs @@ -1,9 +1,10 @@ using System.Web; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class StringHTMLProvider : HTMLProvider { - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, x => $"
\"{HttpUtility.HtmlEncode(x)}\"
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (x, s) => $"
\"{HttpUtility.HtmlEncode(x)}\"
"); } } diff --git a/DumpExtensions/HTMLProviders/DefaultProviders/TypeHTMLProvider.cs b/DumpExtensions/HTMLProviders/DefaultProviders/TypeHTMLProvider.cs index 80bdaaf..927731e 100644 --- a/DumpExtensions/HTMLProviders/DefaultProviders/TypeHTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/DefaultProviders/TypeHTMLProvider.cs @@ -1,11 +1,12 @@ using System; +using System.Collections.Generic; namespace VisualDump.HTMLProviders.DefaultProviders { public class TypeHTMLProvider : HTMLProvider { #region Functions - public override string ToHTML(object Obj, params object[] Args) => ToHTML(Obj, t => $"
{t.FullName}
"); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => ToHTML(Obj, CallStack, (t, s) => $"
{t.FullName}
"); #endregion } } diff --git a/DumpExtensions/HTMLProviders/HTMLProvider.cs b/DumpExtensions/HTMLProviders/HTMLProvider.cs index f7e9f39..9e4470f 100644 --- a/DumpExtensions/HTMLProviders/HTMLProvider.cs +++ b/DumpExtensions/HTMLProviders/HTMLProvider.cs @@ -1,5 +1,7 @@ using System; +using VisualDump.Helpers; using VisualDump.ExtraTypes; +using System.Collections.Generic; using VisualDump.HTMLProviderArgs; namespace VisualDump.HTMLProviders @@ -9,44 +11,44 @@ public abstract class HTMLProvider #region Var private class CustomHTMLProvider : HTMLProvider { - private Func HTMLCreator { get; } + private Func, object[], string> HTMLCreator { get; } - public CustomHTMLProvider(Func HTMLCreator, bool NeedToRegister) + public CustomHTMLProvider(Func, string> HTMLCreator, bool NeedToRegister) { if (HTMLCreator is null) throw new ArgumentNullException(); - this.HTMLCreator = (x, o) => HTMLCreator(x); + this.HTMLCreator = (x, s, o) => HTMLCreator(x, s.CloneAndPush(x)); if (NeedToRegister) Register(); } - public CustomHTMLProvider(Func HTMLCreator) : this(HTMLCreator, true) { } - public CustomHTMLProvider(Func HTMLCreator, bool NeedToRegister) + public CustomHTMLProvider(Func, string> HTMLCreator) : this(HTMLCreator, true) { } + public CustomHTMLProvider(Func, object[], string> HTMLCreator, bool NeedToRegister) { this.HTMLCreator = HTMLCreator ?? throw new ArgumentNullException(); if (NeedToRegister) Register(); } - public CustomHTMLProvider(Func HTMLCreator) : this(HTMLCreator, true) { } + public CustomHTMLProvider(Func, object[], string> HTMLCreator) : this(HTMLCreator, true) { } public bool Register() => DumpExtensions.Register(this, typeof(T)); - public override string ToHTML(object Obj, params object[] Args) => Obj is T t ? HTMLCreator(t, Args) : throw new NotSupportedException(); + public override string ToHTML(object Obj, Stack CallStack, params object[] Args) => Obj is T t ? HTMLCreator(t, CallStack, Args) : throw new NotSupportedException(); } #endregion #region Functions - public abstract string ToHTML(object Obj, params object[] Args); - protected string ToHTML(object Obj, Func Creator) => Obj is null ? GetProvider().ToHTML(Obj) : Obj is T t ? Creator(t) : throw new NotSupportedException(); - protected string ToHTML(object Obj, object[] Args, Func Creator) => Obj is null ? GetProvider().ToHTML(Obj, Args) : Obj is T t ? Creator(t, Args) : throw new NotSupportedException(); - protected string ToHTML(object Obj, object[] Args, Func Creator) where U : new() => Obj is null ? GetProvider().ToHTML(Obj, Args) : Obj is T t ? Creator(t, Mapper.Map(Args)) : throw new NotSupportedException(); + public abstract string ToHTML(object Obj, Stack CallStack, params object[] Args); + protected string ToHTML(object Obj, Stack CallStack, Func, string> Creator) => Obj is null ? GetProvider().ToHTML(Obj, CallStack.CloneAndPush(Obj)) : Obj is T t ? Creator(t, CallStack.CloneAndPush(t)) : throw new NotSupportedException(); + protected string ToHTML(object Obj, Stack CallStack, object[] Args, Func, object[], string> Creator) => Obj is null ? GetProvider().ToHTML(Obj, CallStack.CloneAndPush(Obj), Args) : Obj is T t ? Creator(t, CallStack.CloneAndPush(t), Args) : throw new NotSupportedException(); + protected string ToHTML(object Obj, Stack CallStack, object[] Args, Func, U, string> Creator) where U : new() => Obj is null ? GetProvider().ToHTML(Obj, CallStack.CloneAndPush(Obj), Args) : Obj is T t ? Creator(t, CallStack.CloneAndPush(t), Mapper.Map(Args)) : throw new NotSupportedException(); public static HTMLProvider GetProvider() => DumpExtensions.GetProvider(typeof(T)); public static HTMLProvider GetProvider(Type Type) => DumpExtensions.GetProvider(Type); - public static HTMLProvider GetProvider(object Obj) => DumpExtensions.GetProvider(Obj?.GetType() ?? typeof(NullReference)); + public static HTMLProvider GetProvider(object Obj) => DumpExtensions.GetProvider(Obj?.GetType()); - public static HTMLProvider CreateProvider(Func HTMLCreator) => new CustomHTMLProvider(HTMLCreator); - public static HTMLProvider CreateProvider(Func HTMLCreator, bool NeedToRegister) => new CustomHTMLProvider(HTMLCreator, NeedToRegister); - public static HTMLProvider CreateProvider(Func HTMLCreator) => new CustomHTMLProvider(HTMLCreator); - public static HTMLProvider CreateProvider(Func HTMLCreator, bool NeedToRegister) => new CustomHTMLProvider(HTMLCreator, NeedToRegister); + public static HTMLProvider CreateProvider(Func, string> HTMLCreator) => new CustomHTMLProvider(HTMLCreator); + public static HTMLProvider CreateProvider(Func, object[], string> HTMLCreator) => new CustomHTMLProvider(HTMLCreator); + public static HTMLProvider CreateProvider(Func, string> HTMLCreator, bool NeedToRegister) => new CustomHTMLProvider(HTMLCreator, NeedToRegister); + public static HTMLProvider CreateProvider(Func, object[], string> HTMLCreator, bool NeedToRegister) => new CustomHTMLProvider(HTMLCreator, NeedToRegister); #endregion } } diff --git a/DumpExtensions/Helpers/StackHelpers.cs b/DumpExtensions/Helpers/StackHelpers.cs new file mode 100644 index 0000000..01a347e --- /dev/null +++ b/DumpExtensions/Helpers/StackHelpers.cs @@ -0,0 +1,15 @@ +using System.Linq; +using System.Collections.Generic; + +namespace VisualDump.Helpers +{ + internal static class StackHelpers + { + public static Stack CloneAndPush(this Stack Stack, T Value) + { + Stack result = new Stack(Stack.Reverse()); + result.Push(Value); + return result; + } + } +} diff --git a/DumpExtensions/Helpers/WindowsInterop.cs b/DumpExtensions/Helpers/WindowsInterop.cs new file mode 100644 index 0000000..fb12c7b --- /dev/null +++ b/DumpExtensions/Helpers/WindowsInterop.cs @@ -0,0 +1,71 @@ +using System; +using System.Text; +using System.Diagnostics; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace VisualDump.Helpers +{ + internal static class WindowsInterop + { + public static class User32 + { + public delegate bool Win32Callback(IntPtr WindowHandle, IntPtr Param); + + [DllImport("user32.dll")] + public static extern uint GetWindowThreadProcessId(IntPtr WindowHandle, out uint ProcessID); + + [DllImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static extern bool EnumChildWindows(IntPtr ParentHandle, Win32Callback Callback, IntPtr Param); + + [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] + public static extern int GetWindowText(IntPtr WindowHandle, StringBuilder String, int MaxCount); + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + public static extern int GetWindowTextLength(IntPtr WindowHandle); + } + + public static IEnumerable EnumerateWindows(this Process Process) + { + foreach (IntPtr windowHandle in GetChildWindows(IntPtr.Zero)) + { + User32.GetWindowThreadProcessId(windowHandle, out uint processID); + if (processID == Process.Id) + yield return windowHandle; + } + } + + private static List GetChildWindows(IntPtr Parent) + { + List result = new List(); + GCHandle listHandle = GCHandle.Alloc(result); + try + { + User32.EnumChildWindows(Parent, EnumWindow, GCHandle.ToIntPtr(listHandle)); + } + finally + { + if (listHandle.IsAllocated) + listHandle.Free(); + } + return result; + } + + private static bool EnumWindow(IntPtr Handle, IntPtr ListPointer) + { + if (GCHandle.FromIntPtr(ListPointer).Target is List list) + list.Add(Handle); + else + throw new InvalidCastException(); + return true; + } + + public static string GetWindowText(IntPtr WindowHandle) + { + StringBuilder sb = new StringBuilder(User32.GetWindowTextLength(WindowHandle) + 1); + User32.GetWindowText(WindowHandle, sb, sb.Capacity); + return sb.ToString(); + } + } +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..3729ad6 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,676 @@ +``` + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. +``` \ No newline at end of file diff --git a/VisualDump/Controls/ToolWindows/VisualDumpContainer.cs b/VisualDump/Controls/ToolWindows/VisualDumpContainer.cs index 00aa216..97af762 100644 --- a/VisualDump/Controls/ToolWindows/VisualDumpContainer.cs +++ b/VisualDump/Controls/ToolWindows/VisualDumpContainer.cs @@ -1,5 +1,5 @@ using EnvDTE; -using System.Threading; +using System; using VisualDump.Models; using VisualDump.VSHelpers; @@ -10,9 +10,6 @@ public class VisualDumpContainer #region Var public static DumpWindow DumpWindow { get; set; } public static HTMLServer Server { get; private set; } - - private const int MaxConnectionWaitTime = 15000; - private static CancellationTokenSource PreviousConnectionSource { get; set; } #endregion #region Init @@ -20,8 +17,10 @@ public static void Initialize() { ThemeListener.ThemeChanged += ThemeListener_ThemeChanged; DebugListener.OnProjectDebuggingStart += DebugListener_OnProjectDebugging; - DebugListener.OnProjectDebuggingStop += DebugListener_OnProjectDebuggingStop; Clear(); + Server = new PipeHTMLServer($"VisualDump-{System.Diagnostics.Process.GetCurrentProcess().Id}-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}"); + Server.OnDataReceived += Server_HTMLReceived; + Server.BeginRead(); } #endregion @@ -29,27 +28,12 @@ public static void Initialize() private static void Clear() => DumpWindow?.Clear(); private static void Server_HTMLReceived(string HTML) => DumpWindow?.Render(HTML); -#pragma warning disable - private static async void DebugListener_OnProjectDebugging(Project Project) + private static void DebugListener_OnProjectDebugging(Project Project) { - ProjectExplorer explorer = new ProjectExplorer(Project); - if (explorer.Language != Models.Languages.Undefined) - { - if (OptionContainer.AutoClear) - Clear(); - PreviousConnectionSource?.Cancel(); - Server?.Dispose(); - Server = new PipeHTMLServer(explorer.AssemblyName); - Server.OnDataReceived += Server_HTMLReceived; - PreviousConnectionSource = new CancellationTokenSource(MaxConnectionWaitTime); - await Server.WaitForConnectionAsync(PreviousConnectionSource.Token); - Server.BeginRead(); - } + if (OptionContainer.AutoClear) + Clear(); } - private static void DebugListener_OnProjectDebuggingStop(Project Project) => Server?.EndRead(); -#pragma warning restore - private static void ThemeListener_ThemeChanged(Themes Theme) => DumpWindow?.ChangeTheme(Theme == Themes.Dark); #endregion } diff --git a/VisualDump/Images/VSPackageIcon.ico b/VisualDump/Images/VSPackageIcon.ico index add2057b8814678f54d81be8cdad3bb280c17fdd..1f1dc84d65eab7766b5bc107818873605d74ae7c 100644 GIT binary patch literal 104016 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 DA~pp7 literal 67646 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 diff --git a/VisualDump/Models/HTMLServer.cs b/VisualDump/Models/HTMLServer.cs index bdf2e15..ea472c7 100644 --- a/VisualDump/Models/HTMLServer.cs +++ b/VisualDump/Models/HTMLServer.cs @@ -1,6 +1,4 @@ using System; -using System.Threading; -using System.Threading.Tasks; namespace VisualDump.Models { @@ -17,11 +15,7 @@ public abstract class HTMLServer : IDisposable #endregion #region Functions - protected virtual void InvokeDataReceived(string Data) => OnDataReceived?.Invoke(Data); - - public abstract Task WaitForConnectionAsync(CancellationToken Token); - public Task WaitForConnectionAsync() => WaitForConnectionAsync(CancellationToken.None); - public Task WaitForConnectionAsync(int TimeoutMS) => WaitForConnectionAsync(TimeoutMS < 1 ? new CancellationTokenSource().Token : new CancellationTokenSource(TimeoutMS).Token); + protected void InvokeDataReceived(string Data) => OnDataReceived?.Invoke(Data); public abstract void BeginRead(); public abstract void EndRead(); diff --git a/VisualDump/Models/PipeHTMLServer.cs b/VisualDump/Models/PipeHTMLServer.cs index 2d4b090..e776129 100644 --- a/VisualDump/Models/PipeHTMLServer.cs +++ b/VisualDump/Models/PipeHTMLServer.cs @@ -3,7 +3,6 @@ using System.Text; using System.IO.Pipes; using System.Threading; -using System.Threading.Tasks; namespace VisualDump.Models { @@ -24,16 +23,6 @@ public class PipeHTMLServer : HTMLServer #endregion #region Functions - public override async Task WaitForConnectionAsync(CancellationToken Token) - { - try - { - if (!Stream.IsConnected) - await Stream.WaitForConnectionAsync(Token); - } - catch { } - } - public override void BeginRead() { if (!Reading) @@ -51,9 +40,14 @@ private void Listen(CancellationToken Token) { try { + if (!Stream.IsConnected) + Stream.WaitForConnection(); int[] blockSizeData = new[] { Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte(), Stream.ReadByte() }; if (blockSizeData.Any(x => x == -1)) - break; + { + Stream.Disconnect(); + continue; + } int blockSize = BitConverter.ToInt32(blockSizeData.Select(x => (byte)x).ToArray(), 0); if (blockSize > 0) { @@ -61,11 +55,7 @@ private void Listen(CancellationToken Token) Stream.Read(buffer, 0, blockSize); InvokeDataReceived(Encoding.UTF8.GetString(buffer)); } - } - catch - { - break; - } + } catch { } } Reading = false; } diff --git a/VisualDump/Models/ProjectExplorer.cs b/VisualDump/Models/ProjectExplorer.cs index ce0e0b5..52e5278 100644 --- a/VisualDump/Models/ProjectExplorer.cs +++ b/VisualDump/Models/ProjectExplorer.cs @@ -22,8 +22,8 @@ public class ProjectExplorer private readonly Lazy _proj; public XDocument Configuration => _proj.Value; - private readonly Lazy> _ref; - public IEnumerable References => _ref.Value; + private readonly Lazy> _ref; + public IEnumerable References => _ref.Value; #endregion #region Init @@ -44,7 +44,7 @@ public ProjectExplorer(Project Project) Language = Languages.Undefined; _proj = new Lazy(() => new XDocument()); } - _ref = new Lazy>(() => GetNodes(Configuration).Where(x => x.Name.LocalName == "Reference").Select(x => x.Attribute("Include").Value).ToArray()); + _ref = new Lazy>(() => GetNodes(Configuration).Where(x => x.Name.LocalName == "Reference").Select(x => Reference.TryParse(x.Attribute("Include").Value, out Reference reference) ? reference : null).Where(x => x != null).ToArray()); _asm = new Lazy(() => { // Get AssemblyName from proj-file string result = GetNodes(Configuration).FirstOrDefault(x => x.Name.LocalName == "AssemblyName")?.Value; diff --git a/VisualDump/Models/Reference.cs b/VisualDump/Models/Reference.cs new file mode 100644 index 0000000..9a1363d --- /dev/null +++ b/VisualDump/Models/Reference.cs @@ -0,0 +1,81 @@ +using System; +using System.Linq; + +namespace VisualDump.Models +{ + public class Reference + { + #region Var + public string Name { get; } + public Version Version { get; } + public string Culture { get; } + public string PublicKeyToken { get; } + public string ProcessorArchitecture { get; } + #endregion + + #region Init + public Reference(string Name, Version Version, string Culture, string PublicKeyToken, string ProcessorArchitecture) + { + this.Name = Name; + this.Version = Version ?? new Version(0, 0, 0, 0); + this.Culture = Culture; + this.PublicKeyToken = PublicKeyToken; + this.ProcessorArchitecture = ProcessorArchitecture; + } + public Reference(string Name, string Version, string Culture, string PublicKeyToken, string ProcessorArchitecture) : this(Name, System.Version.TryParse(Version, out var version) ? version : null, Culture, PublicKeyToken, ProcessorArchitecture) { } + + public static bool TryParse(string Include, out Reference Reference) + { + string name = null; + string culture = "neutral"; + string version = "0.0.0.0"; + string publicKeyToken = null; + string processorArchitecture = null; + foreach (string part in Include.Split(',').Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => x.Trim())) + { + int equalIndex = part.IndexOf('='); + if (equalIndex == -1) + name = part; + else + { + string propertyName = part.Substring(0, equalIndex).ToLower(); + string propertyValue = part.Substring(equalIndex + 1); + switch (propertyName) + { + case "version": + version = propertyValue; + break; + case "culture": + culture = propertyValue; + break; + case "publickeytoken": + publicKeyToken = propertyValue; + break; + case "processorarchitecture": + processorArchitecture = propertyValue; + break; + default: + break; + } + } + } + if (string.IsNullOrEmpty(name)) + { + Reference = null; + return false; + } + else + { + Reference = new Reference(name, version, culture, publicKeyToken, processorArchitecture); + return true; + } + } + #endregion + + #region Functions + public override string ToString() => Name; + public override int GetHashCode() => Name.GetHashCode(); + public override bool Equals(object obj) => obj is Reference r && r.Name == Name && r.Version == Version && r.Culture == Culture && r.ProcessorArchitecture == ProcessorArchitecture && r.PublicKeyToken == PublicKeyToken; + #endregion + } +} diff --git a/VisualDump/Resources/VisualDumpPackage.ico b/VisualDump/Resources/VisualDumpPackage.ico deleted file mode 100644 index d323b07fb8d8b417bfc12e7c46dea88bee17760c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 428446 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

N3mPu2mM3; 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 - - -

- Dump - DIANY - Inserts code that activates Dumping - Kir_Antipov - - Expansion - SurroundsWith - -
- - - - - \ No newline at end of file diff --git a/VisualDump/Snippets/Basic/VisualDump/DumpIfDebug.snippet b/VisualDump/Snippets/Basic/VisualDump/DumpIfDebug.snippet index 1e2ddfb..b51eeac 100644 --- a/VisualDump/Snippets/Basic/VisualDump/DumpIfDebug.snippet +++ b/VisualDump/Snippets/Basic/VisualDump/DumpIfDebug.snippet @@ -12,8 +12,8 @@ - diff --git a/VisualDump/Snippets/Basic/VisualDump/DumpIfRelease.snippet b/VisualDump/Snippets/Basic/VisualDump/DumpIfRelease.snippet index d90e6bf..edefdcd 100644 --- a/VisualDump/Snippets/Basic/VisualDump/DumpIfRelease.snippet +++ b/VisualDump/Snippets/Basic/VisualDump/DumpIfRelease.snippet @@ -12,8 +12,8 @@ - diff --git a/VisualDump/Snippets/CSharp/VisualDump/DumpIfAny.snippet b/VisualDump/Snippets/CSharp/VisualDump/DumpIfAny.snippet deleted file mode 100644 index 166ea6f..0000000 --- a/VisualDump/Snippets/CSharp/VisualDump/DumpIfAny.snippet +++ /dev/null @@ -1,18 +0,0 @@ - - - -
- Dump - diany - Inserts code that activates Dumping - Kir_Antipov - - Expansion - SurroundsWith - -
- - - -
-
\ No newline at end of file diff --git a/VisualDump/Snippets/CSharp/VisualDump/DumpIfDebug.snippet b/VisualDump/Snippets/CSharp/VisualDump/DumpIfDebug.snippet index 00876e6..ab281aa 100644 --- a/VisualDump/Snippets/CSharp/VisualDump/DumpIfDebug.snippet +++ b/VisualDump/Snippets/CSharp/VisualDump/DumpIfDebug.snippet @@ -11,8 +11,8 @@ SurroundsWith - diff --git a/VisualDump/Snippets/CSharp/VisualDump/DumpIfRelease.snippet b/VisualDump/Snippets/CSharp/VisualDump/DumpIfRelease.snippet index 41638a0..3180547 100644 --- a/VisualDump/Snippets/CSharp/VisualDump/DumpIfRelease.snippet +++ b/VisualDump/Snippets/CSharp/VisualDump/DumpIfRelease.snippet @@ -11,8 +11,8 @@ SurroundsWith - diff --git a/VisualDump/Models/NuGetWatcher.cs b/VisualDump/VSHelpers/NuGetListener.cs similarity index 80% rename from VisualDump/Models/NuGetWatcher.cs rename to VisualDump/VSHelpers/NuGetListener.cs index cdadd50..f06daef 100644 --- a/VisualDump/Models/NuGetWatcher.cs +++ b/VisualDump/VSHelpers/NuGetListener.cs @@ -1,16 +1,17 @@ using EnvDTE; +using System; using System.Linq; -using VisualDump.VSHelpers; +using VisualDump.Models; using Thread = System.Threading.Thread; - -namespace VisualDump.Models +namespace VisualDump.VSHelpers { - public static class NuGetWatcher + public static class NuGetListener { #region Var public const string NuGet = "DumpExtensions"; - public const string NuGetVersion = "1.0.1"; + public const string NuGetVersionString = "2.0.0"; + public static readonly Version NuGetVersion = new Version(NuGetVersionString); public const string NuGetAPI = "https://api.nuget.org/v3/index.json"; #endregion @@ -22,12 +23,9 @@ public static class NuGetWatcher private static void ProjectListener_OnProjectOpened(Project Project) { ProjectExplorer explorer = new ProjectExplorer(Project); - if (explorer.Language != Languages.Undefined) - { - string packageName = NuGet.ToLower(); - if (!explorer.References.Any(x => x.ToLower().Contains(packageName))) + if (explorer.Language != Models.Languages.Undefined) + if (!explorer.References.Any(x => x.Name == NuGet && x.Version >= NuGetVersion)) AddReference(Project); - } } private static void AddReference(Project Project) @@ -69,8 +67,8 @@ private static void AddReference(Project Project, int Wait, int TryIndex) } } - private static void AddOnlineReferece(Project Project) => VSPackage.PackageInstaller.InstallPackage(NuGetAPI, Project, NuGet, NuGetVersion, false); - private static void AddOfflineReferece(Project Project) => VSPackage.PackageInstaller.InstallPackage(VSPackage.AssemblyPath, Project, NuGet, NuGetVersion, false); + private static void AddOnlineReferece(Project Project) => VSPackage.PackageInstaller.InstallPackage(NuGetAPI, Project, NuGet, NuGetVersionString, false); + private static void AddOfflineReferece(Project Project) => VSPackage.PackageInstaller.InstallPackage(VSPackage.AssemblyPath, Project, NuGet, NuGetVersionString, false); #endregion } } diff --git a/VisualDump/VSPackage.cs b/VisualDump/VSPackage.cs index 891134b..61f6aac 100644 --- a/VisualDump/VSPackage.cs +++ b/VisualDump/VSPackage.cs @@ -1,7 +1,6 @@ using EnvDTE; using System; using System.Threading; -using VisualDump.Models; using NuGet.VisualStudio; using VisualDump.Controls; using VisualDump.VSHelpers; @@ -23,7 +22,6 @@ namespace VisualDump [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)] [ProvideAutoLoad(VSConstants.UICONTEXT.CodeWindow_string, PackageAutoLoadFlags.BackgroundLoad)] [ProvideAutoLoad(VSConstants.UICONTEXT.SolutionOpening_string, PackageAutoLoadFlags.BackgroundLoad)] - [ProvideAutoLoad(VSConstants.UICONTEXT.FirstLaunchSetup_string, PackageAutoLoadFlags.BackgroundLoad)] [ProvideAutoLoad(VSConstants.UICONTEXT.ShellInitialized_string, PackageAutoLoadFlags.BackgroundLoad)] [ProvideToolWindow(typeof(Controls.VisualDump), Orientation = ToolWindowOrientation.Right, Window = "{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}", Style = VsDockStyle.Tabbed)] [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] @@ -61,7 +59,7 @@ protected override async Task InitializeAsync(CancellationToken CancellationToke DebugListener.Initialize(); ThemeListener.Initialize(GetService(typeof(SVsShell)) as IVsShell); ProjectListener.Initialize(); - NuGetWatcher.Initialize(); + NuGetListener.Initialize(); PackageInstaller = (GetService(typeof(SComponentModel)) as IComponentModel2)?.GetService(); }); diff --git a/VisualDump/VSPackage.resx b/VisualDump/VSPackage.resx index a4bb006..96db71f 100644 --- a/VisualDump/VSPackage.resx +++ b/VisualDump/VSPackage.resx @@ -125,6 +125,6 @@ - Resources\VisualDumpPackage.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + Images\VSPackageIcon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/VisualDump/VisualDump.csproj b/VisualDump/VisualDump.csproj index 57adb86..46acaa1 100644 --- a/VisualDump/VisualDump.csproj +++ b/VisualDump/VisualDump.csproj @@ -46,7 +46,7 @@ DEBUG;TRACE prompt 4 - 7.1 + 7.3 pdbonly @@ -55,7 +55,7 @@ TRACE prompt 4 - 7.1 + 7.3 @@ -88,9 +88,10 @@ - + + @@ -150,7 +151,10 @@ true - + + true + Always + @@ -268,7 +272,6 @@ - Menus.ctmenu @@ -284,18 +287,10 @@ Always true - - Always - true - Always true - - Always - true - Designer @@ -311,6 +306,7 @@ true VSPackage + Designer diff --git a/VisualDump/source.extension.vsixmanifest b/VisualDump/source.extension.vsixmanifest index f13c3ee..2d4926c 100644 --- a/VisualDump/source.extension.vsixmanifest +++ b/VisualDump/source.extension.vsixmanifest @@ -1,12 +1,12 @@ - + Visual Dump This extension allows you to view a visual dump of your objects during the debugging of the program in Visual Studio Images\VSPackageIcon.ico Images\VSPackageIcon.ico - Visual Dump, VisualDump, Dump, Dumping + Visual Dump, VisualDump, Dump, Dumping, LINQPad diff --git a/logo-64.png b/logo-64.png new file mode 100644 index 0000000000000000000000000000000000000000..a4ab5c699722968b7de711b49076d67d18bf7fb8 GIT binary patch literal 2305 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 literal 0 HcmV?d00001