From 6584a02309bde359784ef79532f40c99da8f76d2 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sat, 31 Jul 2021 03:30:34 +1000 Subject: [PATCH 01/22] added wpf project create shared project (new project type) and isolate non-ui code to share between WinForm/WPF projects --- Demo.WPF/App.xaml | 9 + Demo.WPF/App.xaml.cs | 17 ++ Demo.WPF/AssemblyInfo.cs | 10 + Demo.WPF/Demo.WPF.csproj | 9 + Demo.WPF/MainWindow.xaml | 12 ++ Demo.WPF/MainWindow.xaml.cs | 28 +++ ExceptionReporter.NET.sln | 21 ++- .../Core/ConfigException.cs | 11 ++ .../Core/ExceptionReporterExtensions.cs | 0 .../Core/FileService.cs | 0 .../Core}/IExceptionReportView.cs | 2 +- .../Core/IScreenshotTaker.cs | 7 + ExceptionReporter.Shared/Core/IViewMaker.cs | 20 ++ .../Core/IZipReportService.cs | 0 .../Core/ZipReportService.cs | 5 +- .../ExceptionReportInfo.cs | 11 +- .../ExceptionReporter.Shared.projitems | 74 ++++++++ .../ExceptionReporter.Shared.shproj | 13 ++ .../ExceptionReporter.cs | 9 +- .../Mail/AttachAdapter.cs | 0 .../Mail/Attacher.cs | 5 +- .../Mail/Zipper.cs | 0 .../Network/Events/ConsoleSendEvent.cs | 0 .../Network/Events/IReportSendEvent.cs | 0 .../Network/Events/SilentSendEvent.cs | 0 .../Network/IReportSender.cs | 0 .../Network/ReportPacket.cs | 0 .../Network/SenderFactory.cs | 0 .../Network/Senders/GhostSender.cs | 0 .../Network/Senders/MailSender.cs | 0 .../Network/Senders/MapiMailSender.cs | 4 +- .../Network/Senders/SmtpMailSender.cs | 0 .../Network/Senders/WebServiceSender.cs | 0 .../Properties/Resources.Designer.cs | 4 +- .../Properties/Resources.en.resx | 171 ++++++++++++++++++ .../Properties/Resources.resx | 0 .../Properties/Resources.ru.resx | 171 ++++++++++++++++++ .../Report/AssemblyDigger.cs | 0 .../Report/ReportBuilder.cs | 0 .../Report/StackTraceMaker.cs | 0 .../ReportGenerator.cs | 20 +- .../SystemInfo/SysInfoQueries.cs | 1 + .../SystemInfo/SysInfoQuery.cs | 0 .../SystemInfo/SysInfoResult.cs | 0 .../SystemInfo/SysInfoResultMapper.cs | 35 +--- .../SystemInfo/SysInfoRetriever.cs | 4 +- .../Templates/EmailIntroModel.cs | 0 .../Templates/EmailIntroTemplate.text | 0 .../Templates/ReportModel.cs | 0 .../Templates/ReportTemplate.html | 0 .../Templates/ReportTemplate.markdown | 0 .../Templates/ReportTemplate.text | 0 .../Templates/TemplateFormat.cs | 0 .../Templates/TemplateRenderer.cs | 0 .../ExceptionReporter.WPF.csproj | 89 +++++++++ ExceptionReporter.WPF/ExceptionReporter.xaml | 12 ++ .../ExceptionReporter.xaml.cs | 28 +++ .../Properties/AssemblyInfo.cs | 55 ++++++ .../Properties/Settings.Designer.cs | 30 +++ .../Properties/Settings.settings | 7 + ExceptionReporter.WPF/packages.config | 6 + src/Demos/WinForms/Demo.WinForms.csproj | 6 +- src/Demos/WinForms/YourCustomReporterView.cs | 2 +- src/Demos/WinForms/YourCustomViewMaker.cs | 2 +- ...proj => ExceptionReporter.WinForms.csproj} | 42 ++--- .../Presenters/ExceptionReportPresenter.cs | 1 + .../MVP/Views/ExceptionDetailControl.cs | 6 +- .../MVP/Views/ExceptionReportView.cs | 9 +- src/ExceptionReporting/MVP/Views/ViewMaker.cs | 21 +-- .../{Core => WinForms}/ScreenshotTaker.cs | 8 +- .../WinForms/SysInfoResultMapperWinForm.cs | 36 ++++ .../{Core => WinForms}/WinformsClipboard.cs | 2 +- src/Tests/ExceptionReporter_Tests.cs | 2 +- src/Tests/ReportBuilder_Tests.cs | 1 + src/Tests/Tests.ExceptionReporter.NET.csproj | 2 +- 75 files changed, 908 insertions(+), 132 deletions(-) create mode 100644 Demo.WPF/App.xaml create mode 100644 Demo.WPF/App.xaml.cs create mode 100644 Demo.WPF/AssemblyInfo.cs create mode 100644 Demo.WPF/Demo.WPF.csproj create mode 100644 Demo.WPF/MainWindow.xaml create mode 100644 Demo.WPF/MainWindow.xaml.cs create mode 100644 ExceptionReporter.Shared/Core/ConfigException.cs rename {src/ExceptionReporting => ExceptionReporter.Shared}/Core/ExceptionReporterExtensions.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Core/FileService.cs (100%) rename {src/ExceptionReporting/MVP/Views => ExceptionReporter.Shared/Core}/IExceptionReportView.cs (95%) create mode 100644 ExceptionReporter.Shared/Core/IScreenshotTaker.cs create mode 100644 ExceptionReporter.Shared/Core/IViewMaker.cs rename {src/ExceptionReporting => ExceptionReporter.Shared}/Core/IZipReportService.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Core/ZipReportService.cs (93%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/ExceptionReportInfo.cs (96%) create mode 100644 ExceptionReporter.Shared/ExceptionReporter.Shared.projitems create mode 100644 ExceptionReporter.Shared/ExceptionReporter.Shared.shproj rename {src/ExceptionReporting => ExceptionReporter.Shared}/ExceptionReporter.cs (96%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Mail/AttachAdapter.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Mail/Attacher.cs (86%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Mail/Zipper.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Events/ConsoleSendEvent.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Events/IReportSendEvent.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Events/SilentSendEvent.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/IReportSender.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/ReportPacket.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/SenderFactory.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Senders/GhostSender.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Senders/MailSender.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Senders/MapiMailSender.cs (93%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Senders/SmtpMailSender.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Network/Senders/WebServiceSender.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Properties/Resources.Designer.cs (98%) create mode 100644 ExceptionReporter.Shared/Properties/Resources.en.resx rename {src/ExceptionReporting => ExceptionReporter.Shared}/Properties/Resources.resx (100%) create mode 100644 ExceptionReporter.Shared/Properties/Resources.ru.resx rename {src/ExceptionReporting => ExceptionReporter.Shared}/Report/AssemblyDigger.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Report/ReportBuilder.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Report/StackTraceMaker.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/ReportGenerator.cs (91%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/SystemInfo/SysInfoQueries.cs (84%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/SystemInfo/SysInfoQuery.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/SystemInfo/SysInfoResult.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/SystemInfo/SysInfoResultMapper.cs (53%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/SystemInfo/SysInfoRetriever.cs (88%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/EmailIntroModel.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/EmailIntroTemplate.text (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/ReportModel.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/ReportTemplate.html (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/ReportTemplate.markdown (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/ReportTemplate.text (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/TemplateFormat.cs (100%) rename {src/ExceptionReporting => ExceptionReporter.Shared}/Templates/TemplateRenderer.cs (100%) create mode 100644 ExceptionReporter.WPF/ExceptionReporter.WPF.csproj create mode 100644 ExceptionReporter.WPF/ExceptionReporter.xaml create mode 100644 ExceptionReporter.WPF/ExceptionReporter.xaml.cs create mode 100644 ExceptionReporter.WPF/Properties/AssemblyInfo.cs create mode 100644 ExceptionReporter.WPF/Properties/Settings.Designer.cs create mode 100644 ExceptionReporter.WPF/Properties/Settings.settings create mode 100644 ExceptionReporter.WPF/packages.config rename src/ExceptionReporting/{ExceptionReporter.NET.csproj => ExceptionReporter.WinForms.csproj} (60%) rename src/ExceptionReporting/{Core => WinForms}/ScreenshotTaker.cs (93%) create mode 100644 src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs rename src/ExceptionReporting/{Core => WinForms}/WinformsClipboard.cs (91%) diff --git a/Demo.WPF/App.xaml b/Demo.WPF/App.xaml new file mode 100644 index 00000000..ebf0b06d --- /dev/null +++ b/Demo.WPF/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/Demo.WPF/App.xaml.cs b/Demo.WPF/App.xaml.cs new file mode 100644 index 00000000..ddb5c864 --- /dev/null +++ b/Demo.WPF/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace Demo.WPF +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Demo.WPF/AssemblyInfo.cs b/Demo.WPF/AssemblyInfo.cs new file mode 100644 index 00000000..0ae68e3e --- /dev/null +++ b/Demo.WPF/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/Demo.WPF/Demo.WPF.csproj b/Demo.WPF/Demo.WPF.csproj new file mode 100644 index 00000000..407932cd --- /dev/null +++ b/Demo.WPF/Demo.WPF.csproj @@ -0,0 +1,9 @@ + + + + WinExe + net5.0-windows + true + + + diff --git a/Demo.WPF/MainWindow.xaml b/Demo.WPF/MainWindow.xaml new file mode 100644 index 00000000..cbcc3fcd --- /dev/null +++ b/Demo.WPF/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/Demo.WPF/MainWindow.xaml.cs b/Demo.WPF/MainWindow.xaml.cs new file mode 100644 index 00000000..b475e4d1 --- /dev/null +++ b/Demo.WPF/MainWindow.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Demo.WPF +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + } +} diff --git a/ExceptionReporter.NET.sln b/ExceptionReporter.NET.sln index 00e21072..359090ae 100644 --- a/ExceptionReporter.NET.sln +++ b/ExceptionReporter.NET.sln @@ -3,13 +3,24 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31402.337 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionReporter.Net", "src\ExceptionReporting\ExceptionReporter.Net.csproj", "{1AEEC57B-FB44-4F88-AD50-A2A3686DBC97}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionReporter.WinForms", "src\ExceptionReporting\ExceptionReporter.WinForms.csproj", "{1AEEC57B-FB44-4F88-AD50-A2A3686DBC97}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.ExceptionReporter.Net", "src\Tests\Tests.ExceptionReporter.Net.csproj", "{565583C0-0162-4973-962B-7C3F6EE1A4B0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.WinForms", "src\Demos\WinForms\Demo.WinForms.csproj", "{2FC9BAC6-3AC4-43C2-A8E2-C9655446531E}" EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ExceptionReporter.Shared", "ExceptionReporter.Shared\ExceptionReporter.Shared.shproj", "{AAEEE6CD-9D37-424E-B62A-E7D28D3391F4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo.WPF", "Demo.WPF\Demo.WPF.csproj", "{37CAA53A-D158-4E3A-B760-16AEE4008154}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExceptionReporter.WPF", "ExceptionReporter.WPF\ExceptionReporter.WPF.csproj", "{EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}" +EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{1aeec57b-fb44-4f88-ad50-a2a3686dbc97}*SharedItemsImports = 5 + ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{aaeee6cd-9d37-424e-b62a-e7d28d3391f4}*SharedItemsImports = 13 + ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{ef418ef6-d1db-4cb0-9e77-afc5d7c64aed}*SharedItemsImports = 4 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -27,6 +38,14 @@ Global {2FC9BAC6-3AC4-43C2-A8E2-C9655446531E}.Debug|Any CPU.Build.0 = Debug|Any CPU {2FC9BAC6-3AC4-43C2-A8E2-C9655446531E}.Release|Any CPU.ActiveCfg = Release|Any CPU {2FC9BAC6-3AC4-43C2-A8E2-C9655446531E}.Release|Any CPU.Build.0 = Release|Any CPU + {37CAA53A-D158-4E3A-B760-16AEE4008154}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37CAA53A-D158-4E3A-B760-16AEE4008154}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37CAA53A-D158-4E3A-B760-16AEE4008154}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37CAA53A-D158-4E3A-B760-16AEE4008154}.Release|Any CPU.Build.0 = Release|Any CPU + {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ExceptionReporter.Shared/Core/ConfigException.cs b/ExceptionReporter.Shared/Core/ConfigException.cs new file mode 100644 index 00000000..f96e1a3e --- /dev/null +++ b/ExceptionReporter.Shared/Core/ConfigException.cs @@ -0,0 +1,11 @@ +using System; + +namespace ExceptionReporting.Core +{ + internal class ConfigException : Exception + { + public ConfigException(string message) : base(message) + { } + } + +} \ No newline at end of file diff --git a/src/ExceptionReporting/Core/ExceptionReporterExtensions.cs b/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs similarity index 100% rename from src/ExceptionReporting/Core/ExceptionReporterExtensions.cs rename to ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs diff --git a/src/ExceptionReporting/Core/FileService.cs b/ExceptionReporter.Shared/Core/FileService.cs similarity index 100% rename from src/ExceptionReporting/Core/FileService.cs rename to ExceptionReporter.Shared/Core/FileService.cs diff --git a/src/ExceptionReporting/MVP/Views/IExceptionReportView.cs b/ExceptionReporter.Shared/Core/IExceptionReportView.cs similarity index 95% rename from src/ExceptionReporting/MVP/Views/IExceptionReportView.cs rename to ExceptionReporter.Shared/Core/IExceptionReportView.cs index 2ec38209..ed127361 100644 --- a/src/ExceptionReporting/MVP/Views/IExceptionReportView.cs +++ b/ExceptionReporter.Shared/Core/IExceptionReportView.cs @@ -4,7 +4,7 @@ #pragma warning disable 1591 -namespace ExceptionReporting.MVP.Views +namespace ExceptionReporting.Core { /// /// The interface (contract) for an ExceptionReport dialog/View diff --git a/ExceptionReporter.Shared/Core/IScreenshotTaker.cs b/ExceptionReporter.Shared/Core/IScreenshotTaker.cs new file mode 100644 index 00000000..c1d1514a --- /dev/null +++ b/ExceptionReporter.Shared/Core/IScreenshotTaker.cs @@ -0,0 +1,7 @@ +namespace ExceptionReporting.Core +{ + internal interface IScreenshotTaker + { + string TakeScreenShot(); + } +} \ No newline at end of file diff --git a/ExceptionReporter.Shared/Core/IViewMaker.cs b/ExceptionReporter.Shared/Core/IViewMaker.cs new file mode 100644 index 00000000..4a1b2bb6 --- /dev/null +++ b/ExceptionReporter.Shared/Core/IViewMaker.cs @@ -0,0 +1,20 @@ +using ExceptionReporting.Core; + +/// +/// contract to show view-related things +/// +public interface IViewMaker +{ + /// + /// create the main view/dialog + /// + /// + IExceptionReportView Create(); + + /// + /// show error + /// + /// + /// + void ShowError(string message, string description); +} \ No newline at end of file diff --git a/src/ExceptionReporting/Core/IZipReportService.cs b/ExceptionReporter.Shared/Core/IZipReportService.cs similarity index 100% rename from src/ExceptionReporting/Core/IZipReportService.cs rename to ExceptionReporter.Shared/Core/IZipReportService.cs diff --git a/src/ExceptionReporting/Core/ZipReportService.cs b/ExceptionReporter.Shared/Core/ZipReportService.cs similarity index 93% rename from src/ExceptionReporting/Core/ZipReportService.cs rename to ExceptionReporter.Shared/Core/ZipReportService.cs index 216bcb9c..c687241f 100644 --- a/src/ExceptionReporting/Core/ZipReportService.cs +++ b/ExceptionReporter.Shared/Core/ZipReportService.cs @@ -40,10 +40,9 @@ public string CreateZipReport(ExceptionReportInfo reportInfo, string zipFilePath } var filesThatExist = files.Where(f => FileService.Exists(f)).ToList(); - var filesToZip = filesThatExist; - if (filesToZip.Any()) - Zipper.Zip(zipFilePath, filesToZip); + if (filesThatExist.Any()) + Zipper.Zip(zipFilePath, filesThatExist); else return string.Empty; diff --git a/src/ExceptionReporting/ExceptionReportInfo.cs b/ExceptionReporter.Shared/ExceptionReportInfo.cs similarity index 96% rename from src/ExceptionReporting/ExceptionReportInfo.cs rename to ExceptionReporter.Shared/ExceptionReportInfo.cs index ab9dc3e8..bc08e4f3 100644 --- a/src/ExceptionReporting/ExceptionReportInfo.cs +++ b/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -219,8 +219,8 @@ public bool ShowAssembliesTab /// public bool ShowEmailButton { - get { return SendMethod != ReportSendMethod.None && _showEmailButton; } - set { _showEmailButton = value; } + get => SendMethod != ReportSendMethod.None && _showEmailButton; + set => _showEmailButton = value; } /// @@ -231,7 +231,8 @@ public bool ShowEmailButton /// /// Background color of the dialog /// - public Color BackgroundColor { get; set; } = Color.WhiteSmoke; + // public Color BackgroundColor { get; set; } = Color.WhiteSmoke; + public string BackgroundColor { get; set; } = "#f5f5f5"; /// /// The font size of the user input text box @@ -268,8 +269,8 @@ public bool ShowEmailButton /// The attachment filename, extension .zip applied automatically if not provided public string AttachmentFilename { - get { return _attachmentFilename.ToLower().EndsWith(".zip") ? _attachmentFilename : _attachmentFilename + ".zip"; } - set { _attachmentFilename = value; } + get => _attachmentFilename.ToLower().EndsWith(".zip") ? _attachmentFilename : _attachmentFilename + ".zip"; + set => _attachmentFilename = value; } /// diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems new file mode 100644 index 00000000..7c161bf4 --- /dev/null +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -0,0 +1,74 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + aaeee6cd-9d37-424e-b62a-e7d28d3391f4 + + + ExceptionReporting + + + + + + + + + + + + + + + + + + + + + + + + + + + + Resources.resx + True + True + + + + + + + + + + + + + + + + + + Designer + ResXFileCodeGenerator + + + Designer + Resources.Designer.cs + ResXFileCodeGenerator + + + Designer + ResXFileCodeGenerator + + + + + + + \ No newline at end of file diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj b/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj new file mode 100644 index 00000000..dba5a9c8 --- /dev/null +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj @@ -0,0 +1,13 @@ + + + + aaeee6cd-9d37-424e-b62a-e7d28d3391f4 + 14.0 + + + + + + + + diff --git a/src/ExceptionReporting/ExceptionReporter.cs b/ExceptionReporter.Shared/ExceptionReporter.cs similarity index 96% rename from src/ExceptionReporting/ExceptionReporter.cs rename to ExceptionReporter.Shared/ExceptionReporter.cs index 1c51bc90..71cc1334 100644 --- a/src/ExceptionReporting/ExceptionReporter.cs +++ b/ExceptionReporter.Shared/ExceptionReporter.cs @@ -4,7 +4,6 @@ using System; using System.Runtime.CompilerServices; -using ExceptionReporting.MVP.Views; using ExceptionReporting.Network; using ExceptionReporting.Network.Events; using ExceptionReporting.Properties; @@ -36,16 +35,14 @@ public class ExceptionReporter public ExceptionReporter() { _info = new ExceptionReportInfo(); - ViewMaker = new ViewMaker(_info); + //TODO make make ViewMaker for wpf/winforms separately + // ViewMaker = new ViewMaker(_info); } /// /// Public access to configuration/settings /// - public ExceptionReportInfo Config - { - get { return _info; } - } + public ExceptionReportInfo Config => _info; /// /// Show the ExceptionReport dialog diff --git a/src/ExceptionReporting/Mail/AttachAdapter.cs b/ExceptionReporter.Shared/Mail/AttachAdapter.cs similarity index 100% rename from src/ExceptionReporting/Mail/AttachAdapter.cs rename to ExceptionReporter.Shared/Mail/AttachAdapter.cs diff --git a/src/ExceptionReporting/Mail/Attacher.cs b/ExceptionReporter.Shared/Mail/Attacher.cs similarity index 86% rename from src/ExceptionReporting/Mail/Attacher.cs rename to ExceptionReporter.Shared/Mail/Attacher.cs index 6c7ed543..0f8aa9d7 100644 --- a/src/ExceptionReporting/Mail/Attacher.cs +++ b/ExceptionReporter.Shared/Mail/Attacher.cs @@ -12,7 +12,10 @@ internal class Attacher public IFileService FileService { private get; set; } = new FileService(); public IZipper Zipper { private get; set; } = new Zipper(); - public IScreenshotTaker ScreenshotTaker { private get; set; } = new ScreenshotTaker(); + + //TODO move this back into winforms version + // public IScreenshotTaker ScreenshotTaker { private get; set; } = new ScreenshotTaker(); + public IScreenshotTaker ScreenshotTaker { private get; set; } public Attacher(ExceptionReportInfo config) { diff --git a/src/ExceptionReporting/Mail/Zipper.cs b/ExceptionReporter.Shared/Mail/Zipper.cs similarity index 100% rename from src/ExceptionReporting/Mail/Zipper.cs rename to ExceptionReporter.Shared/Mail/Zipper.cs diff --git a/src/ExceptionReporting/Network/Events/ConsoleSendEvent.cs b/ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs similarity index 100% rename from src/ExceptionReporting/Network/Events/ConsoleSendEvent.cs rename to ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs diff --git a/src/ExceptionReporting/Network/Events/IReportSendEvent.cs b/ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs similarity index 100% rename from src/ExceptionReporting/Network/Events/IReportSendEvent.cs rename to ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs diff --git a/src/ExceptionReporting/Network/Events/SilentSendEvent.cs b/ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs similarity index 100% rename from src/ExceptionReporting/Network/Events/SilentSendEvent.cs rename to ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs diff --git a/src/ExceptionReporting/Network/IReportSender.cs b/ExceptionReporter.Shared/Network/IReportSender.cs similarity index 100% rename from src/ExceptionReporting/Network/IReportSender.cs rename to ExceptionReporter.Shared/Network/IReportSender.cs diff --git a/src/ExceptionReporting/Network/ReportPacket.cs b/ExceptionReporter.Shared/Network/ReportPacket.cs similarity index 100% rename from src/ExceptionReporting/Network/ReportPacket.cs rename to ExceptionReporter.Shared/Network/ReportPacket.cs diff --git a/src/ExceptionReporting/Network/SenderFactory.cs b/ExceptionReporter.Shared/Network/SenderFactory.cs similarity index 100% rename from src/ExceptionReporting/Network/SenderFactory.cs rename to ExceptionReporter.Shared/Network/SenderFactory.cs diff --git a/src/ExceptionReporting/Network/Senders/GhostSender.cs b/ExceptionReporter.Shared/Network/Senders/GhostSender.cs similarity index 100% rename from src/ExceptionReporting/Network/Senders/GhostSender.cs rename to ExceptionReporter.Shared/Network/Senders/GhostSender.cs diff --git a/src/ExceptionReporting/Network/Senders/MailSender.cs b/ExceptionReporter.Shared/Network/Senders/MailSender.cs similarity index 100% rename from src/ExceptionReporting/Network/Senders/MailSender.cs rename to ExceptionReporter.Shared/Network/Senders/MailSender.cs diff --git a/src/ExceptionReporting/Network/Senders/MapiMailSender.cs b/ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs similarity index 93% rename from src/ExceptionReporting/Network/Senders/MapiMailSender.cs rename to ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs index 0e415f33..33283d42 100644 --- a/src/ExceptionReporting/Network/Senders/MapiMailSender.cs +++ b/ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs @@ -1,4 +1,4 @@ -using System.Configuration; +using System.Configuration; using ExceptionReporting.Core; using ExceptionReporting.Mail; using ExceptionReporting.Network.Events; @@ -30,7 +30,7 @@ public void Send(string report) { if (_config.EmailReportAddress.IsEmpty()) { - _sendEvent.ShowError("EmailReportAddress not set", new ConfigurationErrorsException("EmailReportAddress")); + _sendEvent.ShowError("EmailReportAddress not set", new ConfigException("EmailReportAddress")); return; } diff --git a/src/ExceptionReporting/Network/Senders/SmtpMailSender.cs b/ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs similarity index 100% rename from src/ExceptionReporting/Network/Senders/SmtpMailSender.cs rename to ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs diff --git a/src/ExceptionReporting/Network/Senders/WebServiceSender.cs b/ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs similarity index 100% rename from src/ExceptionReporting/Network/Senders/WebServiceSender.cs rename to ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs diff --git a/src/ExceptionReporting/Properties/Resources.Designer.cs b/ExceptionReporter.Shared/Properties/Resources.Designer.cs similarity index 98% rename from src/ExceptionReporting/Properties/Resources.Designer.cs rename to ExceptionReporter.Shared/Properties/Resources.Designer.cs index 612909aa..c81f6620 100644 --- a/src/ExceptionReporting/Properties/Resources.Designer.cs +++ b/ExceptionReporter.Shared/Properties/Resources.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExceptionReporting.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExceptionReporter.WPF.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/ExceptionReporter.Shared/Properties/Resources.en.resx b/ExceptionReporter.Shared/Properties/Resources.en.resx new file mode 100644 index 00000000..c930a5a4 --- /dev/null +++ b/ExceptionReporter.Shared/Properties/Resources.en.resx @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Test Loc + + + Please enter a brief explanation of events leading up to this exception + + + The following details can be used to obtain support for this application + + + Send + + + to {0} + + + Less Detail + + + More Detail + + + Report sent + + + Failed to send report + + + Error sending report + + + Failed trying to report an Error + + + Copied to clipboard + + + Unable to save file + + + Unable to setup + + + If this problem persists, please contact {0} support. + + + ErrorReport + + + Clipboard copy failed + + \ No newline at end of file diff --git a/src/ExceptionReporting/Properties/Resources.resx b/ExceptionReporter.Shared/Properties/Resources.resx similarity index 100% rename from src/ExceptionReporting/Properties/Resources.resx rename to ExceptionReporter.Shared/Properties/Resources.resx diff --git a/ExceptionReporter.Shared/Properties/Resources.ru.resx b/ExceptionReporter.Shared/Properties/Resources.ru.resx new file mode 100644 index 00000000..4857ca54 --- /dev/null +++ b/ExceptionReporter.Shared/Properties/Resources.ru.resx @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ТестЛок + + + Пожалуйста, добавьте краткое описние событий, которые привели к возникновению ошибки: + + + Данная информация сможет быть использована для отладки приложения + + + Отправить + + + в {0} + + + Свернуть + + + Подробнее + + + Отчёт отправлен + + + Ошибка отправления отчёта + + + Ошибка отправки отчёта + + + Скопировано в буфер обмена + + + Не удалось сохранить файл + + + Не удалось произвести настройку + + + Если проблема сохраняется, обратитесь в поддержку {0} + + + Не удалось отправить отчёт + + + Отчёт об ошибке + + + Clipboard copy failed + + \ No newline at end of file diff --git a/src/ExceptionReporting/Report/AssemblyDigger.cs b/ExceptionReporter.Shared/Report/AssemblyDigger.cs similarity index 100% rename from src/ExceptionReporting/Report/AssemblyDigger.cs rename to ExceptionReporter.Shared/Report/AssemblyDigger.cs diff --git a/src/ExceptionReporting/Report/ReportBuilder.cs b/ExceptionReporter.Shared/Report/ReportBuilder.cs similarity index 100% rename from src/ExceptionReporting/Report/ReportBuilder.cs rename to ExceptionReporter.Shared/Report/ReportBuilder.cs diff --git a/src/ExceptionReporting/Report/StackTraceMaker.cs b/ExceptionReporter.Shared/Report/StackTraceMaker.cs similarity index 100% rename from src/ExceptionReporting/Report/StackTraceMaker.cs rename to ExceptionReporter.Shared/Report/StackTraceMaker.cs diff --git a/src/ExceptionReporting/ReportGenerator.cs b/ExceptionReporter.Shared/ReportGenerator.cs similarity index 91% rename from src/ExceptionReporting/ReportGenerator.cs rename to ExceptionReporter.Shared/ReportGenerator.cs index 568970b4..a3b1bc76 100644 --- a/src/ExceptionReporting/ReportGenerator.cs +++ b/ExceptionReporter.Shared/ReportGenerator.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Deployment.Application; using System.Reflection; -using System.Windows.Forms; using ExceptionReporting.Core; using ExceptionReporting.Report; using ExceptionReporting.SystemInfo; @@ -35,27 +34,22 @@ public ReportGenerator(ExceptionReportInfo reportInfo) { // this is going to be a dev/learning mistake - fail fast and hard _info = reportInfo ?? throw new ArgumentNullException(nameof(reportInfo)); - - _info.AppName = _info.AppName.IsEmpty() ? Application.ProductName : _info.AppName; - _info.AppVersion = _info.AppVersion.IsEmpty() ? GetAppVersion() : _info.AppVersion; - _info.ExceptionDate = _info.ExceptionDateKind != DateTimeKind.Local ? DateTime.UtcNow : DateTime.Now; - if (_info.AppAssembly == null) + { _info.AppAssembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly(); + } + + _info.AppName = _info.AppName.IsEmpty() ? _info.AppAssembly.GetName().Name: _info.AppName; + _info.AppVersion = _info.AppVersion.IsEmpty() ? GetAppVersion() : _info.AppVersion; + _info.ExceptionDate = _info.ExceptionDateKind != DateTimeKind.Local ? DateTime.UtcNow : DateTime.Now; } private string GetAppVersion() { return ApplicationDeployment.IsNetworkDeployed ? - ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString() : Application.ProductVersion; + ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString() : _info.AppAssembly.GetName().Version.ToString(); } -// leave commented out for mono to toggle in/out to be able to compile -// private string GetAppVersion() -// { -// return Application.ProductVersion; -// } - /// /// Generate the exception report /// diff --git a/src/ExceptionReporting/SystemInfo/SysInfoQueries.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs similarity index 84% rename from src/ExceptionReporting/SystemInfo/SysInfoQueries.cs rename to ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs index 6fa64e41..ae97d6ae 100644 --- a/src/ExceptionReporting/SystemInfo/SysInfoQueries.cs +++ b/ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs @@ -1,5 +1,6 @@ namespace ExceptionReporting.SystemInfo { + // ReSharper disable once ClassNeverInstantiated.Global internal class SysInfoQueries { public static readonly SysInfoQuery OperatingSystem = new SysInfoQuery("Operating System", "Win32_OperatingSystem", false); diff --git a/src/ExceptionReporting/SystemInfo/SysInfoQuery.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs similarity index 100% rename from src/ExceptionReporting/SystemInfo/SysInfoQuery.cs rename to ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs diff --git a/src/ExceptionReporting/SystemInfo/SysInfoResult.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs similarity index 100% rename from src/ExceptionReporting/SystemInfo/SysInfoResult.cs rename to ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs diff --git a/src/ExceptionReporting/SystemInfo/SysInfoResultMapper.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs similarity index 53% rename from src/ExceptionReporting/SystemInfo/SysInfoResultMapper.cs rename to ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs index 99a5e66d..12d90874 100644 --- a/src/ExceptionReporting/SystemInfo/SysInfoResultMapper.cs +++ b/ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; +using System.Linq; using System.Text; -using System.Windows.Forms; namespace ExceptionReporting.SystemInfo { @@ -16,6 +16,9 @@ internal class SysInfoResultMapper : ISysInfoResultMapper { private readonly IEnumerable _sysInfoResults; + protected SysInfoResultMapper() + { } + public SysInfoResultMapper(IEnumerable sysInfoResults) { _sysInfoResults = sysInfoResults; @@ -36,12 +39,9 @@ public string SysInfoString() { sb.AppendLine("-" + nodeValueParent); - foreach (var childResult in result.ChildResults) + foreach (var nodeValue in result.ChildResults.SelectMany(childResult => childResult.Nodes)) { - foreach (var nodeValue in childResult.Nodes) - { - sb.AppendLine("--" + nodeValue); // the max no. of levels is 2, ie '--' is as deep as we go - } + sb.AppendLine("--" + nodeValue); // the max no. of levels is 2, ie '--' is as deep as we go } } sb.AppendLine(); @@ -49,28 +49,5 @@ public string SysInfoString() return sb.ToString(); } - - /// - /// Add a tree node to an existing parentNode, by passing the SysInfoResult - /// - public static void AddTreeViewNode(TreeNode parentNode, SysInfoResult result) - { - var nodeRoot = new TreeNode(result.Name); - - foreach (var nodeValueParent in result.Nodes) - { - var nodeLeaf = new TreeNode(nodeValueParent); - nodeRoot.Nodes.Add(nodeLeaf); - - foreach (var childResult in result.ChildResults) - { - foreach (var nodeValue in childResult.Nodes) - { - nodeLeaf.Nodes.Add(new TreeNode(nodeValue)); - } - } - } - parentNode.Nodes.Add(nodeRoot); - } } } \ No newline at end of file diff --git a/src/ExceptionReporting/SystemInfo/SysInfoRetriever.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs similarity index 88% rename from src/ExceptionReporting/SystemInfo/SysInfoRetriever.cs rename to ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs index 13d501c1..07f7d08e 100644 --- a/src/ExceptionReporting/SystemInfo/SysInfoRetriever.cs +++ b/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs @@ -25,7 +25,7 @@ public SysInfoResult Retrieve(SysInfoQuery sysInfoQuery) return null; } _sysInfoQuery = sysInfoQuery; - _sysInfoSearcher = new ManagementObjectSearcher(string.Format("SELECT * FROM {0}", _sysInfoQuery.QueryText)); + _sysInfoSearcher = new ManagementObjectSearcher($"SELECT * FROM {_sysInfoQuery.QueryText}"); _sysInfoResult = new SysInfoResult(_sysInfoQuery.Name); foreach (ManagementObject managementObject in _sysInfoSearcher.Get()) @@ -49,7 +49,7 @@ private IEnumerable GetChildren(ManagementBaseObject managementOb childList.Add(childResult); } - var nodeValue = string.Format("{0} = {1}", propertyData.Name, Convert.ToString(propertyData.Value)); + var nodeValue = $"{propertyData.Name} = {Convert.ToString(propertyData.Value)}"; childResult.Nodes.Add(nodeValue); } diff --git a/src/ExceptionReporting/Templates/EmailIntroModel.cs b/ExceptionReporter.Shared/Templates/EmailIntroModel.cs similarity index 100% rename from src/ExceptionReporting/Templates/EmailIntroModel.cs rename to ExceptionReporter.Shared/Templates/EmailIntroModel.cs diff --git a/src/ExceptionReporting/Templates/EmailIntroTemplate.text b/ExceptionReporter.Shared/Templates/EmailIntroTemplate.text similarity index 100% rename from src/ExceptionReporting/Templates/EmailIntroTemplate.text rename to ExceptionReporter.Shared/Templates/EmailIntroTemplate.text diff --git a/src/ExceptionReporting/Templates/ReportModel.cs b/ExceptionReporter.Shared/Templates/ReportModel.cs similarity index 100% rename from src/ExceptionReporting/Templates/ReportModel.cs rename to ExceptionReporter.Shared/Templates/ReportModel.cs diff --git a/src/ExceptionReporting/Templates/ReportTemplate.html b/ExceptionReporter.Shared/Templates/ReportTemplate.html similarity index 100% rename from src/ExceptionReporting/Templates/ReportTemplate.html rename to ExceptionReporter.Shared/Templates/ReportTemplate.html diff --git a/src/ExceptionReporting/Templates/ReportTemplate.markdown b/ExceptionReporter.Shared/Templates/ReportTemplate.markdown similarity index 100% rename from src/ExceptionReporting/Templates/ReportTemplate.markdown rename to ExceptionReporter.Shared/Templates/ReportTemplate.markdown diff --git a/src/ExceptionReporting/Templates/ReportTemplate.text b/ExceptionReporter.Shared/Templates/ReportTemplate.text similarity index 100% rename from src/ExceptionReporting/Templates/ReportTemplate.text rename to ExceptionReporter.Shared/Templates/ReportTemplate.text diff --git a/src/ExceptionReporting/Templates/TemplateFormat.cs b/ExceptionReporter.Shared/Templates/TemplateFormat.cs similarity index 100% rename from src/ExceptionReporting/Templates/TemplateFormat.cs rename to ExceptionReporter.Shared/Templates/TemplateFormat.cs diff --git a/src/ExceptionReporting/Templates/TemplateRenderer.cs b/ExceptionReporter.Shared/Templates/TemplateRenderer.cs similarity index 100% rename from src/ExceptionReporting/Templates/TemplateRenderer.cs rename to ExceptionReporter.Shared/Templates/TemplateRenderer.cs diff --git a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj new file mode 100644 index 00000000..4d0c36aa --- /dev/null +++ b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -0,0 +1,89 @@ + + + + + Debug + AnyCPU + {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED} + library + ExceptionReporter.WPF + ExceptionReporter.WPF + v4.7.2 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\DotNetZip.1.15.0\lib\net40\DotNetZip.dll + + + ..\packages\Handlebars.Net.1.9.0\lib\net40\Handlebars.dll + + + ..\packages\Simple-MAPI.NET.1.1.0\lib\net20\SimpleMapi.dll + + + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + ExceptionReporter.xaml + Code + + + + + Code + + + True + Settings.settings + True + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + \ No newline at end of file diff --git a/ExceptionReporter.WPF/ExceptionReporter.xaml b/ExceptionReporter.WPF/ExceptionReporter.xaml new file mode 100644 index 00000000..21938e45 --- /dev/null +++ b/ExceptionReporter.WPF/ExceptionReporter.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/ExceptionReporter.WPF/ExceptionReporter.xaml.cs b/ExceptionReporter.WPF/ExceptionReporter.xaml.cs new file mode 100644 index 00000000..10e4740d --- /dev/null +++ b/ExceptionReporter.WPF/ExceptionReporter.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ExceptionReporter.WPF +{ + /// + /// Interaction logic for ExceptionReporter.xaml + /// + public partial class ExceptionReporter : UserControl + { + public ExceptionReporter() + { + InitializeComponent(); + } + } +} diff --git a/ExceptionReporter.WPF/Properties/AssemblyInfo.cs b/ExceptionReporter.WPF/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..7f017a46 --- /dev/null +++ b/ExceptionReporter.WPF/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ExceptionReporter.WPF")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ExceptionReporter.WPF")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly:ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ExceptionReporter.WPF/Properties/Settings.Designer.cs b/ExceptionReporter.WPF/Properties/Settings.Designer.cs new file mode 100644 index 00000000..2bf83844 --- /dev/null +++ b/ExceptionReporter.WPF/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ExceptionReporter.WPF.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ExceptionReporter.WPF/Properties/Settings.settings b/ExceptionReporter.WPF/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/ExceptionReporter.WPF/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ExceptionReporter.WPF/packages.config b/ExceptionReporter.WPF/packages.config new file mode 100644 index 00000000..aac1b3c3 --- /dev/null +++ b/ExceptionReporter.WPF/packages.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/src/Demos/WinForms/Demo.WinForms.csproj b/src/Demos/WinForms/Demo.WinForms.csproj index a532d382..0c386c14 100644 --- a/src/Demos/WinForms/Demo.WinForms.csproj +++ b/src/Demos/WinForms/Demo.WinForms.csproj @@ -65,9 +65,9 @@ - - {c49896a3-c0da-45c4-b30e-4d17e548dbf6} - ExceptionReporter.NET + + {1AEEC57B-FB44-4F88-AD50-A2A3686DBC97} + ExceptionReporter.WinForms diff --git a/src/Demos/WinForms/YourCustomReporterView.cs b/src/Demos/WinForms/YourCustomReporterView.cs index d71bcaeb..5cc261a2 100644 --- a/src/Demos/WinForms/YourCustomReporterView.cs +++ b/src/Demos/WinForms/YourCustomReporterView.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Windows.Forms; -using ExceptionReporting.MVP.Views; +using ExceptionReporting.Core; namespace Demo.WinForms { diff --git a/src/Demos/WinForms/YourCustomViewMaker.cs b/src/Demos/WinForms/YourCustomViewMaker.cs index f89d7c8b..b223a8fe 100644 --- a/src/Demos/WinForms/YourCustomViewMaker.cs +++ b/src/Demos/WinForms/YourCustomViewMaker.cs @@ -1,5 +1,5 @@ using System.Windows.Forms; -using ExceptionReporting.MVP.Views; +using ExceptionReporting.Core; namespace Demo.WinForms { diff --git a/src/ExceptionReporting/ExceptionReporter.NET.csproj b/src/ExceptionReporting/ExceptionReporter.WinForms.csproj similarity index 60% rename from src/ExceptionReporting/ExceptionReporter.NET.csproj rename to src/ExceptionReporting/ExceptionReporter.WinForms.csproj index 3f5ef7b9..f8e3f631 100644 --- a/src/ExceptionReporting/ExceptionReporter.NET.csproj +++ b/src/ExceptionReporting/ExceptionReporter.WinForms.csproj @@ -1,4 +1,4 @@ - + ExceptionReporting ExceptionReporter.NET @@ -9,6 +9,10 @@ https://raw.githubusercontent.com/PandaWood/ExceptionReporter.NET/master/LICENSE.txt https://github.com/PandaWood/ExceptionReporter.NET + + + + @@ -17,14 +21,6 @@ - - - - - - - - @@ -33,25 +29,6 @@ - - - True - True - Resources.resx - - - - - ResXFileCodeGenerator - - - ResXFileCodeGenerator - Resources.Designer.cs - - - ResXFileCodeGenerator - - 4.1.0 4.1.0.0 @@ -59,4 +36,13 @@ ExceptionReporter is a .NET component that gathers detailed information on an Exception and the application/system running it. It allows the user to copy, save or email a report to the developer + + + + True + + + + + \ No newline at end of file diff --git a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs index 8d9e3dee..b690e742 100644 --- a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs +++ b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs @@ -10,6 +10,7 @@ using ExceptionReporting.Report; using ExceptionReporting.SystemInfo; using ExceptionReporting.Templates; +using ExceptionReporting.WinForms; namespace ExceptionReporting.MVP.Presenters { diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs b/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs index f69e1f1a..a241ead9 100644 --- a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs +++ b/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Drawing; using System.Windows.Forms; @@ -13,11 +13,11 @@ public ExceptionDetailControl() WireUpEvents(); } - public void SetControlBackgrounds(Color color) + public void SetControlBackgrounds(string color) { listviewExceptions.BackColor = txtExceptionTabMessage.BackColor = - txtExceptionTabStackTrace.BackColor = color; + txtExceptionTabStackTrace.BackColor = ColorTranslator.FromHtml(color); } //TODO this is duplicated almost entirely (without ListView) in ReportBuilder) diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs b/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs index bb699c71..23bf40c2 100644 --- a/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs +++ b/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs @@ -1,3 +1,7 @@ +/* + * https://github.com/PandaWood/ExceptionReporter.NET + */ + using System; using System.Collections.Generic; using System.Drawing; @@ -7,6 +11,7 @@ using ExceptionReporting.MVP.Presenters; using ExceptionReporting.Properties; using ExceptionReporting.SystemInfo; +using ExceptionReporting.WinForms; #pragma warning disable 1591 @@ -68,7 +73,7 @@ private void PopulateReportInfo(ExceptionReportInfo reportInfo) txtApplicationName.BackColor = txtDate.BackColor = txtExceptionMessageLarge.BackColor = - txtExceptionMessage.BackColor = reportInfo.BackgroundColor; + txtExceptionMessage.BackColor = ColorTranslator.FromHtml("#FFCC66"); if (!reportInfo.ShowButtonIcons) { @@ -323,7 +328,7 @@ private TreeNode CreateSysInfoTree() foreach (var sysInfoResult in _presenter.GetSysInfoResults()) { - SysInfoResultMapper.AddTreeViewNode(rootNode, sysInfoResult); + SysInfoResultMapperWinForm.AddTreeViewNode(rootNode, sysInfoResult); } return rootNode; diff --git a/src/ExceptionReporting/MVP/Views/ViewMaker.cs b/src/ExceptionReporting/MVP/Views/ViewMaker.cs index e94f8787..b311f44f 100644 --- a/src/ExceptionReporting/MVP/Views/ViewMaker.cs +++ b/src/ExceptionReporting/MVP/Views/ViewMaker.cs @@ -1,28 +1,9 @@ using System.Windows.Forms; -using ExceptionReporting.MVP.Views; +using ExceptionReporting.Core; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global -/// -/// contract to show view-related things -/// -public interface IViewMaker -{ - /// - /// create the main view/dialog - /// - /// - IExceptionReportView Create(); - - /// - /// show error - /// - /// - /// - void ShowError(string message, string description); -} - namespace ExceptionReporting.MVP.Views { internal class ViewMaker : IViewMaker diff --git a/src/ExceptionReporting/Core/ScreenshotTaker.cs b/src/ExceptionReporting/WinForms/ScreenshotTaker.cs similarity index 93% rename from src/ExceptionReporting/Core/ScreenshotTaker.cs rename to src/ExceptionReporting/WinForms/ScreenshotTaker.cs index f094e1b3..0dc9df68 100644 --- a/src/ExceptionReporting/Core/ScreenshotTaker.cs +++ b/src/ExceptionReporting/WinForms/ScreenshotTaker.cs @@ -2,14 +2,10 @@ using System.Drawing.Imaging; using System.IO; using System.Windows.Forms; +using ExceptionReporting.Core; -namespace ExceptionReporting.Core +namespace ExceptionReporting.WinForms { - internal interface IScreenshotTaker - { - string TakeScreenShot(); - } - /// /// Utility to take a screenshot and return as a graphic file /// diff --git a/src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs b/src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs new file mode 100644 index 00000000..49a084f5 --- /dev/null +++ b/src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs @@ -0,0 +1,36 @@ +/* + * https://github.com/PandaWood/ExceptionReporter.NET + */ + +using System.Linq; +using System.Windows.Forms; +using ExceptionReporting.SystemInfo; + +namespace ExceptionReporting.WinForms +{ + /// + /// WinForms extension + /// + // ReSharper disable once ClassNeverInstantiated.Global + internal class SysInfoResultMapperWinForm : SysInfoResultMapper + { + /// + /// Add a tree node to an existing parentNode, by passing the SysInfoResult + /// + public static void AddTreeViewNode(TreeNode parentNode, SysInfoResult result) + { + var nodeRoot = new TreeNode(result.Name); + + foreach (var nodeLeaf in result.Nodes.Select(nodeValueParent => new TreeNode(nodeValueParent))) + { + nodeRoot.Nodes.Add(nodeLeaf); + + foreach (var nodeValue in result.ChildResults.SelectMany(childResult => childResult.Nodes)) + { + nodeLeaf.Nodes.Add(new TreeNode(nodeValue)); + } + } + parentNode.Nodes.Add(nodeRoot); + } + } +} \ No newline at end of file diff --git a/src/ExceptionReporting/Core/WinformsClipboard.cs b/src/ExceptionReporting/WinForms/WinformsClipboard.cs similarity index 91% rename from src/ExceptionReporting/Core/WinformsClipboard.cs rename to src/ExceptionReporting/WinForms/WinformsClipboard.cs index a353964e..a542d27b 100644 --- a/src/ExceptionReporting/Core/WinformsClipboard.cs +++ b/src/ExceptionReporting/WinForms/WinformsClipboard.cs @@ -1,6 +1,6 @@ using System; -namespace ExceptionReporting.Core +namespace ExceptionReporting.WinForms { internal static class WinFormsClipboard { diff --git a/src/Tests/ExceptionReporter_Tests.cs b/src/Tests/ExceptionReporter_Tests.cs index 6d6b66ae..9c6955d1 100644 --- a/src/Tests/ExceptionReporter_Tests.cs +++ b/src/Tests/ExceptionReporter_Tests.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using ExceptionReporting; -using ExceptionReporting.MVP.Views; +using ExceptionReporting.Core; using Moq; using NUnit.Framework; diff --git a/src/Tests/ReportBuilder_Tests.cs b/src/Tests/ReportBuilder_Tests.cs index e48432d5..ab4d6ff7 100644 --- a/src/Tests/ReportBuilder_Tests.cs +++ b/src/Tests/ReportBuilder_Tests.cs @@ -4,6 +4,7 @@ using ExceptionReporting; using ExceptionReporting.Report; using ExceptionReporting.SystemInfo; +using ExceptionReporting.WinForms; using NUnit.Framework; namespace Tests.ExceptionReporting diff --git a/src/Tests/Tests.ExceptionReporter.NET.csproj b/src/Tests/Tests.ExceptionReporter.NET.csproj index ccbdc60e..97053dfe 100644 --- a/src/Tests/Tests.ExceptionReporter.NET.csproj +++ b/src/Tests/Tests.ExceptionReporter.NET.csproj @@ -15,6 +15,6 @@ - + \ No newline at end of file From bb82b2c20dd17ba86a72b54802a1c46efeaaa9b1 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sat, 31 Jul 2021 11:22:55 +1000 Subject: [PATCH 02/22] all building, test passing - some property resources had to be temporarily commented out --- .../ExceptionReportInfo.cs | 12 +- .../ExceptionReporter.Shared.projitems | 21 +-- ExceptionReporter.Shared/ExceptionReporter.cs | 5 +- .../Properties/Resources.en.resx | 171 ------------------ .../Properties/Resources.ru.resx | 171 ------------------ .../ExceptionReporter.WPF.csproj | 3 +- .../Properties/Settings.Designer.cs | 14 +- .../ExceptionReporter.WinForms.csproj | 21 ++- .../Presenters/ExceptionReportPresenter.cs | 1 - .../Properties/Resources.Designer.cs | 4 +- .../Properties/Resources.resx | 0 src/Tests/ReportBuilder_Tests.cs | 1 - src/Tests/Tests.ExceptionReporter.NET.csproj | 11 +- 13 files changed, 53 insertions(+), 382 deletions(-) delete mode 100644 ExceptionReporter.Shared/Properties/Resources.en.resx delete mode 100644 ExceptionReporter.Shared/Properties/Resources.ru.resx rename {ExceptionReporter.Shared => src/ExceptionReporting}/Properties/Resources.Designer.cs (98%) rename {ExceptionReporter.Shared => src/ExceptionReporting}/Properties/Resources.resx (100%) diff --git a/ExceptionReporter.Shared/ExceptionReportInfo.cs b/ExceptionReporter.Shared/ExceptionReportInfo.cs index bc08e4f3..453b6e85 100644 --- a/ExceptionReporter.Shared/ExceptionReportInfo.cs +++ b/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -7,7 +7,6 @@ using System.Drawing; using System.Net.Mail; using System.Reflection; -using ExceptionReporting.Properties; // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global @@ -226,7 +225,9 @@ public bool ShowEmailButton /// /// The title of the main ExceptionReporter dialog /// - public string TitleText { get; set; } = Resources.ErrorReport; + // public string TitleText { get; set; } = Resources.ErrorReport; + //TODO figure out shared resources + public string TitleText { get; set; } = "ErrorReport"; /// /// Background color of the dialog @@ -360,11 +361,14 @@ public enum ReportSendMethod internal static class DefaultLabelMessages { + //TODO shared resources or move messages out public static readonly string DefaultExplanationLabel = - Resources.Please_enter_a_brief_explanation_of_events_leading_up_to_this_exception; + // Resources.Please_enter_a_brief_explanation_of_events_leading_up_to_this_exception; + "Please_enter_a_brief_explanation_of_events_leading_up_to_this_exception"; public static readonly string DefaultContactMessageTop = - Resources.The_following_details_can_be_used_to_obtain_support_for_this_application; + // Resources.The_following_details_can_be_used_to_obtain_support_for_this_application; + "The_following_details_can_be_used_to_obtain_support_for_this_application"; } } diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems index 7c161bf4..eae4f969 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -33,11 +33,6 @@ - - Resources.resx - True - True - @@ -53,22 +48,12 @@ - - Designer - ResXFileCodeGenerator - - - Designer - Resources.Designer.cs - ResXFileCodeGenerator - - - Designer - ResXFileCodeGenerator - + + + \ No newline at end of file diff --git a/ExceptionReporter.Shared/ExceptionReporter.cs b/ExceptionReporter.Shared/ExceptionReporter.cs index 71cc1334..1c62141f 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.cs +++ b/ExceptionReporter.Shared/ExceptionReporter.cs @@ -6,7 +6,6 @@ using System.Runtime.CompilerServices; using ExceptionReporting.Network; using ExceptionReporting.Network.Events; -using ExceptionReporting.Properties; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global @@ -65,7 +64,9 @@ public bool Show(params Exception[] exceptions) } catch (Exception ex) { - ViewMaker.ShowError(ex.Message, Resources.Failed_trying_to_report_an_Error); + //TODO figure out shared resources between WinForms and WPF or move messages out of common code + // ViewMaker.ShowError(ex.Message, Resources.Failed_trying_to_report_an_Error); + ViewMaker.ShowError(ex.Message, "Failed_trying_to_report_an_Error"); return false; } } diff --git a/ExceptionReporter.Shared/Properties/Resources.en.resx b/ExceptionReporter.Shared/Properties/Resources.en.resx deleted file mode 100644 index c930a5a4..00000000 --- a/ExceptionReporter.Shared/Properties/Resources.en.resx +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Test Loc - - - Please enter a brief explanation of events leading up to this exception - - - The following details can be used to obtain support for this application - - - Send - - - to {0} - - - Less Detail - - - More Detail - - - Report sent - - - Failed to send report - - - Error sending report - - - Failed trying to report an Error - - - Copied to clipboard - - - Unable to save file - - - Unable to setup - - - If this problem persists, please contact {0} support. - - - ErrorReport - - - Clipboard copy failed - - \ No newline at end of file diff --git a/ExceptionReporter.Shared/Properties/Resources.ru.resx b/ExceptionReporter.Shared/Properties/Resources.ru.resx deleted file mode 100644 index 4857ca54..00000000 --- a/ExceptionReporter.Shared/Properties/Resources.ru.resx +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - ТестЛок - - - Пожалуйста, добавьте краткое описние событий, которые привели к возникновению ошибки: - - - Данная информация сможет быть использована для отладки приложения - - - Отправить - - - в {0} - - - Свернуть - - - Подробнее - - - Отчёт отправлен - - - Ошибка отправления отчёта - - - Ошибка отправки отчёта - - - Скопировано в буфер обмена - - - Не удалось сохранить файл - - - Не удалось произвести настройку - - - Если проблема сохраняется, обратитесь в поддержку {0} - - - Не удалось отправить отчёт - - - Отчёт об ошибке - - - Clipboard copy failed - - \ No newline at end of file diff --git a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index 4d0c36aa..f2d5d790 100644 --- a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -8,11 +8,12 @@ library ExceptionReporter.WPF ExceptionReporter.WPF - v4.7.2 + v4.8 512 {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 4 true + true diff --git a/ExceptionReporter.WPF/Properties/Settings.Designer.cs b/ExceptionReporter.WPF/Properties/Settings.Designer.cs index 2bf83844..1a8d6207 100644 --- a/ExceptionReporter.WPF/Properties/Settings.Designer.cs +++ b/ExceptionReporter.WPF/Properties/Settings.Designer.cs @@ -8,21 +8,17 @@ // //------------------------------------------------------------------------------ -namespace ExceptionReporter.WPF.Properties -{ +namespace ExceptionReporter.WPF.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase - { + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - public static Settings Default - { - get - { + public static Settings Default { + get { return defaultInstance; } } diff --git a/src/ExceptionReporting/ExceptionReporter.WinForms.csproj b/src/ExceptionReporting/ExceptionReporter.WinForms.csproj index f8e3f631..1db0eb64 100644 --- a/src/ExceptionReporting/ExceptionReporter.WinForms.csproj +++ b/src/ExceptionReporting/ExceptionReporter.WinForms.csproj @@ -22,6 +22,16 @@ + + + Designer + ResXFileCodeGenerator + + + Designer + ResXFileCodeGenerator + + @@ -41,8 +51,17 @@ True + + Resources.resx + True + True + - + + Designer + Resources.Designer.cs + ResXFileCodeGenerator + \ No newline at end of file diff --git a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs index b690e742..57d269dc 100644 --- a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs +++ b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs @@ -4,7 +4,6 @@ using System.Linq; using ExceptionReporting.Core; using ExceptionReporting.Mail; -using ExceptionReporting.MVP.Views; using ExceptionReporting.Network; using ExceptionReporting.Properties; using ExceptionReporting.Report; diff --git a/ExceptionReporter.Shared/Properties/Resources.Designer.cs b/src/ExceptionReporting/Properties/Resources.Designer.cs similarity index 98% rename from ExceptionReporter.Shared/Properties/Resources.Designer.cs rename to src/ExceptionReporting/Properties/Resources.Designer.cs index c81f6620..612909aa 100644 --- a/ExceptionReporter.Shared/Properties/Resources.Designer.cs +++ b/src/ExceptionReporting/Properties/Resources.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -39,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExceptionReporter.WPF.Properties.Resources", typeof(Resources).Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ExceptionReporting.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; diff --git a/ExceptionReporter.Shared/Properties/Resources.resx b/src/ExceptionReporting/Properties/Resources.resx similarity index 100% rename from ExceptionReporter.Shared/Properties/Resources.resx rename to src/ExceptionReporting/Properties/Resources.resx diff --git a/src/Tests/ReportBuilder_Tests.cs b/src/Tests/ReportBuilder_Tests.cs index ab4d6ff7..e48432d5 100644 --- a/src/Tests/ReportBuilder_Tests.cs +++ b/src/Tests/ReportBuilder_Tests.cs @@ -4,7 +4,6 @@ using ExceptionReporting; using ExceptionReporting.Report; using ExceptionReporting.SystemInfo; -using ExceptionReporting.WinForms; using NUnit.Framework; namespace Tests.ExceptionReporting diff --git a/src/Tests/Tests.ExceptionReporter.NET.csproj b/src/Tests/Tests.ExceptionReporter.NET.csproj index 97053dfe..751848bc 100644 --- a/src/Tests/Tests.ExceptionReporter.NET.csproj +++ b/src/Tests/Tests.ExceptionReporter.NET.csproj @@ -1,6 +1,6 @@  - net452 + net472 Tests.ExceptionReporting 4.0.3 @@ -17,4 +17,13 @@ + + + + + + + True + + \ No newline at end of file From e62c5f9ab8ba992eb140df84b9207ddc4c3b54c5 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sat, 31 Jul 2021 11:38:22 +1000 Subject: [PATCH 03/22] separate out ExceptionReporter main class so WinForms version now compiles/works as it did, with the exception of some resource messages --- ExceptionReporter.Shared/ExceptionReportInfo.cs | 16 +++------------- .../ExceptionReporter.Shared.projitems | 4 ---- ExceptionReporter.Shared/ReportGenerator.cs | 1 - .../SystemInfo/SysInfoRetriever.cs | 4 ---- ExceptionReporter.WPF/ExceptionReporter.xaml | 10 ++++++++-- .../ExceptionReporting}/ExceptionReporter.cs | 12 ++---------- .../MVP/Presenters/ExceptionReportPresenter.cs | 3 +-- .../WinForms/ScreenshotTaker.cs | 2 -- src/Tests/ReportGenerator_Tests.cs | 1 - src/Tests/SystemInfoRetriever_Tests.cs | 10 ---------- 10 files changed, 14 insertions(+), 49 deletions(-) rename {ExceptionReporter.Shared => src/ExceptionReporting}/ExceptionReporter.cs (88%) diff --git a/ExceptionReporter.Shared/ExceptionReportInfo.cs b/ExceptionReporter.Shared/ExceptionReportInfo.cs index 453b6e85..b459a105 100644 --- a/ExceptionReporter.Shared/ExceptionReportInfo.cs +++ b/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -163,28 +163,18 @@ public void SetExceptions(IEnumerable exceptions) /// public bool ShowExceptionsTab { get; set; } = true; - - private bool _showSysInfoTab = true; + /// /// Show/hide *System Information* (SysInfo) tab in dialog /// ignored in Mono /// - public bool ShowSysInfoTab - { - get { return !ExceptionReporter.IsRunningMono() && _showSysInfoTab; } - set { _showSysInfoTab = value; } - } + public bool ShowSysInfoTab { get; set; } = true; - private bool _showAssembliesTab = true; /// /// Show/hide *Assemblies* tab in dialog /// ignored in Mono /// - public bool ShowAssembliesTab - { - get { return !ExceptionReporter.IsRunningMono() && _showAssembliesTab; } - set { _showAssembliesTab = value; } - } + public bool ShowAssembliesTab { get; set; } = true; /// /// Email address used to send the report via email diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems index eae4f969..cdadd35e 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -14,7 +14,6 @@ - @@ -53,7 +52,4 @@ - - - \ No newline at end of file diff --git a/ExceptionReporter.Shared/ReportGenerator.cs b/ExceptionReporter.Shared/ReportGenerator.cs index a3b1bc76..f1dd1bba 100644 --- a/ExceptionReporter.Shared/ReportGenerator.cs +++ b/ExceptionReporter.Shared/ReportGenerator.cs @@ -75,7 +75,6 @@ public string Generate() /// internal IEnumerable GetOrFetchSysInfoResults() { - if (ExceptionReporter.IsRunningMono()) return new List(); if (_sysInfoResults.Count == 0) _sysInfoResults.AddRange(CreateSysInfoResults()); diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs b/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs index 07f7d08e..f4d68a90 100644 --- a/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs +++ b/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs @@ -20,10 +20,6 @@ internal class SysInfoRetriever /// a SysInfoResult ie containing the results of the query public SysInfoResult Retrieve(SysInfoQuery sysInfoQuery) { - if (ExceptionReporter.IsRunningMono()) - { - return null; - } _sysInfoQuery = sysInfoQuery; _sysInfoSearcher = new ManagementObjectSearcher($"SELECT * FROM {_sysInfoQuery.QueryText}"); _sysInfoResult = new SysInfoResult(_sysInfoQuery.Name); diff --git a/ExceptionReporter.WPF/ExceptionReporter.xaml b/ExceptionReporter.WPF/ExceptionReporter.xaml index 21938e45..39992753 100644 --- a/ExceptionReporter.WPF/ExceptionReporter.xaml +++ b/ExceptionReporter.WPF/ExceptionReporter.xaml @@ -7,6 +7,12 @@ mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> - - + + + + + + + + diff --git a/ExceptionReporter.Shared/ExceptionReporter.cs b/src/ExceptionReporting/ExceptionReporter.cs similarity index 88% rename from ExceptionReporter.Shared/ExceptionReporter.cs rename to src/ExceptionReporting/ExceptionReporter.cs index 1c62141f..e4fa8e21 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.cs +++ b/src/ExceptionReporting/ExceptionReporter.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.CompilerServices; +using ExceptionReporting.MVP.Views; using ExceptionReporting.Network; using ExceptionReporting.Network.Events; @@ -34,8 +35,7 @@ public class ExceptionReporter public ExceptionReporter() { _info = new ExceptionReportInfo(); - //TODO make make ViewMaker for wpf/winforms separately - // ViewMaker = new ViewMaker(_info); + ViewMaker = new ViewMaker(_info); } /// @@ -106,14 +106,6 @@ public void Send(params Exception[] exceptions) { Send(new SilentSendEvent(), exceptions); } - - static readonly bool _isRunningMono = System.Type.GetType("Mono.Runtime") != null; - - /// true, if running mono false otherwise. - public static bool IsRunningMono() { return _isRunningMono; } - - /// true, if not running mono false otherwise. - public static bool NotRunningMono() { return !_isRunningMono; } } } diff --git a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs index 57d269dc..9f6d2e61 100644 --- a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs +++ b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs @@ -170,8 +170,7 @@ public void PopulateReport() View.PopulateExceptionTab(ReportInfo.Exceptions); View.PopulateAssembliesTab(); - if (ExceptionReporter.NotRunningMono()) - View.PopulateSysInfoTab(); + View.PopulateSysInfoTab(); } finally { diff --git a/src/ExceptionReporting/WinForms/ScreenshotTaker.cs b/src/ExceptionReporting/WinForms/ScreenshotTaker.cs index 0dc9df68..a75c2d7e 100644 --- a/src/ExceptionReporting/WinForms/ScreenshotTaker.cs +++ b/src/ExceptionReporting/WinForms/ScreenshotTaker.cs @@ -17,8 +17,6 @@ internal class ScreenshotTaker : IScreenshotTaker /// temp file name of JPEG image public string TakeScreenShot() { - if (ExceptionReporter.IsRunningMono()) return null; - var rectangle = Rectangle.Empty; foreach (var screen in Screen.AllScreens) diff --git a/src/Tests/ReportGenerator_Tests.cs b/src/Tests/ReportGenerator_Tests.cs index 8f1b7f62..f52aef31 100644 --- a/src/Tests/ReportGenerator_Tests.cs +++ b/src/Tests/ReportGenerator_Tests.cs @@ -29,7 +29,6 @@ public void Can_Deal_With_Null_In_Constructor() [Test] public void Can_Create_Report_With_A_Couple_Of_Minimal_Bits_That_Should_Exist() { - if (ExceptionReporter.IsRunningMono()) return; var report = _reportGenerator.Generate(); var reportString = report; diff --git a/src/Tests/SystemInfoRetriever_Tests.cs b/src/Tests/SystemInfoRetriever_Tests.cs index 6bef7027..954a68b9 100644 --- a/src/Tests/SystemInfoRetriever_Tests.cs +++ b/src/Tests/SystemInfoRetriever_Tests.cs @@ -18,11 +18,6 @@ public class SystemInfoRetriever_Tests public void Can_Retrieve_SysInfo_For_CPU() { var sysInfoResult = _retriever.Retrieve(SysInfoQueries.Machine); - if (ExceptionReporter.IsRunningMono()) - { - Assert.That(sysInfoResult, Is.Null); - return; - }; Assert.That(sysInfoResult.Nodes.Count, Is.EqualTo(1)); // at least 1 machine name Assert.That(sysInfoResult.ChildResults[0].Nodes.Count, Is.GreaterThan(0)); @@ -33,11 +28,6 @@ public void Can_Retrieve_SysInfo_For_CPU() public void Can_Retrieve_SysInfo_For_OS() { var sysInfoResult = _retriever.Retrieve(SysInfoQueries.OperatingSystem); - if (ExceptionReporter.IsRunningMono()) - { - Assert.That(sysInfoResult, Is.Null); - return; - }; Assert.That(sysInfoResult.Nodes[0], Does.Contain("Windows")); } } From 06ae89410b02410774002c272a00ea28dce5fa33 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sun, 1 Aug 2021 21:19:27 +1000 Subject: [PATCH 04/22] some progress with UI and user control interface --- Demo.WPF/App.xaml | 12 ++-- Demo.WPF/Demo.WPF.csproj | 5 ++ .../{MainWindow.xaml => DummyWindow.xaml} | 13 +++-- Demo.WPF/DummyWindow.xaml.cs | 42 ++++++++++++++ Demo.WPF/MainWindow.xaml.cs | 28 ---------- ExceptionReporter.NET.sln.DotSettings | 2 + .../Core/ExceptionReporterExtensions.cs | 3 +- .../ExceptionReportInfo.cs | 48 ++-------------- .../ExceptionReporter.Shared.projitems | 1 + ExceptionReporter.Shared/ReportGenerator.cs | 2 +- ExceptionReporter.Shared/ReportSendMethod.cs | 34 ++++++++++++ .../Converters/IconToImageSourceConverter.cs | 36 ++++++++++++ .../ExceptionReporter.WPF.csproj | 12 +++- ExceptionReporter.WPF/ExceptionReporter.xaml | 18 ------ .../ExceptionReporter.xaml.cs | 28 ---------- .../MvvM/View/WpfExceptionReporter.xaml | 55 +++++++++++++++++++ .../MvvM/View/WpfExceptionReporter.xaml.cs | 21 +++++++ .../MvvM/ViewModel/MainViewModel.cs | 45 +++++++++++++++ .../Properties/AssemblyInfo.cs | 4 +- .../Properties/Settings.Designer.cs | 2 +- src/ExceptionReporting/ExceptionReporter.cs | 2 +- .../Presenters/ExceptionReportPresenter.cs | 17 ------ .../MVP/Views/ExceptionReportView.cs | 1 - 23 files changed, 276 insertions(+), 155 deletions(-) rename Demo.WPF/{MainWindow.xaml => DummyWindow.xaml} (58%) create mode 100644 Demo.WPF/DummyWindow.xaml.cs delete mode 100644 Demo.WPF/MainWindow.xaml.cs create mode 100644 ExceptionReporter.NET.sln.DotSettings create mode 100644 ExceptionReporter.Shared/ReportSendMethod.cs create mode 100644 ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs delete mode 100644 ExceptionReporter.WPF/ExceptionReporter.xaml delete mode 100644 ExceptionReporter.WPF/ExceptionReporter.xaml.cs create mode 100644 ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml create mode 100644 ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs create mode 100644 ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs diff --git a/Demo.WPF/App.xaml b/Demo.WPF/App.xaml index ebf0b06d..c9efbbc8 100644 --- a/Demo.WPF/App.xaml +++ b/Demo.WPF/App.xaml @@ -1,9 +1,9 @@ - - - - - + StartupUri="DummyWindow.xaml"> + + + + \ No newline at end of file diff --git a/Demo.WPF/Demo.WPF.csproj b/Demo.WPF/Demo.WPF.csproj index 407932cd..088fb4d7 100644 --- a/Demo.WPF/Demo.WPF.csproj +++ b/Demo.WPF/Demo.WPF.csproj @@ -4,6 +4,11 @@ WinExe net5.0-windows true + Demo.WPF.App + + + + diff --git a/Demo.WPF/MainWindow.xaml b/Demo.WPF/DummyWindow.xaml similarity index 58% rename from Demo.WPF/MainWindow.xaml rename to Demo.WPF/DummyWindow.xaml index cbcc3fcd..b9cfb177 100644 --- a/Demo.WPF/MainWindow.xaml +++ b/Demo.WPF/DummyWindow.xaml @@ -1,12 +1,15 @@ - - - - + FontSize="22" + Title="DummyWindow" Height="150" Width="450"> + + + diff --git a/Demo.WPF/DummyWindow.xaml.cs b/Demo.WPF/DummyWindow.xaml.cs new file mode 100644 index 00000000..a4a438e8 --- /dev/null +++ b/Demo.WPF/DummyWindow.xaml.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using ExceptionReporter.WPF.MvvM.View; +using ExceptionReporting; + +namespace Demo.WPF +{ + /// + /// Interaction logic for DummyWindow.xaml + /// + public partial class DummyWindow : Window + { + public DummyWindow() + { + InitializeComponent(); + } + + private void ButtonBase_OnClick(object sender, RoutedEventArgs e) + { + var config = new ExceptionReportInfo + { + SendMethod = ReportSendMethod.SimpleMAPI, + EmailReportAddress = "support@acme.com", + CompanyName = "Acme", + TitleText = "Acme Error Report", + ShowLessDetailButton = true, + ReportTemplateFormat = TemplateFormat.Text, + }; + + var window = new Window + { + Title = "Error Report", + Height = 250, + Width = 400, + Content = new WpfExceptionReporter(new Exception("WPF confluxion error"), config) + }; + + window.ShowDialog(); + } + } +} diff --git a/Demo.WPF/MainWindow.xaml.cs b/Demo.WPF/MainWindow.xaml.cs deleted file mode 100644 index b475e4d1..00000000 --- a/Demo.WPF/MainWindow.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace Demo.WPF -{ - /// - /// Interaction logic for MainWindow.xaml - /// - public partial class MainWindow : Window - { - public MainWindow() - { - InitializeComponent(); - } - } -} diff --git a/ExceptionReporter.NET.sln.DotSettings b/ExceptionReporter.NET.sln.DotSettings new file mode 100644 index 00000000..1c729933 --- /dev/null +++ b/ExceptionReporter.NET.sln.DotSettings @@ -0,0 +1,2 @@ + + MAPI \ No newline at end of file diff --git a/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs b/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs index fa587e99..00a479f7 100644 --- a/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs +++ b/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs @@ -2,7 +2,7 @@ namespace ExceptionReporting.Core { /// /// All extension methods for ExceptionReporter - /// It's important this class is internal/not public - else it will pollute the assembly consumer's extensions + /// It's important this class is internal/not public - else it will pollute the available extensions for users of this library /// internal static class ExceptionReporterExtensions { @@ -19,6 +19,5 @@ public static string Truncate(this string value, int maxLength) if (string.IsNullOrEmpty(value)) return value; return value.Length <= maxLength ? value : value.Substring(0, maxLength); } - } } \ No newline at end of file diff --git a/ExceptionReporter.Shared/ExceptionReportInfo.cs b/ExceptionReporter.Shared/ExceptionReportInfo.cs index b459a105..032aedc1 100644 --- a/ExceptionReporter.Shared/ExceptionReportInfo.cs +++ b/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Drawing; using System.Net.Mail; using System.Reflection; @@ -33,7 +32,7 @@ public class ExceptionReportInfo /// public Exception MainException { - get { return _exceptions.Count > 0 ? _exceptions[0] : new Exception("Empty Exception"); } + get => _exceptions.Count > 0 ? _exceptions[0] : new Exception("Empty Exception"); set { _exceptions.Clear(); @@ -44,10 +43,7 @@ public Exception MainException } } - public Exception[] Exceptions - { - get { return _exceptions.ToArray(); } - } + public Exception[] Exceptions => _exceptions.ToArray(); /// /// Add multiple exceptions @@ -65,7 +61,7 @@ public void SetExceptions(IEnumerable exceptions) /// /// Override the Exception.Message property /// ie a custom message to show in place of the Exception Message - /// NB this can also be set in the 1st parameter of + /// NB this can also be set in the 1st parameter of /// public string CustomMessage { get; set; } @@ -213,7 +209,7 @@ public bool ShowEmailButton } /// - /// The title of the main ExceptionReporter dialog + /// The title of the main WpfExceptionReporter dialog /// // public string TitleText { get; set; } = Resources.ErrorReport; //TODO figure out shared resources @@ -231,7 +227,7 @@ public bool ShowEmailButton public float UserExplanationFontSize { get; set; } = 12f; /// - /// Take a screenshot automatically when attaching + /// Take a screenshot automatically when attaching /// which will then be available if sending an email using the ExceptionReporter dialog functionality /// public bool TakeScreenshot { get; set; } = false; @@ -300,7 +296,7 @@ public string AttachmentFilename public TemplateFormat ReportTemplateFormat { get; set; } = TemplateFormat.Text; /// - /// A custom/user Handlebar template (Handlebars is almost identical to Mustache) - see https://handlebarsjs.com + /// A custom/user Handlebar template (Handlebars is almost identical to Mustache) - /// to use instead of the supplied presets /// A populated model will be passed to the template /// See Templates/ReportTemplate.text for example @@ -316,38 +312,6 @@ public bool IsSimpleMAPI() return SendMethod == ReportSendMethod.SimpleMAPI; } } - - /// - /// The communication method used to send a report - /// - public enum ReportSendMethod - { - /// - /// No sending (default) - /// - None, - - /// - /// Tries to use the Windows default Email client eg Outlook via SMTP - /// If a compatible client isn't installed, it will not work, so there is some risk - but in that case, an - /// error message will prompt the user to use the "Copy" feature and manually send the result - /// - /// requires to be set to a valid email - /// - SimpleMAPI, - - /// - /// Sends an Email via an SMTP server - requires other config (host/port etc) properties starting with 'Smtp' - /// - SMTP, - - /// - /// WebService - requires a REST API server accepting content-type 'application/json' of type POST and a - /// JSON packet containing the properties represented in the DataContract class 'ExceptionReportPacket' - /// An example project doing exactly what is required is included in the ExceptionReporter.NET solution - /// - WebService - } internal static class DefaultLabelMessages { diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems index cdadd35e..1063b2cc 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -33,6 +33,7 @@ + diff --git a/ExceptionReporter.Shared/ReportGenerator.cs b/ExceptionReporter.Shared/ReportGenerator.cs index f1dd1bba..f17614d8 100644 --- a/ExceptionReporter.Shared/ReportGenerator.cs +++ b/ExceptionReporter.Shared/ReportGenerator.cs @@ -39,7 +39,7 @@ public ReportGenerator(ExceptionReportInfo reportInfo) _info.AppAssembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly(); } - _info.AppName = _info.AppName.IsEmpty() ? _info.AppAssembly.GetName().Name: _info.AppName; + _info.AppName = _info.AppName.IsEmpty() ? _info.AppAssembly.GetName().Name: _info.AppName; _info.AppVersion = _info.AppVersion.IsEmpty() ? GetAppVersion() : _info.AppVersion; _info.ExceptionDate = _info.ExceptionDateKind != DateTimeKind.Local ? DateTime.UtcNow : DateTime.Now; } diff --git a/ExceptionReporter.Shared/ReportSendMethod.cs b/ExceptionReporter.Shared/ReportSendMethod.cs new file mode 100644 index 00000000..1f558c16 --- /dev/null +++ b/ExceptionReporter.Shared/ReportSendMethod.cs @@ -0,0 +1,34 @@ +namespace ExceptionReporting +{ + /// + /// The communication method used to send a report + /// + public enum ReportSendMethod + { + /// + /// No sending (default) + /// + None, + + /// + /// Tries to use the Windows default Email client eg Outlook via SMTP + /// If a compatible client isn't installed, it will not work, so there is some risk - but in that case, an + /// error message will prompt the user to use the "Copy" feature and manually send the result + /// + /// requires to be set to a valid email + /// + SimpleMAPI, + + /// + /// Sends an Email via an SMTP server - requires other config (host/port etc) properties starting with 'Smtp' + /// + SMTP, + + /// + /// WebService - requires a REST API server accepting content-type 'application/json' of type POST and a + /// JSON packet containing the properties represented in the DataContract class 'ExceptionReportPacket' + /// An example project demonstrating requirements is included in the fExceptionReporter.NET solution + /// + WebService + } +} \ No newline at end of file diff --git a/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs b/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs new file mode 100644 index 00000000..46276cbb --- /dev/null +++ b/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs @@ -0,0 +1,36 @@ +using System; +using System.Diagnostics; +using System.Drawing; +using System.Globalization; +using System.Windows; +using System.Windows.Data; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Media.Imaging; + +namespace ExceptionReporter.WPF.Converters +{ + public class IconToImageSourceConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var icon = value as Icon; + if (icon == null) + { + Trace.TraceWarning("Attempted to convert {0} instead of Icon object in IconToImageSourceConverter", value); + return null; + } + + ImageSource imageSource = Imaging.CreateBitmapSourceFromHIcon( + icon.Handle, + Int32Rect.Empty, + BitmapSizeOptions.FromEmptyOptions()); + return imageSource; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index f2d5d790..9e1fa7e0 100644 --- a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -45,6 +45,7 @@ + @@ -61,16 +62,18 @@ - + MSBuild:Compile Designer - - ExceptionReporter.xaml + + + WpfExceptionReporter.xaml Code + Code @@ -85,6 +88,9 @@ Settings.Designer.cs + + + \ No newline at end of file diff --git a/ExceptionReporter.WPF/ExceptionReporter.xaml b/ExceptionReporter.WPF/ExceptionReporter.xaml deleted file mode 100644 index 39992753..00000000 --- a/ExceptionReporter.WPF/ExceptionReporter.xaml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - diff --git a/ExceptionReporter.WPF/ExceptionReporter.xaml.cs b/ExceptionReporter.WPF/ExceptionReporter.xaml.cs deleted file mode 100644 index 10e4740d..00000000 --- a/ExceptionReporter.WPF/ExceptionReporter.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; -using System.Windows.Navigation; -using System.Windows.Shapes; - -namespace ExceptionReporter.WPF -{ - /// - /// Interaction logic for ExceptionReporter.xaml - /// - public partial class ExceptionReporter : UserControl - { - public ExceptionReporter() - { - InitializeComponent(); - } - } -} diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml new file mode 100644 index 00000000..f4c1e397 --- /dev/null +++ b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs new file mode 100644 index 00000000..d82d9032 --- /dev/null +++ b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs @@ -0,0 +1,21 @@ +using System; +using System.Windows.Controls; +using ExceptionReporter.WPF.MvvM.ViewModel; +using ExceptionReporting; + +namespace ExceptionReporter.WPF.MvvM.View +{ + /// + /// Interaction logic for WpfExceptionReporter + /// + public partial class WpfExceptionReporter : UserControl + { + public WpfExceptionReporter(Exception exception, ExceptionReportInfo info) + { + InitializeComponent(); + + info.MainException = exception; + this.DataContext = new MainViewModel(info); + } + } +} \ No newline at end of file diff --git a/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs b/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs new file mode 100644 index 00000000..5f712ac2 --- /dev/null +++ b/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs @@ -0,0 +1,45 @@ +using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using ExceptionReporting; + +namespace ExceptionReporter.WPF.MvvM.ViewModel +{ + public class MainViewModel : INotifyPropertyChanged + { + private Exception _exception; + private ExceptionReportInfo _info; + + public MainViewModel(ExceptionReportInfo info) + { + _info = info; + } + + public ExceptionReportInfo Info + { + get => _info; + set + { + _info = value; + NotifyPropertyChanged(); + } + } + + public Exception ExceptionSource + { + get => _exception; + set + { + _exception = value; + NotifyPropertyChanged(); + } + } + + // a quick/simple implementation of observable object - we only need it once + public event PropertyChangedEventHandler PropertyChanged; + private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} \ No newline at end of file diff --git a/ExceptionReporter.WPF/Properties/AssemblyInfo.cs b/ExceptionReporter.WPF/Properties/AssemblyInfo.cs index 7f017a46..a3a242ce 100644 --- a/ExceptionReporter.WPF/Properties/AssemblyInfo.cs +++ b/ExceptionReporter.WPF/Properties/AssemblyInfo.cs @@ -7,11 +7,11 @@ // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("ExceptionReporter.WPF")] +[assembly: AssemblyTitle("WpfExceptionReporter.WPF")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ExceptionReporter.WPF")] +[assembly: AssemblyProduct("WpfExceptionReporter.WPF")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/ExceptionReporter.WPF/Properties/Settings.Designer.cs b/ExceptionReporter.WPF/Properties/Settings.Designer.cs index 1a8d6207..71470b1f 100644 --- a/ExceptionReporter.WPF/Properties/Settings.Designer.cs +++ b/ExceptionReporter.WPF/Properties/Settings.Designer.cs @@ -8,7 +8,7 @@ // //------------------------------------------------------------------------------ -namespace ExceptionReporter.WPF.Properties { +namespace ExceptionReporting.WPF.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] diff --git a/src/ExceptionReporting/ExceptionReporter.cs b/src/ExceptionReporting/ExceptionReporter.cs index e4fa8e21..e8906cec 100644 --- a/src/ExceptionReporting/ExceptionReporter.cs +++ b/src/ExceptionReporting/ExceptionReporter.cs @@ -17,7 +17,7 @@ namespace ExceptionReporting { /// - /// The entry-point (class) to invoking an ExceptionReporter dialog + /// The entry-point (class) to invoking a (WinForms) ExceptionReporter dialog /// eg new ExceptionReporter().Show(exceptions) /// public class ExceptionReporter diff --git a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs index 9f6d2e61..f5764a02 100644 --- a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs +++ b/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs @@ -44,23 +44,6 @@ private string CreateReport() return _reportGenerator.Generate(); } - /// - /// Save the exception report to file/disk - /// - /// the filename to save to - public void SaveTextReportToFile(string fileName) - { - if (string.IsNullOrEmpty(fileName)) return; - - var report = CreateReport(); - var result = _fileService.Write(fileName, report); - - if (!result.Saved) - { - View.ShowError(Resources.Unable_to_save_file + $" '{fileName}'", result.Exception); - } - } - /// /// Save the exception report to file/disk /// diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs b/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs index 23bf40c2..1a1e1300 100644 --- a/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs +++ b/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs @@ -10,7 +10,6 @@ using ExceptionReporting.Core; using ExceptionReporting.MVP.Presenters; using ExceptionReporting.Properties; -using ExceptionReporting.SystemInfo; using ExceptionReporting.WinForms; #pragma warning disable 1591 From 9d7ab58f655307a323bd7720ed491f7386892e3c Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sun, 1 Aug 2021 22:07:08 +1000 Subject: [PATCH 05/22] pulling out the exceptionreporter into a base class so WPF assembly can still the stilent send options --- .../ExceptionReporter.Shared.projitems | 1 + .../ExceptionReporterBase.cs | 57 ++------------ src/Demos/WinForms/DemoApp.cs | 4 +- .../{MVP/Views => WinForms}/ViewMaker.cs | 21 ++++- .../WinFormsExceptionReporter.cs | 76 +++++++++++++++++++ 5 files changed, 107 insertions(+), 52 deletions(-) rename src/ExceptionReporting/ExceptionReporter.cs => ExceptionReporter.Shared/ExceptionReporterBase.cs (52%) rename src/ExceptionReporting/{MVP/Views => WinForms}/ViewMaker.cs (55%) create mode 100644 src/ExceptionReporting/WinFormsExceptionReporter.cs diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems index 1063b2cc..b2211fd4 100644 --- a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems +++ b/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -14,6 +14,7 @@ + diff --git a/src/ExceptionReporting/ExceptionReporter.cs b/ExceptionReporter.Shared/ExceptionReporterBase.cs similarity index 52% rename from src/ExceptionReporting/ExceptionReporter.cs rename to ExceptionReporter.Shared/ExceptionReporterBase.cs index e8906cec..72371209 100644 --- a/src/ExceptionReporting/ExceptionReporter.cs +++ b/ExceptionReporter.Shared/ExceptionReporterBase.cs @@ -4,12 +4,13 @@ using System; using System.Runtime.CompilerServices; -using ExceptionReporting.MVP.Views; using ExceptionReporting.Network; using ExceptionReporting.Network.Events; -// ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedMember.Global +// ReSharper disable ConvertToAutoPropertyWhenPossible +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedType.Global [assembly: InternalsVisibleTo("Tests.ExceptionReporter.NET")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] // for moq @@ -17,25 +18,22 @@ namespace ExceptionReporting { /// - /// The entry-point (class) to invoking a (WinForms) ExceptionReporter dialog + /// The entry-point (class) to invoking either a WinForms dialog or sending /// eg new ExceptionReporter().Show(exceptions) /// - public class ExceptionReporter + public class ExceptionReporterBase { - private readonly ExceptionReportInfo _info; - /// - /// Contract by which to show any dialogs/view + /// /// - public IViewMaker ViewMaker { get; set; } + protected readonly ExceptionReportInfo _info; /// /// Initialise the ExceptionReporter /// - public ExceptionReporter() + public ExceptionReporterBase() { _info = new ExceptionReportInfo(); - ViewMaker = new ViewMaker(_info); } /// @@ -43,45 +41,6 @@ public ExceptionReporter() /// public ExceptionReportInfo Config => _info; - /// - /// Show the ExceptionReport dialog - /// - /// The will analyze the s and - /// create and show the report dialog. - /// The s to show. - public bool Show(params Exception[] exceptions) - { - // silently ignore the mistake of passing null - if (exceptions == null || exceptions.Length == 0 || exceptions.Length >= 1 && exceptions[0] == null) return false; - - try - { - _info.SetExceptions(exceptions); - - var view = ViewMaker.Create(); - view.ShowWindow(); - return true; - } - catch (Exception ex) - { - //TODO figure out shared resources between WinForms and WPF or move messages out of common code - // ViewMaker.ShowError(ex.Message, Resources.Failed_trying_to_report_an_Error); - ViewMaker.ShowError(ex.Message, "Failed_trying_to_report_an_Error"); - return false; - } - } - - /// - /// Show the ExceptionReport dialog with a custom message instead of the Exception's Message property - /// - /// custom (exception) message - /// The exception/s to display in the exception report - public void Show(string customMessage, params Exception[] exceptions) - { - _info.CustomMessage = customMessage; - Show(exceptions); - } - /// /// Send the report, asynchronously, without showing a dialog (silent send) /// must be SMTP or WebService, else this is ignored (silently) diff --git a/src/Demos/WinForms/DemoApp.cs b/src/Demos/WinForms/DemoApp.cs index 18902317..a8c8c22c 100644 --- a/src/Demos/WinForms/DemoApp.cs +++ b/src/Demos/WinForms/DemoApp.cs @@ -2,6 +2,7 @@ using System.IO; using System.Windows.Forms; using ExceptionReporting; +using ExceptionReporting.WinForms; namespace Demo.WinForms { @@ -116,7 +117,8 @@ static void ThrowAndShowExceptionReporter(bool detailView = false) er.Config.ReportTemplateFormat = TemplateFormat.Text; // er.Config.ShowEmailButton = false; // just for testing that removing email button works // er.Config.TemplateFormat = TemplateFormat.Markdown; - + + er.ViewMaker = new ViewMaker(er.Config); er.Show(exception); } } diff --git a/src/ExceptionReporting/MVP/Views/ViewMaker.cs b/src/ExceptionReporting/WinForms/ViewMaker.cs similarity index 55% rename from src/ExceptionReporting/MVP/Views/ViewMaker.cs rename to src/ExceptionReporting/WinForms/ViewMaker.cs index b311f44f..58f9e1b2 100644 --- a/src/ExceptionReporting/MVP/Views/ViewMaker.cs +++ b/src/ExceptionReporting/WinForms/ViewMaker.cs @@ -1,25 +1,42 @@ using System.Windows.Forms; using ExceptionReporting.Core; +using ExceptionReporting.MVP.Views; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable UnusedAutoPropertyAccessor.Global -namespace ExceptionReporting.MVP.Views +namespace ExceptionReporting.WinForms { - internal class ViewMaker : IViewMaker + /// + /// WinForms implementation of ViewMaker + /// + public class ViewMaker : IViewMaker { private readonly ExceptionReportInfo _reportInfo; + /// + /// + /// + /// public ViewMaker(ExceptionReportInfo reportInfo) { _reportInfo = reportInfo; } + /// + /// + /// + /// public IExceptionReportView Create() { return new ExceptionReportView(_reportInfo); } + /// + /// + /// + /// + /// public void ShowError(string message, string description) { MessageBox.Show(message, description, MessageBoxButtons.OK, MessageBoxIcon.Error); diff --git a/src/ExceptionReporting/WinFormsExceptionReporter.cs b/src/ExceptionReporting/WinFormsExceptionReporter.cs new file mode 100644 index 00000000..8ed7afea --- /dev/null +++ b/src/ExceptionReporting/WinFormsExceptionReporter.cs @@ -0,0 +1,76 @@ +using System; +using System.Diagnostics; +using ExceptionReporting.WinForms; + +// ReSharper disable UnusedMember.Global +// ReSharper disable ConvertToAutoPropertyWhenPossible +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedType.Global + +namespace ExceptionReporting +{ + /// + /// The entry-point (class) to invoking a (WinForms) ExceptionReporter dialog + /// eg new ExceptionReporter().Show(exceptions) + /// + public class ExceptionReporter : ExceptionReporterBase + { + /// + /// Initialise the ExceptionReporter + /// + public ExceptionReporter() + { + ViewMaker = new ViewMaker(_info); + } + + /// + /// Contract by which to show any dialogs/view + /// + // ReSharper disable once UnusedAutoPropertyAccessor.Global + public IViewMaker ViewMaker { get; set; } + + /// + /// Show the ExceptionReport dialog + /// + /// The will analyze the s and + /// create and show the report dialog. + /// The s to show. + public bool Show(params Exception[] exceptions) + { + // silently ignore the mistake of passing null + if (exceptions == null || exceptions.Length == 0 || exceptions.Length >= 1 && exceptions[0] == null) return false; + if (ViewMaker == null) + { + Debug.WriteLine("ViewMaker must be initialized. Add `er.ViewMaker = new ViewMaker(er.Config);` where 'er'` is ExceptionReporter object"); + return false; + } + + try + { + _info.SetExceptions(exceptions); + + var view = ViewMaker.Create(); + view.ShowWindow(); + return true; + } + catch (Exception ex) + { + //TODO figure out shared resources between WinForms and WPF or move messages out of common code + // ViewMaker.ShowError(ex.Message, Resources.Failed_trying_to_report_an_Error); + ViewMaker.ShowError(ex.Message, "Failed_trying_to_report_an_Error"); + return false; + } + } + + /// + /// Show the ExceptionReport dialog with a custom message instead of the Exception's Message property + /// + /// custom (exception) message + /// The exception/s to display in the exception report + public void Show(string customMessage, params Exception[] exceptions) + { + _info.CustomMessage = customMessage; + Show(exceptions); + } + } +} From 18aec1e1269a9cfb9a4a5f8beec89e1ea97feb92 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Wed, 4 Aug 2021 00:02:36 +1000 Subject: [PATCH 06/22] compatibility and contining XAML UI --- Demo.WPF/DummyWindow.xaml.cs | 2 +- .../Converters/IconToImageSourceConverter.cs | 2 +- .../ExceptionReporter.WPF.csproj | 2 +- .../MvvM/View/WpfExceptionReporter.xaml | 49 ++++++++++--------- .../MvvM/View/WpfExceptionReporter.xaml.cs | 5 +- .../MvvM/ViewModel/MainViewModel.cs | 14 +----- 6 files changed, 33 insertions(+), 41 deletions(-) diff --git a/Demo.WPF/DummyWindow.xaml.cs b/Demo.WPF/DummyWindow.xaml.cs index a4a438e8..7e64fd34 100644 --- a/Demo.WPF/DummyWindow.xaml.cs +++ b/Demo.WPF/DummyWindow.xaml.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; using System.Windows; -using ExceptionReporter.WPF.MvvM.View; using ExceptionReporting; +using ExceptionReporting.WPF.MvvM.View; namespace Demo.WPF { diff --git a/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs b/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs index 46276cbb..41a2c334 100644 --- a/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs +++ b/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs @@ -8,7 +8,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; -namespace ExceptionReporter.WPF.Converters +namespace ExceptionReporting.WPF.Converters { public class IconToImageSourceConverter : IValueConverter { diff --git a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index 9e1fa7e0..9297578e 100644 --- a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -6,7 +6,7 @@ AnyCPU {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED} library - ExceptionReporter.WPF + ExceptionReporting.WPF ExceptionReporter.WPF v4.8 512 diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index f4c1e397..df549b57 100644 --- a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -1,12 +1,11 @@ - @@ -14,20 +13,20 @@ - + - - + + + - - + @@ -38,18 +37,24 @@ - - - - - - - - - - - - + + + + + + + + + + + diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs index d82d9032..330ecf7d 100644 --- a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs +++ b/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs @@ -1,9 +1,8 @@ using System; using System.Windows.Controls; -using ExceptionReporter.WPF.MvvM.ViewModel; -using ExceptionReporting; +using ExceptionReporting.WPF.MvvM.ViewModel; -namespace ExceptionReporter.WPF.MvvM.View +namespace ExceptionReporting.WPF.MvvM.View { /// /// Interaction logic for WpfExceptionReporter diff --git a/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs b/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs index 5f712ac2..a00bfe80 100644 --- a/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs +++ b/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs @@ -1,13 +1,11 @@ using System; using System.ComponentModel; using System.Runtime.CompilerServices; -using ExceptionReporting; -namespace ExceptionReporter.WPF.MvvM.ViewModel +namespace ExceptionReporting.WPF.MvvM.ViewModel { public class MainViewModel : INotifyPropertyChanged { - private Exception _exception; private ExceptionReportInfo _info; public MainViewModel(ExceptionReportInfo info) @@ -25,16 +23,6 @@ public ExceptionReportInfo Info } } - public Exception ExceptionSource - { - get => _exception; - set - { - _exception = value; - NotifyPropertyChanged(); - } - } - // a quick/simple implementation of observable object - we only need it once public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") From cc0814f1601b238448e5dcc78468b741e592518d Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Wed, 4 Aug 2021 20:09:04 +1000 Subject: [PATCH 07/22] fix folder locations and progress ui layoutbuttons --- ExceptionReporter.NET.sln | 14 ++--- {Demo.WPF => src/Demos/WPF}/App.xaml | 0 {Demo.WPF => src/Demos/WPF}/App.xaml.cs | 0 {Demo.WPF => src/Demos/WPF}/AssemblyInfo.cs | 0 {Demo.WPF => src/Demos/WPF}/Demo.WPF.csproj | 2 +- {Demo.WPF => src/Demos/WPF}/DummyWindow.xaml | 0 .../Demos/WPF}/DummyWindow.xaml.cs | 0 src/Demos/WinForms/Demo.WinForms.csproj | 2 +- .../Core/ConfigException.cs | 0 .../Core/ExceptionReporterExtensions.cs | 0 .../Core/FileService.cs | 0 .../Core/IExceptionReportView.cs | 0 .../Core/IScreenshotTaker.cs | 0 .../Core/IViewMaker.cs | 0 .../Core/IZipReportService.cs | 0 .../Core/ZipReportService.cs | 0 .../ExceptionReportInfo.cs | 0 .../ExceptionReporter.Shared.projitems | 0 .../ExceptionReporter.Shared.shproj | 0 .../ExceptionReporterBase.cs | 0 .../Mail/AttachAdapter.cs | 0 .../Mail/Attacher.cs | 0 .../ExceptionReporter.Shared}/Mail/Zipper.cs | 0 .../Network/Events/ConsoleSendEvent.cs | 0 .../Network/Events/IReportSendEvent.cs | 0 .../Network/Events/SilentSendEvent.cs | 0 .../Network/IReportSender.cs | 0 .../Network/ReportPacket.cs | 0 .../Network/SenderFactory.cs | 0 .../Network/Senders/GhostSender.cs | 0 .../Network/Senders/MailSender.cs | 0 .../Network/Senders/MapiMailSender.cs | 0 .../Network/Senders/SmtpMailSender.cs | 0 .../Network/Senders/WebServiceSender.cs | 0 .../Report/AssemblyDigger.cs | 0 .../Report/ReportBuilder.cs | 0 .../Report/StackTraceMaker.cs | 0 .../ReportGenerator.cs | 0 .../ReportSendMethod.cs | 0 .../SystemInfo/SysInfoQueries.cs | 0 .../SystemInfo/SysInfoQuery.cs | 0 .../SystemInfo/SysInfoResult.cs | 0 .../SystemInfo/SysInfoResultMapper.cs | 0 .../SystemInfo/SysInfoRetriever.cs | 0 .../Templates/EmailIntroModel.cs | 0 .../Templates/EmailIntroTemplate.text | 0 .../Templates/ReportModel.cs | 0 .../Templates/ReportTemplate.html | 0 .../Templates/ReportTemplate.markdown | 0 .../Templates/ReportTemplate.text | 0 .../Templates/TemplateFormat.cs | 0 .../Templates/TemplateRenderer.cs | 0 .../Converters/IconToImageSourceConverter.cs | 0 .../ExceptionReporter.WPF.csproj | 5 ++ .../Images/clipboard.png | Bin 0 -> 8731 bytes src/ExceptionReporter.WPF/Images/envelope.png | Bin 0 -> 16186 bytes src/ExceptionReporter.WPF/Images/magnify.png | Bin 0 -> 25107 bytes .../MvvM/View/WpfExceptionReporter.xaml | 48 +++++++++++++++--- .../MvvM/View/WpfExceptionReporter.xaml.cs | 0 .../MvvM/ViewModel/MainViewModel.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../Properties/Settings.Designer.cs | 0 .../Properties/Settings.settings | 0 .../ExceptionReporter.WPF}/packages.config | 0 .../ExceptionReporter.WinForms.csproj | 2 +- .../Presenters/ExceptionReportPresenter.cs | 0 .../Views/ExceptionDetailControl.Designer.cs | 0 .../MVP/Views/ExceptionDetailControl.cs | 0 .../MVP/Views/ExceptionDetailControl.en.resx | 0 .../MVP/Views/ExceptionDetailControl.resx | 0 .../MVP/Views/ExceptionDetailControl.ru.resx | 0 .../MVP/Views/ExceptionReportView.Designer.cs | 0 .../MVP/Views/ExceptionReportView.cs | 0 .../MVP/Views/ExceptionReportView.en.resx | 0 .../MVP/Views/ExceptionReportView.resx | 0 .../MVP/Views/ExceptionReportView.ru.resx | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.en.resx | 0 .../Properties/Resources.resx | 0 .../Properties/Resources.ru.resx | 0 .../WinForms/ScreenshotTaker.cs | 0 .../WinForms/SysInfoResultMapperWinForm.cs | 0 .../WinForms/ViewMaker.cs | 0 .../WinForms/WinformsClipboard.cs | 0 .../WinFormsExceptionReporter.cs | 0 src/Tests/Tests.ExceptionReporter.NET.csproj | 2 +- 86 files changed, 57 insertions(+), 18 deletions(-) rename {Demo.WPF => src/Demos/WPF}/App.xaml (100%) rename {Demo.WPF => src/Demos/WPF}/App.xaml.cs (100%) rename {Demo.WPF => src/Demos/WPF}/AssemblyInfo.cs (100%) rename {Demo.WPF => src/Demos/WPF}/Demo.WPF.csproj (75%) rename {Demo.WPF => src/Demos/WPF}/DummyWindow.xaml (100%) rename {Demo.WPF => src/Demos/WPF}/DummyWindow.xaml.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/ConfigException.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/ExceptionReporterExtensions.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/FileService.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/IExceptionReportView.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/IScreenshotTaker.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/IViewMaker.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/IZipReportService.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Core/ZipReportService.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ExceptionReportInfo.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ExceptionReporter.Shared.projitems (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ExceptionReporter.Shared.shproj (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ExceptionReporterBase.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Mail/AttachAdapter.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Mail/Attacher.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Mail/Zipper.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Events/ConsoleSendEvent.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Events/IReportSendEvent.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Events/SilentSendEvent.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/IReportSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/ReportPacket.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/SenderFactory.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Senders/GhostSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Senders/MailSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Senders/MapiMailSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Senders/SmtpMailSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Network/Senders/WebServiceSender.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Report/AssemblyDigger.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Report/ReportBuilder.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Report/StackTraceMaker.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ReportGenerator.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/ReportSendMethod.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/SystemInfo/SysInfoQueries.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/SystemInfo/SysInfoQuery.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/SystemInfo/SysInfoResult.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/SystemInfo/SysInfoResultMapper.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/SystemInfo/SysInfoRetriever.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/EmailIntroModel.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/EmailIntroTemplate.text (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/ReportModel.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/ReportTemplate.html (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/ReportTemplate.markdown (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/ReportTemplate.text (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/TemplateFormat.cs (100%) rename {ExceptionReporter.Shared => src/ExceptionReporter.Shared}/Templates/TemplateRenderer.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/Converters/IconToImageSourceConverter.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/ExceptionReporter.WPF.csproj (96%) create mode 100644 src/ExceptionReporter.WPF/Images/clipboard.png create mode 100644 src/ExceptionReporter.WPF/Images/envelope.png create mode 100644 src/ExceptionReporter.WPF/Images/magnify.png rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/MvvM/View/WpfExceptionReporter.xaml (54%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/MvvM/View/WpfExceptionReporter.xaml.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/MvvM/ViewModel/MainViewModel.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/Properties/AssemblyInfo.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/Properties/Settings.Designer.cs (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/Properties/Settings.settings (100%) rename {ExceptionReporter.WPF => src/ExceptionReporter.WPF}/packages.config (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/ExceptionReporter.WinForms.csproj (96%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Presenters/ExceptionReportPresenter.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionDetailControl.Designer.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionDetailControl.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionDetailControl.en.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionDetailControl.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionDetailControl.ru.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionReportView.Designer.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionReportView.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionReportView.en.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionReportView.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/MVP/Views/ExceptionReportView.ru.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/Properties/Resources.Designer.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/Properties/Resources.en.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/Properties/Resources.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/Properties/Resources.ru.resx (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/WinForms/ScreenshotTaker.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/WinForms/SysInfoResultMapperWinForm.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/WinForms/ViewMaker.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/WinForms/WinformsClipboard.cs (100%) rename src/{ExceptionReporting => ExceptionReporter.WinForms}/WinFormsExceptionReporter.cs (100%) diff --git a/ExceptionReporter.NET.sln b/ExceptionReporter.NET.sln index 359090ae..75d1da67 100644 --- a/ExceptionReporter.NET.sln +++ b/ExceptionReporter.NET.sln @@ -3,23 +3,23 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31402.337 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionReporter.WinForms", "src\ExceptionReporting\ExceptionReporter.WinForms.csproj", "{1AEEC57B-FB44-4F88-AD50-A2A3686DBC97}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExceptionReporter.WinForms", "src\ExceptionReporter.WinForms\ExceptionReporter.WinForms.csproj", "{1AEEC57B-FB44-4F88-AD50-A2A3686DBC97}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tests.ExceptionReporter.Net", "src\Tests\Tests.ExceptionReporter.Net.csproj", "{565583C0-0162-4973-962B-7C3F6EE1A4B0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.WinForms", "src\Demos\WinForms\Demo.WinForms.csproj", "{2FC9BAC6-3AC4-43C2-A8E2-C9655446531E}" EndProject -Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ExceptionReporter.Shared", "ExceptionReporter.Shared\ExceptionReporter.Shared.shproj", "{AAEEE6CD-9D37-424E-B62A-E7D28D3391F4}" +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ExceptionReporter.Shared", "src\ExceptionReporter.Shared\ExceptionReporter.Shared.shproj", "{AAEEE6CD-9D37-424E-B62A-E7D28D3391F4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo.WPF", "Demo.WPF\Demo.WPF.csproj", "{37CAA53A-D158-4E3A-B760-16AEE4008154}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo.WPF", "src\Demos\WPF\Demo.WPF.csproj", "{37CAA53A-D158-4E3A-B760-16AEE4008154}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExceptionReporter.WPF", "ExceptionReporter.WPF\ExceptionReporter.WPF.csproj", "{EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExceptionReporter.WPF", "src\ExceptionReporter.WPF\ExceptionReporter.WPF.csproj", "{EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution - ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{1aeec57b-fb44-4f88-ad50-a2a3686dbc97}*SharedItemsImports = 5 - ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{aaeee6cd-9d37-424e-b62a-e7d28d3391f4}*SharedItemsImports = 13 - ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{ef418ef6-d1db-4cb0-9e77-afc5d7c64aed}*SharedItemsImports = 4 + src\ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{1aeec57b-fb44-4f88-ad50-a2a3686dbc97}*SharedItemsImports = 5 + src\ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{aaeee6cd-9d37-424e-b62a-e7d28d3391f4}*SharedItemsImports = 13 + src\ExceptionReporter.Shared\ExceptionReporter.Shared.projitems*{ef418ef6-d1db-4cb0-9e77-afc5d7c64aed}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/Demo.WPF/App.xaml b/src/Demos/WPF/App.xaml similarity index 100% rename from Demo.WPF/App.xaml rename to src/Demos/WPF/App.xaml diff --git a/Demo.WPF/App.xaml.cs b/src/Demos/WPF/App.xaml.cs similarity index 100% rename from Demo.WPF/App.xaml.cs rename to src/Demos/WPF/App.xaml.cs diff --git a/Demo.WPF/AssemblyInfo.cs b/src/Demos/WPF/AssemblyInfo.cs similarity index 100% rename from Demo.WPF/AssemblyInfo.cs rename to src/Demos/WPF/AssemblyInfo.cs diff --git a/Demo.WPF/Demo.WPF.csproj b/src/Demos/WPF/Demo.WPF.csproj similarity index 75% rename from Demo.WPF/Demo.WPF.csproj rename to src/Demos/WPF/Demo.WPF.csproj index 088fb4d7..209c946f 100644 --- a/Demo.WPF/Demo.WPF.csproj +++ b/src/Demos/WPF/Demo.WPF.csproj @@ -8,7 +8,7 @@ - + diff --git a/Demo.WPF/DummyWindow.xaml b/src/Demos/WPF/DummyWindow.xaml similarity index 100% rename from Demo.WPF/DummyWindow.xaml rename to src/Demos/WPF/DummyWindow.xaml diff --git a/Demo.WPF/DummyWindow.xaml.cs b/src/Demos/WPF/DummyWindow.xaml.cs similarity index 100% rename from Demo.WPF/DummyWindow.xaml.cs rename to src/Demos/WPF/DummyWindow.xaml.cs diff --git a/src/Demos/WinForms/Demo.WinForms.csproj b/src/Demos/WinForms/Demo.WinForms.csproj index 0c386c14..aa13cc26 100644 --- a/src/Demos/WinForms/Demo.WinForms.csproj +++ b/src/Demos/WinForms/Demo.WinForms.csproj @@ -65,7 +65,7 @@ - + {1AEEC57B-FB44-4F88-AD50-A2A3686DBC97} ExceptionReporter.WinForms diff --git a/ExceptionReporter.Shared/Core/ConfigException.cs b/src/ExceptionReporter.Shared/Core/ConfigException.cs similarity index 100% rename from ExceptionReporter.Shared/Core/ConfigException.cs rename to src/ExceptionReporter.Shared/Core/ConfigException.cs diff --git a/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs b/src/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs similarity index 100% rename from ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs rename to src/ExceptionReporter.Shared/Core/ExceptionReporterExtensions.cs diff --git a/ExceptionReporter.Shared/Core/FileService.cs b/src/ExceptionReporter.Shared/Core/FileService.cs similarity index 100% rename from ExceptionReporter.Shared/Core/FileService.cs rename to src/ExceptionReporter.Shared/Core/FileService.cs diff --git a/ExceptionReporter.Shared/Core/IExceptionReportView.cs b/src/ExceptionReporter.Shared/Core/IExceptionReportView.cs similarity index 100% rename from ExceptionReporter.Shared/Core/IExceptionReportView.cs rename to src/ExceptionReporter.Shared/Core/IExceptionReportView.cs diff --git a/ExceptionReporter.Shared/Core/IScreenshotTaker.cs b/src/ExceptionReporter.Shared/Core/IScreenshotTaker.cs similarity index 100% rename from ExceptionReporter.Shared/Core/IScreenshotTaker.cs rename to src/ExceptionReporter.Shared/Core/IScreenshotTaker.cs diff --git a/ExceptionReporter.Shared/Core/IViewMaker.cs b/src/ExceptionReporter.Shared/Core/IViewMaker.cs similarity index 100% rename from ExceptionReporter.Shared/Core/IViewMaker.cs rename to src/ExceptionReporter.Shared/Core/IViewMaker.cs diff --git a/ExceptionReporter.Shared/Core/IZipReportService.cs b/src/ExceptionReporter.Shared/Core/IZipReportService.cs similarity index 100% rename from ExceptionReporter.Shared/Core/IZipReportService.cs rename to src/ExceptionReporter.Shared/Core/IZipReportService.cs diff --git a/ExceptionReporter.Shared/Core/ZipReportService.cs b/src/ExceptionReporter.Shared/Core/ZipReportService.cs similarity index 100% rename from ExceptionReporter.Shared/Core/ZipReportService.cs rename to src/ExceptionReporter.Shared/Core/ZipReportService.cs diff --git a/ExceptionReporter.Shared/ExceptionReportInfo.cs b/src/ExceptionReporter.Shared/ExceptionReportInfo.cs similarity index 100% rename from ExceptionReporter.Shared/ExceptionReportInfo.cs rename to src/ExceptionReporter.Shared/ExceptionReportInfo.cs diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems similarity index 100% rename from ExceptionReporter.Shared/ExceptionReporter.Shared.projitems rename to src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems diff --git a/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj b/src/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj similarity index 100% rename from ExceptionReporter.Shared/ExceptionReporter.Shared.shproj rename to src/ExceptionReporter.Shared/ExceptionReporter.Shared.shproj diff --git a/ExceptionReporter.Shared/ExceptionReporterBase.cs b/src/ExceptionReporter.Shared/ExceptionReporterBase.cs similarity index 100% rename from ExceptionReporter.Shared/ExceptionReporterBase.cs rename to src/ExceptionReporter.Shared/ExceptionReporterBase.cs diff --git a/ExceptionReporter.Shared/Mail/AttachAdapter.cs b/src/ExceptionReporter.Shared/Mail/AttachAdapter.cs similarity index 100% rename from ExceptionReporter.Shared/Mail/AttachAdapter.cs rename to src/ExceptionReporter.Shared/Mail/AttachAdapter.cs diff --git a/ExceptionReporter.Shared/Mail/Attacher.cs b/src/ExceptionReporter.Shared/Mail/Attacher.cs similarity index 100% rename from ExceptionReporter.Shared/Mail/Attacher.cs rename to src/ExceptionReporter.Shared/Mail/Attacher.cs diff --git a/ExceptionReporter.Shared/Mail/Zipper.cs b/src/ExceptionReporter.Shared/Mail/Zipper.cs similarity index 100% rename from ExceptionReporter.Shared/Mail/Zipper.cs rename to src/ExceptionReporter.Shared/Mail/Zipper.cs diff --git a/ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs b/src/ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs rename to src/ExceptionReporter.Shared/Network/Events/ConsoleSendEvent.cs diff --git a/ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs b/src/ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs rename to src/ExceptionReporter.Shared/Network/Events/IReportSendEvent.cs diff --git a/ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs b/src/ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs rename to src/ExceptionReporter.Shared/Network/Events/SilentSendEvent.cs diff --git a/ExceptionReporter.Shared/Network/IReportSender.cs b/src/ExceptionReporter.Shared/Network/IReportSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/IReportSender.cs rename to src/ExceptionReporter.Shared/Network/IReportSender.cs diff --git a/ExceptionReporter.Shared/Network/ReportPacket.cs b/src/ExceptionReporter.Shared/Network/ReportPacket.cs similarity index 100% rename from ExceptionReporter.Shared/Network/ReportPacket.cs rename to src/ExceptionReporter.Shared/Network/ReportPacket.cs diff --git a/ExceptionReporter.Shared/Network/SenderFactory.cs b/src/ExceptionReporter.Shared/Network/SenderFactory.cs similarity index 100% rename from ExceptionReporter.Shared/Network/SenderFactory.cs rename to src/ExceptionReporter.Shared/Network/SenderFactory.cs diff --git a/ExceptionReporter.Shared/Network/Senders/GhostSender.cs b/src/ExceptionReporter.Shared/Network/Senders/GhostSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Senders/GhostSender.cs rename to src/ExceptionReporter.Shared/Network/Senders/GhostSender.cs diff --git a/ExceptionReporter.Shared/Network/Senders/MailSender.cs b/src/ExceptionReporter.Shared/Network/Senders/MailSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Senders/MailSender.cs rename to src/ExceptionReporter.Shared/Network/Senders/MailSender.cs diff --git a/ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs b/src/ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs rename to src/ExceptionReporter.Shared/Network/Senders/MapiMailSender.cs diff --git a/ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs b/src/ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs rename to src/ExceptionReporter.Shared/Network/Senders/SmtpMailSender.cs diff --git a/ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs b/src/ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs similarity index 100% rename from ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs rename to src/ExceptionReporter.Shared/Network/Senders/WebServiceSender.cs diff --git a/ExceptionReporter.Shared/Report/AssemblyDigger.cs b/src/ExceptionReporter.Shared/Report/AssemblyDigger.cs similarity index 100% rename from ExceptionReporter.Shared/Report/AssemblyDigger.cs rename to src/ExceptionReporter.Shared/Report/AssemblyDigger.cs diff --git a/ExceptionReporter.Shared/Report/ReportBuilder.cs b/src/ExceptionReporter.Shared/Report/ReportBuilder.cs similarity index 100% rename from ExceptionReporter.Shared/Report/ReportBuilder.cs rename to src/ExceptionReporter.Shared/Report/ReportBuilder.cs diff --git a/ExceptionReporter.Shared/Report/StackTraceMaker.cs b/src/ExceptionReporter.Shared/Report/StackTraceMaker.cs similarity index 100% rename from ExceptionReporter.Shared/Report/StackTraceMaker.cs rename to src/ExceptionReporter.Shared/Report/StackTraceMaker.cs diff --git a/ExceptionReporter.Shared/ReportGenerator.cs b/src/ExceptionReporter.Shared/ReportGenerator.cs similarity index 100% rename from ExceptionReporter.Shared/ReportGenerator.cs rename to src/ExceptionReporter.Shared/ReportGenerator.cs diff --git a/ExceptionReporter.Shared/ReportSendMethod.cs b/src/ExceptionReporter.Shared/ReportSendMethod.cs similarity index 100% rename from ExceptionReporter.Shared/ReportSendMethod.cs rename to src/ExceptionReporter.Shared/ReportSendMethod.cs diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs b/src/ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs similarity index 100% rename from ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs rename to src/ExceptionReporter.Shared/SystemInfo/SysInfoQueries.cs diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs b/src/ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs similarity index 100% rename from ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs rename to src/ExceptionReporter.Shared/SystemInfo/SysInfoQuery.cs diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs b/src/ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs similarity index 100% rename from ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs rename to src/ExceptionReporter.Shared/SystemInfo/SysInfoResult.cs diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs b/src/ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs similarity index 100% rename from ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs rename to src/ExceptionReporter.Shared/SystemInfo/SysInfoResultMapper.cs diff --git a/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs b/src/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs similarity index 100% rename from ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs rename to src/ExceptionReporter.Shared/SystemInfo/SysInfoRetriever.cs diff --git a/ExceptionReporter.Shared/Templates/EmailIntroModel.cs b/src/ExceptionReporter.Shared/Templates/EmailIntroModel.cs similarity index 100% rename from ExceptionReporter.Shared/Templates/EmailIntroModel.cs rename to src/ExceptionReporter.Shared/Templates/EmailIntroModel.cs diff --git a/ExceptionReporter.Shared/Templates/EmailIntroTemplate.text b/src/ExceptionReporter.Shared/Templates/EmailIntroTemplate.text similarity index 100% rename from ExceptionReporter.Shared/Templates/EmailIntroTemplate.text rename to src/ExceptionReporter.Shared/Templates/EmailIntroTemplate.text diff --git a/ExceptionReporter.Shared/Templates/ReportModel.cs b/src/ExceptionReporter.Shared/Templates/ReportModel.cs similarity index 100% rename from ExceptionReporter.Shared/Templates/ReportModel.cs rename to src/ExceptionReporter.Shared/Templates/ReportModel.cs diff --git a/ExceptionReporter.Shared/Templates/ReportTemplate.html b/src/ExceptionReporter.Shared/Templates/ReportTemplate.html similarity index 100% rename from ExceptionReporter.Shared/Templates/ReportTemplate.html rename to src/ExceptionReporter.Shared/Templates/ReportTemplate.html diff --git a/ExceptionReporter.Shared/Templates/ReportTemplate.markdown b/src/ExceptionReporter.Shared/Templates/ReportTemplate.markdown similarity index 100% rename from ExceptionReporter.Shared/Templates/ReportTemplate.markdown rename to src/ExceptionReporter.Shared/Templates/ReportTemplate.markdown diff --git a/ExceptionReporter.Shared/Templates/ReportTemplate.text b/src/ExceptionReporter.Shared/Templates/ReportTemplate.text similarity index 100% rename from ExceptionReporter.Shared/Templates/ReportTemplate.text rename to src/ExceptionReporter.Shared/Templates/ReportTemplate.text diff --git a/ExceptionReporter.Shared/Templates/TemplateFormat.cs b/src/ExceptionReporter.Shared/Templates/TemplateFormat.cs similarity index 100% rename from ExceptionReporter.Shared/Templates/TemplateFormat.cs rename to src/ExceptionReporter.Shared/Templates/TemplateFormat.cs diff --git a/ExceptionReporter.Shared/Templates/TemplateRenderer.cs b/src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs similarity index 100% rename from ExceptionReporter.Shared/Templates/TemplateRenderer.cs rename to src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs diff --git a/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs b/src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs similarity index 100% rename from ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs rename to src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs diff --git a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj similarity index 96% rename from ExceptionReporter.WPF/ExceptionReporter.WPF.csproj rename to src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index 9297578e..fc463a02 100644 --- a/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -91,6 +91,11 @@ + + + + + \ No newline at end of file diff --git a/src/ExceptionReporter.WPF/Images/clipboard.png b/src/ExceptionReporter.WPF/Images/clipboard.png new file mode 100644 index 0000000000000000000000000000000000000000..eb14d21ec3c23208d1f97f1cfa69e297034cbe8f GIT binary patch literal 8731 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 bgyvEhlPynvTMGWj0WqxXEX#iPKKXwDuXE_< literal 0 HcmV?d00001 diff --git a/src/ExceptionReporter.WPF/Images/envelope.png b/src/ExceptionReporter.WPF/Images/envelope.png new file mode 100644 index 0000000000000000000000000000000000000000..3eb4e731a8692681bac506ac867563369d113266 GIT binary patch literal 16186 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 AvH$=8 literal 0 HcmV?d00001 diff --git a/src/ExceptionReporter.WPF/Images/magnify.png b/src/ExceptionReporter.WPF/Images/magnify.png new file mode 100644 index 0000000000000000000000000000000000000000..e9a225ecda43801d33bfa7ea056799e0a5ea9451 GIT binary patch literal 25107 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

kB-TyGQ}p*eEWGDAQ0hZx)Ba$K3)KrZ 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 M=&WItKJMoK0gvQio&W#< literal 0 HcmV?d00001 diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml similarity index 54% rename from ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml rename to src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index df549b57..784a23f0 100644 --- a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -44,17 +44,51 @@ + + + + + - - - + diff --git a/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs similarity index 100% rename from ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs rename to src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs diff --git a/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs b/src/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs similarity index 100% rename from ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs rename to src/ExceptionReporter.WPF/MvvM/ViewModel/MainViewModel.cs diff --git a/ExceptionReporter.WPF/Properties/AssemblyInfo.cs b/src/ExceptionReporter.WPF/Properties/AssemblyInfo.cs similarity index 100% rename from ExceptionReporter.WPF/Properties/AssemblyInfo.cs rename to src/ExceptionReporter.WPF/Properties/AssemblyInfo.cs diff --git a/ExceptionReporter.WPF/Properties/Settings.Designer.cs b/src/ExceptionReporter.WPF/Properties/Settings.Designer.cs similarity index 100% rename from ExceptionReporter.WPF/Properties/Settings.Designer.cs rename to src/ExceptionReporter.WPF/Properties/Settings.Designer.cs diff --git a/ExceptionReporter.WPF/Properties/Settings.settings b/src/ExceptionReporter.WPF/Properties/Settings.settings similarity index 100% rename from ExceptionReporter.WPF/Properties/Settings.settings rename to src/ExceptionReporter.WPF/Properties/Settings.settings diff --git a/ExceptionReporter.WPF/packages.config b/src/ExceptionReporter.WPF/packages.config similarity index 100% rename from ExceptionReporter.WPF/packages.config rename to src/ExceptionReporter.WPF/packages.config diff --git a/src/ExceptionReporting/ExceptionReporter.WinForms.csproj b/src/ExceptionReporter.WinForms/ExceptionReporter.WinForms.csproj similarity index 96% rename from src/ExceptionReporting/ExceptionReporter.WinForms.csproj rename to src/ExceptionReporter.WinForms/ExceptionReporter.WinForms.csproj index 1db0eb64..9972e308 100644 --- a/src/ExceptionReporting/ExceptionReporter.WinForms.csproj +++ b/src/ExceptionReporter.WinForms/ExceptionReporter.WinForms.csproj @@ -46,7 +46,7 @@ ExceptionReporter is a .NET component that gathers detailed information on an Exception and the application/system running it. It allows the user to copy, save or email a report to the developer - + True diff --git a/src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs b/src/ExceptionReporter.WinForms/MVP/Presenters/ExceptionReportPresenter.cs similarity index 100% rename from src/ExceptionReporting/MVP/Presenters/ExceptionReportPresenter.cs rename to src/ExceptionReporter.WinForms/MVP/Presenters/ExceptionReportPresenter.cs diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.Designer.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.Designer.cs similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionDetailControl.Designer.cs rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.Designer.cs diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.cs similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionDetailControl.cs rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.cs diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.en.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.en.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionDetailControl.en.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.en.resx diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionDetailControl.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.resx diff --git a/src/ExceptionReporting/MVP/Views/ExceptionDetailControl.ru.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.ru.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionDetailControl.ru.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionDetailControl.ru.resx diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.Designer.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.Designer.cs similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionReportView.Designer.cs rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.Designer.cs diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionReportView.cs rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.en.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.en.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionReportView.en.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.en.resx diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionReportView.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.resx diff --git a/src/ExceptionReporting/MVP/Views/ExceptionReportView.ru.resx b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.ru.resx similarity index 100% rename from src/ExceptionReporting/MVP/Views/ExceptionReportView.ru.resx rename to src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.ru.resx diff --git a/src/ExceptionReporting/Properties/Resources.Designer.cs b/src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs similarity index 100% rename from src/ExceptionReporting/Properties/Resources.Designer.cs rename to src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs diff --git a/src/ExceptionReporting/Properties/Resources.en.resx b/src/ExceptionReporter.WinForms/Properties/Resources.en.resx similarity index 100% rename from src/ExceptionReporting/Properties/Resources.en.resx rename to src/ExceptionReporter.WinForms/Properties/Resources.en.resx diff --git a/src/ExceptionReporting/Properties/Resources.resx b/src/ExceptionReporter.WinForms/Properties/Resources.resx similarity index 100% rename from src/ExceptionReporting/Properties/Resources.resx rename to src/ExceptionReporter.WinForms/Properties/Resources.resx diff --git a/src/ExceptionReporting/Properties/Resources.ru.resx b/src/ExceptionReporter.WinForms/Properties/Resources.ru.resx similarity index 100% rename from src/ExceptionReporting/Properties/Resources.ru.resx rename to src/ExceptionReporter.WinForms/Properties/Resources.ru.resx diff --git a/src/ExceptionReporting/WinForms/ScreenshotTaker.cs b/src/ExceptionReporter.WinForms/WinForms/ScreenshotTaker.cs similarity index 100% rename from src/ExceptionReporting/WinForms/ScreenshotTaker.cs rename to src/ExceptionReporter.WinForms/WinForms/ScreenshotTaker.cs diff --git a/src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs b/src/ExceptionReporter.WinForms/WinForms/SysInfoResultMapperWinForm.cs similarity index 100% rename from src/ExceptionReporting/WinForms/SysInfoResultMapperWinForm.cs rename to src/ExceptionReporter.WinForms/WinForms/SysInfoResultMapperWinForm.cs diff --git a/src/ExceptionReporting/WinForms/ViewMaker.cs b/src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs similarity index 100% rename from src/ExceptionReporting/WinForms/ViewMaker.cs rename to src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs diff --git a/src/ExceptionReporting/WinForms/WinformsClipboard.cs b/src/ExceptionReporter.WinForms/WinForms/WinformsClipboard.cs similarity index 100% rename from src/ExceptionReporting/WinForms/WinformsClipboard.cs rename to src/ExceptionReporter.WinForms/WinForms/WinformsClipboard.cs diff --git a/src/ExceptionReporting/WinFormsExceptionReporter.cs b/src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs similarity index 100% rename from src/ExceptionReporting/WinFormsExceptionReporter.cs rename to src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs diff --git a/src/Tests/Tests.ExceptionReporter.NET.csproj b/src/Tests/Tests.ExceptionReporter.NET.csproj index 751848bc..09edb584 100644 --- a/src/Tests/Tests.ExceptionReporter.NET.csproj +++ b/src/Tests/Tests.ExceptionReporter.NET.csproj @@ -15,7 +15,7 @@ - + From 212001f8d83193b8bab48d0ba4b08f2918a6e09a Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Wed, 4 Aug 2021 20:34:06 +1000 Subject: [PATCH 08/22] getting sizing/styling right --- .../MvvM/View/WpfExceptionReporter.xaml | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index 784a23f0..bf513099 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -11,6 +11,12 @@ d:DesignHeight="250" d:DesignWidth="400"> + @@ -20,7 +26,7 @@ - + @@ -38,16 +44,19 @@ - - - + + + + + Margin="0,20,0,0" + Fill="Gray" Opacity="0.2"> + - - - From 1c3288c8f8d40636ffa56588f1efceef707ee804 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Thu, 5 Aug 2021 00:16:44 +1000 Subject: [PATCH 09/22] tidy up margins and icons --- .../ExceptionReporter.WPF.csproj | 8 ++- src/ExceptionReporter.WPF/Images/envelope.png | Bin 16186 -> 0 bytes src/ExceptionReporter.WPF/Images/magnify.png | Bin 25107 -> 0 bytes .../Images/magnifying-glass.png | Bin 0 -> 16104 bytes src/ExceptionReporter.WPF/Images/message.png | Bin 0 -> 13773 bytes .../MvvM/View/WpfExceptionReporter.xaml | 50 +++++++++++------- 6 files changed, 38 insertions(+), 20 deletions(-) delete mode 100644 src/ExceptionReporter.WPF/Images/envelope.png delete mode 100644 src/ExceptionReporter.WPF/Images/magnify.png create mode 100644 src/ExceptionReporter.WPF/Images/magnifying-glass.png create mode 100644 src/ExceptionReporter.WPF/Images/message.png diff --git a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index fc463a02..33c11437 100644 --- a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -93,8 +93,12 @@ - - + + + + + + diff --git a/src/ExceptionReporter.WPF/Images/envelope.png b/src/ExceptionReporter.WPF/Images/envelope.png deleted file mode 100644 index 3eb4e731a8692681bac506ac867563369d113266..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16186 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 AvH$=8 diff --git a/src/ExceptionReporter.WPF/Images/magnify.png b/src/ExceptionReporter.WPF/Images/magnify.png deleted file mode 100644 index e9a225ecda43801d33bfa7ea056799e0a5ea9451..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25107 zcmY(qcRbba|3Cgb$KETE?U+SIgzSzZluzPu6Ut!b^SnzKeZ(U1Yu>G%#ZwOpGCkXuTil4THpNW^FU*MysPk_L{ zKq(hbH(&cl-cO{wo;u}hsB!^-0HBAsZ5s4uZ94E%o^~33dsYv=IqXwJcbh=~Nj*#s zc|>7dXdayg6BiI@4oDF-xa_T6bT0)b@Q&H_pMdZ+!Jn9z$Cx2Fl*Wma`LU;8WMO9h zP1aKQ?CyEkhFCS7)8gOLzBhq+S#s}iQA1J)2R>Adr$)Tt(&iFm5xTgxJ+e!p+_G)T zr%@xeuaXX=WGI7fl5RO#p{sD4A?F){Q9~T8G@8yLuv+G7XmuE|?sV`e{%lnFmx>qJ zdyG@)nJSfP8P4nHsuguXDgw&PrGp^1VBsV$XAGmYh?DP;Hm-3K`DA#PI**b_Nlz9- zHt4KcE=aDG0z}~u^FsPr|5}M>!u=#syNOBsY}PAguua*D8#0s~?raG*dWUduLG7N^ zU0Hq@p6NdbZGvcF1aT*i7l={JRtRC>a~f8X*8Rt8Jv3^Rv7v)y-T`Q~LE2SJYmNK3Nxl!fpUZsxHH`e3`AD$#AVis!A~t zGPK!fT-qrcJd+^>@RMP&OqE~WWR$f0s8Z1IiT*6T-j49!L@tfso{ccTD{B6C^11vr z6K*PZh%YA9j6y2$Zj@ksk}jaEsov7WR?SpRG1LK$os&&I1+}KOX4j$Ba&FWGCNi;o z3}Ng_To#Q_1L01=d`ef28gNNf(^<@4Vzr?|F$f2Bf&f7mRr+I^CU;$gU`nt?hL;35 z!Kp#14&6aGJR+>(6(hAJ0>z>>Y$*l+qB*kbLMDQ&m_`9uJR~+%ltgjy-z&jvM|K21 zB(F)UoS1?D`TbX*4l@$gX?{%VWYkz_Y2LP513?swk+zb{?QcUCtz__R7W^ zvPFRoh@si&(zQd8s3cIu=~z;b82d=IN*egxtV`Gh_xkFsIzc2kPEDncUC$t3==7oVvG}wfd!J6=1hJpl&V=pZK4!bKc2b^CH{0KdQJIP%4M*euft<9F6Rc z9CbNoFZ_eQjZ>}<(1AO1fQyX6N;1A7U%R);IA$cXz)f8D8EC!oG#6`-RSU0n9cAoS zrjP=X9*m;RH||ki2i5ooqLAMk@P;mz2bBfC@nf6vLhc`fS|}$5>wQ&;nc=pmcpB*V zeYJ2zW~p?AszHSfUiO0gEsVvITZzh|D!}fs!Nbb`v!ogK=@?G)yfbL>Ej>&Jal{T0riHFrA)e^ zjzqByPU-?L7(`qjaR4=hq?b=;*tW#VFWZ&ks(x+gZ;8R;Unb>k7~pOV(b`fb8IQ)h z1qw%*vCwD=!glnApOQKoPKW6Rp&Vo!Wh*A&f>&5l(jwb-25Hk;N4NuD+0vc0U5Kki z7kCrb9aiYuH%q?wVJi1Z@N?71br``jk?GFAI|%Y|Z2h&ZC#ZrJwd{gJJ#!|~edKH@ zXhqrASOFbaEsOWnYWMZ_KD-=04)g*Z4<2e9{Rre(qX^@+r~ySbAB)z zX3SXl*5&5hMMGk8YI}dhJKWOudH#@l$gZ-LVEnbh!J)adR(Z8vXj6Q5O)!N})Q~|r zz}ZU?E=Adho6cAcx}?O{EIM$Xitc0j_Y7SQvkK5{jQGk`n_pt4ee^;XppWYo#d}3Q zaXoy(wLuo~4yQP_q3di1tG&LZQAqb9+flx{6*uz$JPi5UpP(`Vuye$GE51VBYo~)@ z9FA1P_Gko|jB+FW$xw8|PE~s85Ks1$%|&E9v$9n=&?m}b$=VzxPq^7*Q0R4b_;W+| zpEayj&_x@SGZDW0=Q7F&8U7L6>jx25%x?i$PHMohG_qAX3;GKR?og;f#UvHmr#DeR zWEoETK?m#xo~~w{hySwEYI$|Ae&#gTk@tJHgHrW9ZZnwJZXgD8OF5uk)Af~V4TN$Fx@FM;5-jc`gx9(W+PY z_pXqxqG-T*!u?Tm*MM?)mSb{ovF6z+)M3CG=g|ZA7Ywi18;%#nFX^%oOI8j(c$_D`rk|pnD!_S}ZW!e+ob&0V7}EEd zd{h~P<|lK@YPG%~M=9^r6yImHTI#cCUVlZ=L}+^f?w9$RRz9}d8jpVE z`C>B0(GESOHzOue$3cd^KT4B!I^qVaRr40Dw*KzDrl?wiwP!k4O4DuMh0SVEgXjc)f*XoQgd41#+32 zamJ^DnepUrxmj+#tfwg*GbBywIh}B$r|u!lgbhwYS#pl7Mn?*fk@3j=tcl#LtT5F* zYt+bHnU@w1Y-qitCD^o4E%y{%Ut(DE4fkFye zX*ycdpdzRCk#?!3(Eek?LE4!n5^Yhs&fMo027O8Ox(@SP!vB$cbq;REvh+ObM^|0@ zosbT@)lpq>d*~Jwfs`FKWr|RslzMO5kM+f9<-Dnmm67Ak1?GixI8xh3$GqjLGjPOK zpBq3gD*Prv!pyzPlFs7MUjqB-1t>eCYD0C{lb89U(Qe&}3 zI4XT4MFKd^`D%clV9zFrx%7}WXg!R~D|_3;md{<;uGK^@UeUXj8mc$4k(|EE{@!d4>L3X?cBJWO%Vb7C%|ovLSb}d_1Vx!uD>}iO7f6sK`H#{H{xC%XmsW z&;B6$%WTOUs`E-gIz3E8hKrLY6besm@Q1z(JY_0ci|J6rtRwf6o_QFif=KPn9o&Dj z1D&Y~kJSEKcOsXmJ$U68u~17Z!)(zoIoK8X5p<BJ*md)}84Mlce$cbK8(a(`WlIWLrmo6BOHhQiuSfb(_(=KS~4H)_!LW zwliDECNE+(D*94^k?HD?8MwS*aCzkvQ-)b}8*I9*K~>j>#!Po!k$MVG&JFg|y@i%1 ziHSZ_rCB>Fn;v>S_(nXBf2h2T6QE-rB2q2ng1#FkeaQ=wgIf`zn4tZmWu*XNPD#_# z=}Z?NvTj(3`1pF8y>NQQU{_&_&bVhT14Oucd00v9Ybl`urG7pms+v}!=t{q@(PfnF zaNOl1)5u16=G}XuK=4)zl|_N3uXHNynX1{_ic)MhW1$FXID@ml&w?OHpht#R1UP*u zXG=+bX_n4dl$Bq1Zo1zx%n;wrRru`oz01xUmZ-0~@3dU5X8`kG#IJwa z2Jbb9k?w!6L{Okn&`PCiBB zKC>KM1-Goo1kT8h3?qw0U$!4}*c=QN-K_$~uK(W9Ka2P4Uk%17R|Yse<7dg@P{R0m z?CD4Zmb6moRgu3)pBShj^DOSm!^|P~(X{n!(4ohm%O{tVkaRcNoH^4isxa)!K}?hWrIOe^q~ zo*Ma)Y=3j^mhy1T)OHbql6a5=@|IUXc=C-@((h<7Qgo!oNJ0;(36H~_ z>}H;68R3-mkZ8v8yC>y88_Bko&gj`wx?<|+<5N9l!kW7B zr%5LagkwGp>H5>SIO~EP>S4F{$JYX$T-pjo@>;&D`E+|H`N&S>jMYU0-#f4##W*@n zF5onwNcK=kabKp|vXpxT;b1dNsIj=1$%?>@JAr>!mw$mRzjN)$r=&;Y=3s6|)!?op zi8jHxq(2R|BRkyriB}@Pp8jeax*B1By!d@mSMOcPL*1?vdksyQU-RT|zs2N;MJAf= zvo8ez%qbO^veHA3Wf#JIWLv56X`&De-ePtfgxY}jCy8CRA%U?51c*)dPr)=7w{diL z+BN?_yo3(Z{YBQqxNcVbG`=f02N!Va?Ch1O4?NvYe7LO^cnT|}3{3d~gVj=%mU|`A zS%?B+P_gu>o71$2dFo-7z6sHkSI;_Lnze73jnaU3^uS}&-lkonxWBj5+KjI8hq=Uc zKK)Z!fFDlk*N3W`&q=)+n&HX-u-$(Pi-w=@vmn}Rers~ravqMr zpj8@Kl=a`UVm|SNvQ?+q%dzP>xlh+EpPjy;=2@Q}^RuSq`GE5>ckQUziRlQf318Y= z&M!=S{|kb4jZVyg-OyNW>{bH><3O0SLcQ!QOK$?mcyc~o887~}$)>C|vI2y0&-U;W z#^I?XVE7d}v4>*RqI-xZyZkjL95(|5bQY!F0wZE*Fe*4Xr6pB*maumJrv(rf) zQH=j#L3p-EMubSNj`z{wOOX4>E(K6eQa|kWlOA6Lv=VS=Z3GdsscG}|YvKC@4*Bht z#j`j0bZf|h<5c86=O&n@dN5p?lzdBJS9L2cXyEIb>kkRc=9~%$R0FQdAM+a?_n>*U z*pbsJl+m`k>K!&;Ckl6uq_N$lFyp$RpRpfSRB$bd%g8&+Fg=|mrx7HdeSk>fE!*@W zHM1)ClTmX3F`rtP@Ow9CN){JVYafQ%dC(DmwRMuj4|?(r4)?l+xNhgLWY3$Qg$dV; z8@i}m1B+YFrtE0K-l6Jf*N}g)Z?QZEEq5n-PYc=mgEqcOx_zO=-#RiRDnd$>I;liC zj&J4HrjnxZEwa>ouVUQ--(rY(Df~I?X$E#JQ^MUWL!)l>mHO8rY8R8Yhj;9C?US57 zSKQLIccQK@^z*4NTwKQL1$+uhq4Ob-HH(@=_+Rogre$>pEl5XOn< zU(>b6kMj#&m#u5CjN2jaMfkdcL56oLcH;blGv~7I8oyg0c#H>-i0I8*CmWqFuSK@l z3cNN_oQ|2@+`l1nAK9h+oyntou?dq;P(0Sc<*%z9OKV*lFm~NRbBxQ1qS??;KHPNN z3o|OuODU7u4(AiOJ^9PL;^xvQS;FA)m4MW)x0|;VYJ^=R843n*<)CR!;K`0e1UA^~ zc4#|u@d8x}Awj(3hRDsUKW!)7g02#VD=CvC{EIgB=KtPN1mZ8bK2<7}Y@Ss72W2t>mINhA z!8({zT+NY7gGWw!`Nyo3kdDE@`gqmL>)Kp7s(WMuE??S{hOAt}P>jHs?+Z1W@&4T} z^eoFv)_1rH?*={FtGp3#a;n6u^vX}$tArZ}V+c~^cd3A($EZ@(PesBmH%n?vO6_FU zbGsz$RP(vGGZg%K0mACy4mO^gqjucPGAI9VMTCk{(|-%MQ9?*w-D0X4q}-PTgkg$ArP2QH~E@JzFnS zsnhU&k&F$C+pDaP>HzFs^oITD$>?-9z

kB-TyGQ}p*eEWGDAQ0hZx)Ba$K3)KrZ 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 M=&WItKJMoK0gvQio&W#< diff --git a/src/ExceptionReporter.WPF/Images/magnifying-glass.png b/src/ExceptionReporter.WPF/Images/magnifying-glass.png new file mode 100644 index 0000000000000000000000000000000000000000..85714ce787659b940eaa4d032aebed41f3f4ee4b GIT binary patch literal 16104 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�wVw=qHCA%6R7JBLk7ew%Dn=qoxBt*Y@{& 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 bd?kJ2RzlB3hkalw9dfjF!9G5OyY{~T82)QO literal 0 HcmV?d00001 diff --git a/src/ExceptionReporter.WPF/Images/message.png b/src/ExceptionReporter.WPF/Images/message.png new file mode 100644 index 0000000000000000000000000000000000000000..b46d62569efd1680cdc945ed19740c4d05ea90bc GIT binary patch literal 13773 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 + + @@ -26,9 +31,9 @@ - + - + @@ -36,31 +41,37 @@ - + - - - + + - + Margin="0,0,0,0" + Opacity="0.25"> + + + + + + + @@ -68,24 +79,27 @@ - - - - - + + diff --git a/src/Demos/WPF/DummyWindow.xaml.cs b/src/Demos/WPF/MainWindow.xaml.cs similarity index 84% rename from src/Demos/WPF/DummyWindow.xaml.cs rename to src/Demos/WPF/MainWindow.xaml.cs index 7e64fd34..c8d57946 100644 --- a/src/Demos/WPF/DummyWindow.xaml.cs +++ b/src/Demos/WPF/MainWindow.xaml.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Windows; using ExceptionReporting; using ExceptionReporting.WPF.MvvM.View; @@ -7,11 +6,11 @@ namespace Demo.WPF { ///

- /// Interaction logic for DummyWindow.xaml + /// Interaction logic for MainWindow.xaml /// - public partial class DummyWindow : Window + public partial class MainWindow : Window { - public DummyWindow() + public MainWindow() { InitializeComponent(); } diff --git a/src/Demos/WPF/Properties/AssemblyInfo.cs b/src/Demos/WPF/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..33e7f36f --- /dev/null +++ b/src/Demos/WPF/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Demo.WPF2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Demo.WPF2")] +[assembly: AssemblyCopyright("Copyright © 2021")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/Demos/WPF/Properties/Resources.Designer.cs b/src/Demos/WPF/Properties/Resources.Designer.cs new file mode 100644 index 00000000..2489527d --- /dev/null +++ b/src/Demos/WPF/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Demo.WPF.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo.WPF.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/src/Demos/WPF/Properties/Resources.resx b/src/Demos/WPF/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/src/Demos/WPF/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Demos/WPF/Properties/Settings.Designer.cs b/src/Demos/WPF/Properties/Settings.Designer.cs new file mode 100644 index 00000000..6aadf775 --- /dev/null +++ b/src/Demos/WPF/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Demo.WPF.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/src/Demos/WPF/Properties/Settings.settings b/src/Demos/WPF/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/src/Demos/WPF/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems b/src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems index b2211fd4..1fa0d267 100644 --- a/src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems +++ b/src/ExceptionReporter.Shared/ExceptionReporter.Shared.projitems @@ -49,9 +49,17 @@
- - - - + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + \ No newline at end of file diff --git a/src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs b/src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs index 4e1b7cd0..7e7a994f 100644 --- a/src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs +++ b/src/ExceptionReporter.Shared/Templates/TemplateRenderer.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Reflection; using System.Text; using HandlebarsDotNet; @@ -45,12 +46,12 @@ public string RenderCustom(string template) private string GetTemplate(TemplateFormat format) { - var resource = string.Format("{0}.{1}.{2}", this.GetType().Namespace, _name, format.ToString().ToLower()); + var resource = $"{this.GetType().Namespace}.{_name}.{format.ToString().ToLower()}"; var assembly = Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream(resource)) { - using (var reader = new StreamReader(stream, Encoding.UTF8)) + using (var reader = new StreamReader(stream ?? throw new InvalidOperationException($"resource not found: {resource}"), Encoding.UTF8)) { var template = reader.ReadToEnd(); return template; diff --git a/src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs b/src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs index 41a2c334..44b721d4 100644 --- a/src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs +++ b/src/ExceptionReporter.WPF/Converters/IconToImageSourceConverter.cs @@ -8,6 +8,7 @@ using System.Windows.Media; using System.Windows.Media.Imaging; +// ReSharper disable once CheckNamespace namespace ExceptionReporting.WPF.Converters { public class IconToImageSourceConverter : IValueConverter diff --git a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index 33c11437..35024b0a 100644 --- a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -6,7 +6,7 @@ AnyCPU {EF418EF6-D1DB-4CB0-9E77-AFC5D7C64AED} library - ExceptionReporting.WPF + ExceptionReporting ExceptionReporter.WPF v4.8 512 @@ -32,15 +32,18 @@ prompt 4 + + false + - ..\packages\DotNetZip.1.15.0\lib\net40\DotNetZip.dll + ..\..\packages\DotNetZip.1.15.0\lib\net40\DotNetZip.dll - ..\packages\Handlebars.Net.1.9.0\lib\net40\Handlebars.dll + ..\..\packages\Handlebars.Net.1.9.0\lib\net40\Handlebars.dll - ..\packages\Simple-MAPI.NET.1.1.0\lib\net20\SimpleMapi.dll + ..\..\packages\Simple-MAPI.NET.1.1.0\lib\net20\SimpleMapi.dll diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index 421f7cd7..be492946 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -24,6 +24,10 @@ + + + + - @@ -84,29 +74,37 @@ - - - diff --git a/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs index c22638bb..f36d519b 100644 --- a/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs +++ b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs @@ -39,7 +39,8 @@ public ExceptionReportView(ExceptionReportInfo reportInfo) private void PopulateReportInfo(ExceptionReportInfo reportInfo) { - lblExplanation.Text = reportInfo.UserExplanationLabel; + lblExplanation.Text = reportInfo.UserExplanationLabel ?? + Resources.Please_enter_a_brief_explanation_of_events_leading_up_to_this_exception; ShowFullDetail = reportInfo.ShowFullDetail; ToggleShowFullDetail(); btnDetailToggle.Visible = reportInfo.ShowLessDetailButton; From 33d5645b385b8b2a0c64cb79f7374d8042e9310e Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sun, 8 Aug 2021 00:02:57 +1000 Subject: [PATCH 17/22] fix stray references to localisation resources that needed to be moved into WinForms explicitly --- 4.1 changes.txt | 3 ++ src/Demos/WinForms/DemoApp.cs | 1 - src/Demos/WinForms/YourCustomViewMaker.cs | 4 +- .../Core/IViewMaker.cs | 7 ++- .../ExceptionReportInfo.cs | 10 ++--- .../MVP/Views/ExceptionReportView.cs | 2 +- .../Properties/Resources.Designer.cs | 2 +- .../Properties/Resources.en.resx | 32 ++++++------- .../Properties/Resources.resx | 2 +- .../WinForms/DefaultWinFormsViewmaker.cs | 33 ++++++++++++++ .../WinForms/ViewMaker.cs | 45 ------------------- .../WinFormsExceptionReporter.cs | 8 ++-- 12 files changed, 67 insertions(+), 82 deletions(-) create mode 100644 4.1 changes.txt create mode 100644 src/ExceptionReporter.WinForms/WinForms/DefaultWinFormsViewmaker.cs delete mode 100644 src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs diff --git a/4.1 changes.txt b/4.1 changes.txt new file mode 100644 index 00000000..d0a4d555 --- /dev/null +++ b/4.1 changes.txt @@ -0,0 +1,3 @@ +IViewMaker.ShowError method dropped the 2nd argument `description` - this is now taken from localized resources +ExceptionReportInfo property `BackgroundColor` is now a hex color code string, not a System.Drawing.Color object +Saving zip file set the file extension to use the template type (ie markdown/txt/html) \ No newline at end of file diff --git a/src/Demos/WinForms/DemoApp.cs b/src/Demos/WinForms/DemoApp.cs index d1181a09..61b5369d 100644 --- a/src/Demos/WinForms/DemoApp.cs +++ b/src/Demos/WinForms/DemoApp.cs @@ -118,7 +118,6 @@ static void ThrowAndShowExceptionReporter(bool detailView = false) // er.Config.ShowEmailButton = false; // just for testing that removing email button works er.Config.ReportTemplateFormat = TemplateFormat.Markdown; - er.ViewMaker = new ViewMaker(er.Config); er.Show(exception); } } diff --git a/src/Demos/WinForms/YourCustomViewMaker.cs b/src/Demos/WinForms/YourCustomViewMaker.cs index b223a8fe..4d9dfdd1 100644 --- a/src/Demos/WinForms/YourCustomViewMaker.cs +++ b/src/Demos/WinForms/YourCustomViewMaker.cs @@ -13,9 +13,9 @@ public IExceptionReportView Create() return new YourCustomReporterView(); } - public void ShowError(string message, string description) + public void ShowError(string message) { - MessageBox.Show(message, description); + MessageBox.Show(message); } } } \ No newline at end of file diff --git a/src/ExceptionReporter.Shared/Core/IViewMaker.cs b/src/ExceptionReporter.Shared/Core/IViewMaker.cs index 4a1b2bb6..0184e88b 100644 --- a/src/ExceptionReporter.Shared/Core/IViewMaker.cs +++ b/src/ExceptionReporter.Shared/Core/IViewMaker.cs @@ -1,7 +1,7 @@ using ExceptionReporting.Core; /// -/// contract to show view-related things +/// An interface/contract to replace the default view (currently only applicable to WinForms) /// public interface IViewMaker { @@ -12,9 +12,8 @@ public interface IViewMaker IExceptionReportView Create(); /// - /// show error + /// show an error /// /// - /// - void ShowError(string message, string description); + void ShowError(string message); } \ No newline at end of file diff --git a/src/ExceptionReporter.Shared/ExceptionReportInfo.cs b/src/ExceptionReporter.Shared/ExceptionReportInfo.cs index 97c512db..5348622c 100644 --- a/src/ExceptionReporter.Shared/ExceptionReportInfo.cs +++ b/src/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -61,7 +61,7 @@ public void SetExceptions(IEnumerable exceptions) /// /// Override the Exception.Message property /// ie a custom message to show in place of the Exception Message - /// NB this can also be set in the 1st parameter of + /// NB this can also be set in the 1st parameter of /// public string CustomMessage { get; set; } @@ -205,11 +205,9 @@ public bool ShowEmailButton } /// - /// The title of the main WpfExceptionReporter dialog + /// The title of the main ExceptionReporter dialog /// - // public string TitleText { get; set; } = Resources.ErrorReport; - //TODO figure out shared resources - public string TitleText { get; set; } = "ErrorReport"; + public string TitleText { get; set; } /// /// Background color of the dialog @@ -260,7 +258,7 @@ public string AttachmentFilename /// public string UserExplanationLabel { get; set; } - [Obsolete("Not actually used anywhere, not sure since when, but remove all uses")] + [Obsolete("Not actually used anywhere")] public string ContactMessageTop { get; set; } /// diff --git a/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs index f36d519b..d8c5086d 100644 --- a/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs +++ b/src/ExceptionReporter.WinForms/MVP/Views/ExceptionReportView.cs @@ -85,7 +85,7 @@ private void PopulateReportInfo(ExceptionReportInfo reportInfo) RemoveEmailButton(); } - Text = reportInfo.TitleText; + Text = reportInfo.TitleText ?? Resources.ErrorReport; txtUserExplanation.Font = new Font(txtUserExplanation.Font.FontFamily, reportInfo.UserExplanationFontSize); lblContactCompany.Text = string.Format( diff --git a/src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs b/src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs index 612909aa..5f962c88 100644 --- a/src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs +++ b/src/ExceptionReporter.WinForms/Properties/Resources.Designer.cs @@ -70,7 +70,7 @@ internal static string Copied_to_clipboard { } /// - /// Looks up a localized string similar to ErrorReport. + /// Looks up a localized string similar to Error Report. /// internal static string ErrorReport { get { diff --git a/src/ExceptionReporter.WinForms/Properties/Resources.en.resx b/src/ExceptionReporter.WinForms/Properties/Resources.en.resx index c930a5a4..a1fbbe92 100644 --- a/src/ExceptionReporter.WinForms/Properties/Resources.en.resx +++ b/src/ExceptionReporter.WinForms/Properties/Resources.en.resx @@ -121,51 +121,51 @@ Test Loc - Please enter a brief explanation of events leading up to this exception + Please enter a brief explanation of events leading up to this exception - The following details can be used to obtain support for this application + The following details can be used to obtain support for this application - Send + Send - to {0} + to {0} - Less Detail + Less Detail - More Detail + More Detail - Report sent + Report sent - Failed to send report + Failed to send report - Error sending report + Error sending report - Failed trying to report an Error + Failed trying to report an Error - Copied to clipboard + Copied to clipboard - Unable to save file + Unable to save file - Unable to setup + Unable to setup - If this problem persists, please contact {0} support. + If this problem persists, please contact {0} support. - ErrorReport + Error Report - Clipboard copy failed + Clipboard copy failed \ No newline at end of file diff --git a/src/ExceptionReporter.WinForms/Properties/Resources.resx b/src/ExceptionReporter.WinForms/Properties/Resources.resx index e908e3c6..e00b36b8 100644 --- a/src/ExceptionReporter.WinForms/Properties/Resources.resx +++ b/src/ExceptionReporter.WinForms/Properties/Resources.resx @@ -166,6 +166,6 @@ Unable to setup - ErrorReport + Error Report \ No newline at end of file diff --git a/src/ExceptionReporter.WinForms/WinForms/DefaultWinFormsViewmaker.cs b/src/ExceptionReporter.WinForms/WinForms/DefaultWinFormsViewmaker.cs new file mode 100644 index 00000000..dc1cb681 --- /dev/null +++ b/src/ExceptionReporter.WinForms/WinForms/DefaultWinFormsViewmaker.cs @@ -0,0 +1,33 @@ +using System.Windows.Forms; +using ExceptionReporting.Core; +using ExceptionReporting.MVP.Views; +using ExceptionReporting.Properties; + +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedAutoPropertyAccessor.Global + +namespace ExceptionReporting.WinForms +{ + /// + /// Default/WinForms implementation of IViewmaker + /// + internal class DefaultWinFormsViewmaker : IViewMaker + { + private readonly ExceptionReportInfo _reportInfo; + + public DefaultWinFormsViewmaker(ExceptionReportInfo reportInfo) + { + _reportInfo = reportInfo; + } + + public IExceptionReportView Create() + { + return new ExceptionReportView(_reportInfo); + } + + public void ShowError(string message) + { + MessageBox.Show(message, Resources.Failed_trying_to_report_an_Error, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } +} \ No newline at end of file diff --git a/src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs b/src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs deleted file mode 100644 index 58f9e1b2..00000000 --- a/src/ExceptionReporter.WinForms/WinForms/ViewMaker.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Windows.Forms; -using ExceptionReporting.Core; -using ExceptionReporting.MVP.Views; - -// ReSharper disable MemberCanBePrivate.Global -// ReSharper disable UnusedAutoPropertyAccessor.Global - -namespace ExceptionReporting.WinForms -{ - /// - /// WinForms implementation of ViewMaker - /// - public class ViewMaker : IViewMaker - { - private readonly ExceptionReportInfo _reportInfo; - - /// - /// - /// - /// - public ViewMaker(ExceptionReportInfo reportInfo) - { - _reportInfo = reportInfo; - } - - /// - /// - /// - /// - public IExceptionReportView Create() - { - return new ExceptionReportView(_reportInfo); - } - - /// - /// - /// - /// - /// - public void ShowError(string message, string description) - { - MessageBox.Show(message, description, MessageBoxButtons.OK, MessageBoxIcon.Error); - } - } -} \ No newline at end of file diff --git a/src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs b/src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs index fbcb2d43..5b41d3fe 100644 --- a/src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs +++ b/src/ExceptionReporter.WinForms/WinFormsExceptionReporter.cs @@ -21,7 +21,7 @@ public class ExceptionReporter : ExceptionReporterBase /// public ExceptionReporter() { - ViewMaker = new ViewMaker(_info); + ViewMaker = new DefaultWinFormsViewmaker(_info); } /// @@ -42,7 +42,7 @@ public bool Show(params Exception[] exceptions) if (exceptions == null || exceptions.Length == 0 || exceptions.Length >= 1 && exceptions[0] == null) return false; if (ViewMaker == null) { - Debug.WriteLine("ViewMaker must be initialized. Add `er.ViewMaker = new ViewMaker(er.Config);` where 'er'` is ExceptionReporter object"); + Debug.WriteLine("DefaultWinFormsViewmaker must be initialized (not null). Add `er.DefaultWinFormsViewmaker = new DefaultWinFormsViewmaker(er.Config);` where 'er' is the ExceptionReporter object"); return false; } @@ -56,9 +56,7 @@ public bool Show(params Exception[] exceptions) } catch (Exception ex) { - //TODO figure out shared resources between WinForms and WPF or move messages out of common code - // ViewMaker.ShowError(ex.Message, Resources.Failed_trying_to_report_an_Error); - ViewMaker.ShowError(ex.Message, "Failed_trying_to_report_an_Error"); + ViewMaker.ShowError(ex.Message); return false; } } From a7a8664bdf554fef967928facdbb336015e6863d Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Sun, 8 Aug 2021 23:41:17 +1000 Subject: [PATCH 18/22] tidy --- .../MvvM/View/WpfExceptionReporter.xaml | 23 ++++++++++++------- .../ViewModel/ExceptionReporterCommands.cs | 2 ++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index b0ed6753..b8746657 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -72,39 +72,46 @@ + Orientation="Horizontal" + HorizontalAlignment="Stretch"> + + - diff --git a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs b/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs index c6e45174..582c3b5d 100644 --- a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs +++ b/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs @@ -6,10 +6,12 @@ namespace ExceptionReporting.WPF.MvvM.ViewModel public class ExceptionReporterCommands { public static readonly RoutedUICommand EmailCommand; + public static readonly RoutedUICommand ShowDetailsCommand; static ExceptionReporterCommands() { EmailCommand = new RoutedUICommand("Send email", "EmailReport", typeof(ExceptionReporterCommands)); + ShowDetailsCommand = new RoutedUICommand("Show details", "ShowDetails", typeof(ExceptionReporterCommands)); } } } \ No newline at end of file From 56be24f9b521363649e48be26e73182370d51eff Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Tue, 10 Aug 2021 23:17:03 +1000 Subject: [PATCH 19/22] use some more mvvm in commands add the relaycommand and implement commanding with mvvm binding --- .../ExceptionReporter.WPF.csproj | 2 +- .../MvvM/View/WpfExceptionReporter.xaml | 22 +++---- .../MvvM/View/WpfExceptionReporter.xaml.cs | 35 +---------- .../ViewModel/ExceptionReporterCommands.cs | 17 ------ .../ViewModel/ExceptionReporterViewModel.cs | 59 +++++++++++++------ .../Plumbing/RelayCommand.cs | 30 ++++++++++ 6 files changed, 82 insertions(+), 83 deletions(-) delete mode 100644 src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs create mode 100644 src/ExceptionReporter.WPF/Plumbing/RelayCommand.cs diff --git a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index d44afc0b..e43a29a3 100644 --- a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -61,7 +61,6 @@ Designer - WpfExceptionReporter.xaml Code @@ -69,6 +68,7 @@ + Code diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index b8746657..50689a92 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -14,16 +14,10 @@ - - - - - - + @@ -50,7 +44,7 @@ + Text="{Binding Path=Info.MainException.Message}" /> @@ -94,24 +88,24 @@ - - - diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs index 97f38119..93c2e483 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml.cs @@ -1,11 +1,5 @@ using System; -using System.Windows; using System.Windows.Controls; -using System.Windows.Input; -using ExceptionReporting.Mail; -using ExceptionReporting.Network; -using ExceptionReporting.Network.Events; -using ExceptionReporting.Report; using ExceptionReporting.WPF.MvvM.ViewModel; // ReSharper disable CheckNamespace @@ -16,39 +10,12 @@ namespace ExceptionReporting.WPF.MvvM.View /// public partial class WpfExceptionReporter : UserControl { - private readonly ExceptionReportInfo _info; - private readonly ReportGenerator _reportGenerator; - public WpfExceptionReporter(Exception exception, ExceptionReportInfo info) { InitializeComponent(); - _info = info; - _info.MainException = exception; - _reportGenerator = new ReportGenerator(_info); + info.MainException = exception; this.DataContext = new ExceptionReporterViewModel(info); } - - private void CopyCanExecute(object sender, CanExecuteRoutedEventArgs e) - { - e.CanExecute = true; - } - - private void CopyExecute(object sender, ExecutedRoutedEventArgs e) - { - Clipboard.SetText(_reportGenerator.Generate()); - } - - private void EmailCanExecute(object sender, CanExecuteRoutedEventArgs e) - { - e.CanExecute = true; //TODO check MAPI compatible system? - } - - private void EmailExecute(object sender, ExecutedRoutedEventArgs e) - { - var report = _info.IsSimpleMAPI() ? new EmailReporter(_info).Create() : _reportGenerator.Generate(); - var sendFactory = new SenderFactory(_info, new SilentSendEvent(), new NoScreenShot()).Get(); - sendFactory.Send(report); - } } } \ No newline at end of file diff --git a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs b/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs deleted file mode 100644 index 582c3b5d..00000000 --- a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterCommands.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Windows.Input; - -// ReSharper disable CheckNamespace -namespace ExceptionReporting.WPF.MvvM.ViewModel -{ - public class ExceptionReporterCommands - { - public static readonly RoutedUICommand EmailCommand; - public static readonly RoutedUICommand ShowDetailsCommand; - - static ExceptionReporterCommands() - { - EmailCommand = new RoutedUICommand("Send email", "EmailReport", typeof(ExceptionReporterCommands)); - ShowDetailsCommand = new RoutedUICommand("Show details", "ShowDetails", typeof(ExceptionReporterCommands)); - } - } -} \ No newline at end of file diff --git a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterViewModel.cs b/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterViewModel.cs index 9362323e..2e704e55 100644 --- a/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterViewModel.cs +++ b/src/ExceptionReporter.WPF/MvvM/ViewModel/ExceptionReporterViewModel.cs @@ -1,34 +1,59 @@ -using System; -using System.ComponentModel; -using System.Runtime.CompilerServices; +using System.Windows; +using System.Windows.Input; +using ExceptionReporting.Mail; +using ExceptionReporting.Network; +using ExceptionReporting.Network.Events; +using ExceptionReporting.Plumbing; +using ExceptionReporting.Report; // ReSharper disable once CheckNamespace namespace ExceptionReporting.WPF.MvvM.ViewModel { - public class ExceptionReporterViewModel : INotifyPropertyChanged + public class ExceptionReporterViewModel { - private ExceptionReportInfo _info; + private RelayCommand _copyCommand; + private RelayCommand _emailCommand; + private RelayCommand _showDetailsCommand; + + public ExceptionReportInfo Info { get; } + private readonly ReportGenerator _reportGenerator; public ExceptionReporterViewModel(ExceptionReportInfo info) { - _info = info; + Info = info; + _reportGenerator = new ReportGenerator(Info); + } + + public ICommand CopyCommand + { + get { return _copyCommand ?? (_copyCommand = new RelayCommand(_ => Copy(), _ => true)); } + } + + public ICommand EmailCommand + { + get { return _emailCommand ?? (_emailCommand = new RelayCommand(_ => SendEmail(), _ => true)); } + } + + public ICommand ShowDetailsCommand + { + get { return _showDetailsCommand ?? (_showDetailsCommand = new RelayCommand(_ => ShowDetails(), _ => true)); } + } + + private void Copy() + { + Clipboard.SetText(_reportGenerator.Generate()); } - public ExceptionReportInfo Info + private void SendEmail() { - get => _info; - set - { - _info = value; - NotifyPropertyChanged(); - } + var report = Info.IsSimpleMAPI() ? new EmailReporter(Info).Create() : _reportGenerator.Generate(); + var sendFactory = new SenderFactory(Info, new SilentSendEvent(), new NoScreenShot()).Get(); + sendFactory.Send(report); } - // a quick/simple implementation of observable object - we only need it once - public event PropertyChangedEventHandler PropertyChanged; - private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") + private void ShowDetails() { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + //TODO ui stuff? } } } \ No newline at end of file diff --git a/src/ExceptionReporter.WPF/Plumbing/RelayCommand.cs b/src/ExceptionReporter.WPF/Plumbing/RelayCommand.cs new file mode 100644 index 00000000..5b0f6571 --- /dev/null +++ b/src/ExceptionReporter.WPF/Plumbing/RelayCommand.cs @@ -0,0 +1,30 @@ +using System; +using System.Diagnostics; +using System.Windows.Input; + +namespace ExceptionReporting.Plumbing +{ + public class RelayCommand : ICommand + { + readonly Action _execute; + readonly Predicate _canExecute; + + public RelayCommand(Action execute, Predicate canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); _canExecute = canExecute; + } + + [DebuggerStepThrough] + public bool CanExecute(object parameter) + { + return _canExecute == null || _canExecute(parameter); + } + + public event EventHandler CanExecuteChanged + { + add => CommandManager.RequerySuggested += value; + remove => CommandManager.RequerySuggested -= value; + } + public void Execute(object parameter) { _execute(parameter); } + } +} \ No newline at end of file From 7ef1a9b975df92e3929b3f8ae0659f3837243520 Mon Sep 17 00:00:00 2001 From: Peter van der Woude Date: Wed, 11 Aug 2021 23:03:01 +1000 Subject: [PATCH 20/22] add showdetails toggle button --- ExceptionReporter.NET.sln.DotSettings | 1 + src/Demos/WPF/DemoWindow.xaml | 2 +- src/Demos/WPF/DemoWindow.xaml.cs | 39 +- .../ExceptionReportInfo.cs | 20 + .../ExceptionReporter.WPF.csproj | 4 +- .../MvvM/View/WpfExceptionReporter.xaml | 32 +- .../ViewModel/ExceptionReporterViewModel.cs | 19 +- .../Plumbing/ObservableObject.cs | 17 + .../Properties/Annotations.cs | 1236 +++++++++++++++++ .../MVP/Views/ExceptionDetailControl.cs | 2 +- 10 files changed, 1344 insertions(+), 28 deletions(-) create mode 100644 src/ExceptionReporter.WPF/Plumbing/ObservableObject.cs create mode 100644 src/ExceptionReporter.WPF/Properties/Annotations.cs diff --git a/ExceptionReporter.NET.sln.DotSettings b/ExceptionReporter.NET.sln.DotSettings index 1c729933..564705fe 100644 --- a/ExceptionReporter.NET.sln.DotSettings +++ b/ExceptionReporter.NET.sln.DotSettings @@ -1,2 +1,3 @@  + True MAPI \ No newline at end of file diff --git a/src/Demos/WPF/DemoWindow.xaml b/src/Demos/WPF/DemoWindow.xaml index c1573824..3f3fc9b6 100644 --- a/src/Demos/WPF/DemoWindow.xaml +++ b/src/Demos/WPF/DemoWindow.xaml @@ -9,7 +9,7 @@ diff --git a/src/Demos/WPF/DemoWindow.xaml.cs b/src/Demos/WPF/DemoWindow.xaml.cs index 180fcb71..41baea39 100644 --- a/src/Demos/WPF/DemoWindow.xaml.cs +++ b/src/Demos/WPF/DemoWindow.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Data; using System.Windows; using ExceptionReporting; using ExceptionReporting.WPF.MvvM.View; @@ -17,21 +18,33 @@ public DemoWindow() private void ButtonBase_OnClick(object sender, RoutedEventArgs e) { - new Window + try { - Title = "Error Report", - Height = 250, - Width = 400, - Content = new WpfExceptionReporter(new Exception("WPF confluxion error"), new ExceptionReportInfo + TestMethod(); + } + catch (Exception ex) + { + new Window { - SendMethod = ReportSendMethod.SimpleMAPI, - EmailReportAddress = "support@acme.com", - CompanyName = "Acme", - TitleText = "Acme Error Report", - ShowLessDetailButton = true, - ReportTemplateFormat = TemplateFormat.Text, - }) - }.ShowDialog(); + Title = "Error Report", + Height = 250, + Width = 400, + Content = new WpfExceptionReporter(ex, new ExceptionReportInfo + { + SendMethod = ReportSendMethod.SimpleMAPI, + EmailReportAddress = "support@acme.com", + CompanyName = "Acme", + TitleText = "Acme Error Report", + ShowLessDetailButton = true, + ReportTemplateFormat = TemplateFormat.Text, + }) + }.ShowDialog(); + } + } + + private void TestMethod() + { + throw new DataException("Data is horribly incorrect"); } } } diff --git a/src/ExceptionReporter.Shared/ExceptionReportInfo.cs b/src/ExceptionReporter.Shared/ExceptionReportInfo.cs index 5348622c..5877ad17 100644 --- a/src/ExceptionReporter.Shared/ExceptionReportInfo.cs +++ b/src/ExceptionReporter.Shared/ExceptionReportInfo.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Net.Mail; using System.Reflection; +using System.Text; // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global @@ -305,6 +306,25 @@ public bool IsSimpleMAPI() { return SendMethod == ReportSendMethod.SimpleMAPI; } + + public string StackTrace + { + get + { + var s = new StringBuilder(); + var ex = MainException; + + while (ex != null) + { + s.AppendLine(ex.Message); + s.AppendLine(ex.StackTrace); + + ex = ex.InnerException; + } + + return s.ToString(); + } + } } } diff --git a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj index e43a29a3..4131431d 100644 --- a/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj +++ b/src/ExceptionReporter.WPF/ExceptionReporter.WPF.csproj @@ -33,7 +33,7 @@ 4 - false + true @@ -68,7 +68,9 @@ + + Code diff --git a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml index 50689a92..bef9623a 100644 --- a/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml +++ b/src/ExceptionReporter.WPF/MvvM/View/WpfExceptionReporter.xaml @@ -12,6 +12,7 @@ + @@ -42,9 +43,20 @@ - + + + + + + + - - + - -