├── .editorconfig ├── .github └── lockdown.yml ├── .gitignore ├── CHANGELOG ├── CONTRIBUTING.md ├── JuisCheck.sln ├── JuisCheck ├── .editorconfig ├── .vs │ └── JuisCheck.csproj.dtbcache.json ├── AVM │ ├── JUIS.cs │ ├── JUIS.wsdl │ ├── JUIS_http.wsdl │ └── JUIS_https.wsdl ├── App.xaml ├── App.xaml.cs ├── CollectionSettings.cs ├── ComboBoxEx.cs ├── ComboBoxValue.cs ├── ComboBoxValueComparer.cs ├── ContextMenuHelper.cs ├── DectDevice.cs ├── DectDeviceDialog.xaml ├── DectDeviceDialog.xaml.cs ├── Device.cs ├── DeviceCollection.cs ├── DeviceComparer.cs ├── DeviceProperty.cs ├── DownloadDialog.xaml ├── DownloadDialog.xaml.cs ├── ExtensionMethods.cs ├── FindUpdatesDialog.xaml ├── FindUpdatesDialog.xaml.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── GlobalSuppressions.cs ├── JUIS.cs ├── Jason │ └── BoxInfo.cs ├── JuisCheck.csproj ├── JuisDevice.cs ├── JuisDeviceDialog.xaml ├── JuisDeviceDialog.xaml.cs ├── Lang │ ├── JCstring.Designer.cs │ ├── JCstring.de.resx │ ├── JCstring.it.resx │ └── JCstring.resx ├── MainWindow.Backstage.cs ├── MainWindow.Devices.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── MessageBoxEx.xaml ├── MessageBoxEx.xaml.cs ├── MultiSelectDataGrid.cs ├── NaturalStringComparer.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── RecentFileButton.cs ├── RecentItemsCollection.cs ├── Resources │ ├── Converters │ │ ├── BoolToVisibilityConverter.cs │ │ ├── InverseBooleanConverter.cs │ │ └── NullableDateTimeToStringConverter.cs │ ├── Images │ │ ├── 16x16 │ │ │ ├── oxygen-application-exit.png │ │ │ ├── oxygen-dialog-warning.png │ │ │ ├── oxygen-document-close.png │ │ │ ├── oxygen-document-open-recent.png │ │ │ ├── oxygen-document-open.png │ │ │ ├── oxygen-document-save-as.png │ │ │ ├── oxygen-document-save.png │ │ │ ├── oxygen-help-about.png │ │ │ └── oxygen-preferences-system.png │ │ ├── 32x32 │ │ │ ├── oxygen-dialog-information.png │ │ │ ├── oxygen-dialog-ok-apply.png │ │ │ ├── oxygen-document-close.png │ │ │ ├── oxygen-document-edit.png │ │ │ ├── oxygen-document-new.png │ │ │ ├── oxygen-document-open-recent.png │ │ │ ├── oxygen-download.png │ │ │ ├── oxygen-edit-clear-list.png │ │ │ ├── oxygen-edit-copy.png │ │ │ ├── oxygen-edit-paste.png │ │ │ ├── oxygen-edit-select-all.png │ │ │ ├── oxygen-run-build-clean.png │ │ │ └── oxygen-system-search.png │ │ └── 48x48 │ │ │ └── JuisCheck.ico │ ├── ValidationRules │ │ ├── ComboBoxValueSelectedRule.cs │ │ ├── StringInt32RangeRule.cs │ │ └── StringNotNullOrWhiteSpaceRule.cs │ └── XAML │ │ ├── BaseStyles.xaml │ │ ├── ColorsAndBrushes.xaml │ │ ├── Converters.xaml │ │ ├── MainWindowBackstageStyles.xaml │ │ ├── MainWindowDataGridStyles.xaml │ │ ├── MainWindowDataGridTemplates.xaml │ │ ├── MainWindowRibbonStyles.xaml │ │ └── RecentFileButtonTemplate.xaml ├── XML │ ├── JC1Data.cs │ ├── JC1Device.cs │ ├── JC1DeviceKind.cs │ ├── JC2Data.cs │ ├── JC2DectDevice.cs │ ├── JC2JuisDevice.cs │ ├── JC2Setting.cs │ └── JCData.cs └── app.config ├── LICENSE ├── README.md ├── examples ├── FritzBox_Obsolete_Release.xml ├── FritzBox_Release.xml ├── FritzDECT_Release.xml ├── FritzPowerline_Release.xml ├── FritzWLAN_Obsolete_Release.xml └── FritzWLAN_Release.xml └── libraries ├── Muon.DotNetExtensions.dll ├── Muon.DotNetExtensions.pdb ├── Muon.DotNetExtensions.xml ├── Muon.Windows.Controls.dll ├── Muon.Windows.Controls.pdb ├── Muon.Windows.Controls.xml ├── Muon.Windows.dll ├── Muon.Windows.pdb └── Muon.Windows.xml /.editorconfig: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /.github/lockdown.yml: -------------------------------------------------------------------------------- 1 | # Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown 2 | 3 | only: pulls 4 | 5 | pulls: 6 | comment: > 7 | This repository does not accept pull requests. 8 | Please read the CONTRIBUTING document at https://github.com/kingfisher63/avm_juischeck for guidance. 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.vs 2 | /JuisCheck/bin 3 | /JuisCheck/obj 4 | /bin 5 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | v2.1.2 (2023/01/28) 2 | ------------------- 3 | Change: 'Upgrade' predefined DECT base to FRITZ!OS 7.50. 4 | Fix: handle leading/trailing whitespace in update version (triggered 5 | 'Invalid firmware update version' error during 'Make current'). 6 | 7 | v2.1.1 (2021/04/02) 8 | ------------------- 9 | Change: Updated Italian localization (thanks bovirus). 10 | Fix: HTTPS downloads failed because TLS1.2 was not enabled. 11 | 12 | Note: HTTPS downloads require Windows 7 or later as Windows 13 | Vista and earlier do not support TLS1.2. 14 | 15 | v2.1.0 (2020/10/19) 16 | ------------------- 17 | Change: DECT: use JUIS instead of CATI server to search for updates. 18 | New: DECT: view update info (release notes) in web browser. 19 | Fix: DECT: update search with language other than German returned 20 | an error. 21 | Fix: DECT: support for 5-part version numbers (FRITZ!DECT 500). 22 | 23 | Note: If you have a FRITZ!DECT 500 in a device collection, you must 24 | either correct the firmware version manually or do an update 25 | search and make the found version current. JuisCheck did not 26 | handle 5-part version numbers correctly prior to v2.1.0. 27 | 28 | v2.0.3 (2020/10/16) 29 | ------------------- 30 | Change: 'Upgrade' predefined DECT base to FRITZ!OS 7.21. 31 | Change: No firmware major version warning if Hardware == FirmwareMajor 32 | for Hardware >= 249 (FRITZ!Powerline 1260v2). This limit is an 33 | educated guess and may change in the future. 34 | New: Support for LabPLUS firmware type string (build type 1007) 35 | Fix: Highlight new updates also for DECT devices. 36 | Fix: Beta (Labor) DECT firmware cannot be found with beta (Labor) 37 | FRITZ!OS version (wrong FRITZ!OS version format in query). 38 | 39 | v2.0.2 (2020/04/21) 40 | ------------------- 41 | Change: Updated Italian localization (thanks bovirus). 42 | New: Highlight new updates (i.e. updates that differ from the current 43 | value in the Update column). 44 | Doc: updated README.md 45 | Doc: added CONTRIBUTING.md 46 | 47 | v2.0.1 (2020/04/13) 48 | ------------------- 49 | New: Predefined DECT base device (FRITZ!Box 7590 with FRITZ!OS 7.12). 50 | New: German localization. 51 | New: Show download file name in download window caption. 52 | Fix: Application restart message is shown when resetting settings to 53 | default even if the UI language setting is already default. 54 | Fix: Backstage panel width is too small for German localization. 55 | 56 | v2.0.0 (2020/04/04) 57 | ------------------- 58 | Note: JuisCheck v2 is a major release that comes with some breaking changes. 59 | Please consult the README.md file for details about upgrading from 60 | JuisCheck v1.x. 61 | Change: Requires .NET Framework 4.5 or later (Windows Vista or later). 62 | Change: New collection XML file format (incompatible with JuisCheck 1.x). 63 | Change: Column visibility is saved in the collection XML file. 64 | Change: Use built-in engine to download firmware images instead of launching 65 | the default web browser as web browsers are dropping FTP support. 66 | Change: No firmware major version warning if Hardware == FirmwareMajor for 67 | Hardware >= 252 (FRITZ!Box 6660 Cable). This limit is an educated 68 | guess and may change in the future. 69 | New: Select device as Mesh master for non-DECT devices. 70 | New: Select device as DECT base for DECT devices. 71 | New: Column for Mesh master / DECT base (replaces Base Fritz!OS column). 72 | New: Select default columns for new collections (in backstage settings). 73 | New: Select user interface language (default: automatic). 74 | New: Italian localization (thanks bovirus). 75 | New: Support for build type 1006 (TEST beta). 76 | New: Support for devices like DECT 500 which have a different firmware 77 | file name format (5 version parts instead of 4). 78 | New: Portable mode. 79 | New: Menu item icons in backstage. 80 | New: Exit the program with Ctrl-X. 81 | Fix: Device information tooltip is not updated after data change. 82 | Fix: Device information tooltip date/time format is inconsistent with 83 | table date/time format. 84 | Fix: FileNotFoundException is thrown at startup when trying to autoload 85 | a file that does not exist (eg. because it has been renamed or 86 | deleted). 87 | Fix: Firmware version string is not updated after build type change under 88 | certain circumstances. 89 | Fix: Some version formats in the update info cannot not be parsed. JuisCheck 90 | can now handle a wide variety of formats. 91 | Fix: Flags text box height is too small on Windows 10. 92 | 93 | v1.4.2 (2019/06/23) 94 | ------------------- 95 | New: Support for build type 1007 (PLUS beta). 96 | Fix: Update version 149.07.08-67660Labor for FRITZ!Box 7560 could not be 97 | made current due to missing white space between the build number (67660) 98 | and the build type qualifier (Labor). The update version is a string 99 | that is apparently hand crafted by AVM which may cause unanticipated 100 | format variations. 101 | 102 | v1.4.1 (2019/03/07) 103 | ------------------- 104 | New: Keyboard shortcuts for all ribbon buttons. 105 | Fix: Datagrid keyboard navigation did not work correctly when focus was 106 | returned to the datagrid (e.g. after adding or editing a device). 107 | Fix: Update version 105.06.85i for FRITZ!Box 6840 LTE International could 108 | not be made current due to the trailing 'i'. 109 | 110 | v1.4.0 (2018/12/29) 111 | ------------------- 112 | New: Add a device that is a copy of the selected device. 113 | New: JuisCheck remembers the directory of the last successful 'Open' or 114 | 'Save As' dialog. Opening a device collection from the Recent Files 115 | list does not change the remembered directory. 116 | Fix: The column width would jump when resizing a column to a width less 117 | than the column header text width. 118 | Fix: The sort direction was only cleared on the 'Device name' and 'Product 119 | name' columns when a new device collection was opened or the current 120 | collection was closed. 121 | Fix: The column width was not reset to Auto when a new device collection 122 | was opened or the current collection was closed. 123 | Fix: The 'Update file name' column was not cleared in the data grid when 124 | an update was made current. 125 | 126 | v1.3.0 (2018/12/28) 127 | ------------------- 128 | New: Setting to automatically load the current device collection at next 129 | program start. 130 | 131 | v1.2.0 (2018/12/27) 132 | ------------------- 133 | New: Support for the legacy jason_boxinfo.xml device information. When a 134 | request for juis_boxinfo.xml fails with HTTP error 404 (Not Found), 135 | JuisCheck will make a request for jason_boxinfo.xml. A heuristic is 136 | used to determine the firmware build type from the Lab element (the 137 | default is Release). 138 | 139 | v1.1.0 (2018/12/25) 140 | ------------------- 141 | New: Recent files context menu: open file, remove file from the list. 142 | New: Recent files: button to remove all files from the list. 143 | New: Hide/show datagrid columns via a context menu on the column headers. 144 | New: Datagrid columns for hardware, country, language and update file name 145 | (hidden by default). 146 | New: Button to reset settings to defaults. 147 | Fix: The device information tooltip on the datagrid was garbled ('Update file 148 | name' and 'Last checked' fields were in the same row for non-DECT devices). 149 | Change: Base Fritz!OS column is hidden by default. 150 | 151 | v1.0.1 (2018/12/24) 152 | ------------------- 153 | Fix: JuisCheck would exit silently in case of an unhandled exception. It now 154 | displays an error message and attempts to copy the exception data to the 155 | clipboard before exiting. 156 | Fix: A COMException might be thrown when copying image URLs to the clipboard. 157 | The cause is probably that the clipboard is locked by another program 158 | (e.g. some tool that monitors the clipboard). JuisCheck now retries 159 | in case of errors and displays an error message if all attempts fail. 160 | Fix: JuisCheck used Linux style newline (\n) when copying multiple URLs to 161 | the clipboard instead of Windows style newline (\r\n). 162 | Fix: The tooltips of the Recent and Settings backstage menu buttons would 163 | also be shown on the panel area. The tooltips are now restricted to the 164 | button area. 165 | 166 | v1.0.0 (2018/12/20) 167 | ------------------- 168 | Initial release 169 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | JuisCheck is *Open Source* (so that you can inspect the code or create your own 4 | version if you like). However it is not *Open Collaboration*. This repository 5 | offers JuisCheck 'as is' and does not accept pull requests. **Pull requests are 6 | closed automatically.** 7 | 8 | ## Bug reports 9 | 10 | Create a new issue if you wish to report a bug. Please include any error messages 11 | (if applicable) and steps to reproduce (if possible). 12 | 13 | ## Features requests 14 | 15 | Create a new issue if you wish to suggest a new feature. Feature requests will be 16 | considered if they are within the scope of the program as outlined at the top of 17 | the [README](README.md) document. 18 | 19 | ## User interface translation (localization) 20 | 21 | Tranlations are only accepted for user interface languages *supported by FRITZ!OS*. 22 | Unfortunately it is impossible to selectively permit pull requests. Kindly create 23 | a new issue if you wish to contribute a translation. 24 | -------------------------------------------------------------------------------- /JuisCheck.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29920.165 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JuisCheck", "JuisCheck\JuisCheck.csproj", "{E1A82DAF-EE0A-43FA-BEC7-EB63EC3EF78D}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{37F69898-70D6-44AD-9094-53D5A0B7FF34}" 9 | ProjectSection(SolutionItems) = preProject 10 | .editorconfig = .editorconfig 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {E1A82DAF-EE0A-43FA-BEC7-EB63EC3EF78D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {E1A82DAF-EE0A-43FA-BEC7-EB63EC3EF78D}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {E1A82DAF-EE0A-43FA-BEC7-EB63EC3EF78D}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {E1A82DAF-EE0A-43FA-BEC7-EB63EC3EF78D}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {24B6B326-913B-4435-A843-AFA74EEB9288} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /JuisCheck/.editorconfig: -------------------------------------------------------------------------------- 1 | # To learn more about .editorconfig see https://aka.ms/editorconfigdocs 2 | 3 | # CA1062: Validate arguments of public methods 4 | dotnet_code_quality.CA1062.exclude_extension_method_this_parameter = true 5 | 6 | [*.cs] 7 | 8 | # CA1303: Do not pass literals as localized parameters 9 | dotnet_diagnostic.CA1303.severity = none 10 | 11 | # Default severity for analyzer diagnostics with category 'Style' 12 | dotnet_analyzer_diagnostic.category-Style.severity = none 13 | -------------------------------------------------------------------------------- /JuisCheck/.vs/JuisCheck.csproj.dtbcache.json: -------------------------------------------------------------------------------- 1 | {"RootPath":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck","ProjectFileName":"JuisCheck.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"CollectionSettings.cs"},{"SourceFile":"ComboBoxEx.cs"},{"SourceFile":"ComboBoxValue.cs"},{"SourceFile":"ComboBoxValueComparer.cs"},{"SourceFile":"Connected Services\\JUIS\\Reference.cs"},{"SourceFile":"DectDevice.cs"},{"SourceFile":"DectDeviceDialog.xaml.cs"},{"SourceFile":"DeviceComparer.cs"},{"SourceFile":"DeviceProperty.cs"},{"SourceFile":"DownloadDialog.xaml.cs"},{"SourceFile":"FindUpdatesDialog.xaml.cs"},{"SourceFile":"GlobalSuppressions.cs"},{"SourceFile":"Jason\\BoxInfo.cs"},{"SourceFile":"JuisDevice.cs"},{"SourceFile":"MainWindow.Devices.cs"},{"SourceFile":"NaturalStringComparer.cs"},{"SourceFile":"RecentItemsCollection.cs"},{"SourceFile":"Resources\\Converters\\BoolToVisibilityConverter.cs"},{"SourceFile":"Resources\\Converters\\InverseBooleanConverter.cs"},{"SourceFile":"Resources\\Converters\\NullableDateTimeToStringConverter.cs"},{"SourceFile":"Resources\\ValidationRules\\ComboBoxValueSelectedRule.cs"},{"SourceFile":"Resources\\ValidationRules\\StringInt32RangeRule.cs"},{"SourceFile":"Resources\\ValidationRules\\StringNotNullOrWhiteSpaceRule.cs"},{"SourceFile":"XML\\JC1Data.cs"},{"SourceFile":"XML\\JC1Device.cs"},{"SourceFile":"XML\\JC1DeviceKind.cs"},{"SourceFile":"XML\\JC2Data.cs"},{"SourceFile":"XML\\JC2DectDevice.cs"},{"SourceFile":"XML\\JC2JuisDevice.cs"},{"SourceFile":"XML\\JC2Setting.cs"},{"SourceFile":"XML\\JCData.cs"},{"SourceFile":"App.xaml.cs"},{"SourceFile":"Device.cs"},{"SourceFile":"DeviceCollection.cs"},{"SourceFile":"JuisDeviceDialog.xaml.cs"},{"SourceFile":"Lang\\JCstring.Designer.cs"},{"SourceFile":"MainWindow.Backstage.cs"},{"SourceFile":"MainWindow.xaml.cs"},{"SourceFile":"MultiSelectDataGrid.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"Properties\\Resources.Designer.cs"},{"SourceFile":"Properties\\Settings.Designer.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.5.AssemblyAttributes.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\DectDeviceDialog.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\DownloadDialog.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\JuisDeviceDialog.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\FindUpdatesDialog.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\MainWindow.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\App.g.cs"},{"SourceFile":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\obj\\Debug\\GeneratedInternalTypeHelper.g.cs"}],"References":[{"Reference":"C:\\Users\\Roger\\.nuget\\packages\\controlzex\\4.2.2\\lib\\net45\\ControlzEx.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Roger\\.nuget\\packages\\costura.fody\\4.1.0\\lib\\net40\\Costura.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Roger\\.nuget\\packages\\fluent.ribbon\\7.1.0\\lib\\net45\\Fluent.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Roger\\.nuget\\packages\\microsoft.xaml.behaviors.wpf\\1.1.19\\lib\\net45\\Microsoft.Xaml.Behaviors.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\libraries\\Muon.DotNetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\libraries\\Muon.Windows.Controls.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\libraries\\Muon.Windows.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\PresentationCore.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\PresentationFramework.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Drawing.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Net.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Runtime.Serialization.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.ServiceModel.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Windows.Forms.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Xaml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\UIAutomationProvider.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\UIAutomationTypes.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\WindowsBase.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\WindowsFormsIntegration.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\bin\\Debug\\JuisCheck.exe","OutputItemRelativePath":"JuisCheck.exe"},{"OutputItemFullPath":"D:\\Projects\\Roger\\Windows Utilities\\JuisCheck\\JuisCheck\\bin\\Debug\\JuisCheck.pdb","OutputItemRelativePath":"JuisCheck.pdb"}],"CopyToOutputEntries":[]} -------------------------------------------------------------------------------- /JuisCheck/App.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /JuisCheck/App.xaml.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using Muon.Dotnet.Extensions; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Diagnostics; 11 | using System.Globalization; 12 | using System.IO; 13 | using System.Linq; 14 | using System.Net; 15 | using System.Net.Security; 16 | using System.Reflection; 17 | using System.Runtime.InteropServices; 18 | using System.Security.Cryptography.X509Certificates; 19 | using System.Threading; 20 | using System.Windows; 21 | using System.Windows.Markup; 22 | using System.Windows.Threading; 23 | using WinForms = System.Windows.Forms; 24 | 25 | using JuisCheck.Lang; 26 | using JuisCheck.Properties; 27 | 28 | namespace JuisCheck 29 | { 30 | /// 31 | /// Interaction logic for App.xaml 32 | /// 33 | public partial class App : Application 34 | { 35 | public const string defaultDataFileName = "default.xml"; 36 | public const string portableProgramFileName = "JuisCheckPortable.exe"; 37 | public const string programName = "JuisCheck"; 38 | public const string programVersionSuffix = ""; // BETA, RC1, etc. 39 | 40 | public const StringComparison defaultDisplayStringComparison = StringComparison.CurrentCultureIgnoreCase; 41 | public const StringComparison defaultFileNameComparison = StringComparison.OrdinalIgnoreCase; 42 | 43 | private static readonly Settings programSettings = Settings.Default; 44 | 45 | public static bool IsLanguageSelectionEnabled { get; private set; } 46 | public static bool IsPortableMode { get; private set; } 47 | public static bool RestartPending { get; private set; } 48 | 49 | public static List AdditionalLanguages { get; } = new List() { "de", "es", "fr", "it", "nl", "pl" }; 50 | 51 | /*****************/ 52 | /* Other methods */ 53 | /*****************/ 54 | 55 | public static void CancelRestart() 56 | { 57 | RestartPending = false; 58 | } 59 | 60 | public static string GetAssemblyName() { return Assembly.GetExecutingAssembly().GetName().Name; } 61 | public static string GetCopyright() { return Assembly.GetExecutingAssembly().GetCopyright(); } 62 | public static string GetDefaultDirectory() { return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); } 63 | public static string GetLocation() { return Assembly.GetExecutingAssembly().Location; } 64 | public static string GetProgramDirectory() { return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } 65 | public static string GetProgramFileName() { return Path.GetFileName(Assembly.GetExecutingAssembly().Location); } 66 | public static string GetProgramInfo() { return $"{programName} {GetVersion()}{programVersionSuffix}"; } 67 | public static MainWindow GetMainWindow() { return (MainWindow)Current.MainWindow; } 68 | public static string GetVersion() { return Assembly.GetExecutingAssembly().GetName().Version.ToString(3); } 69 | 70 | public static void Restart() 71 | { 72 | RestartPending = true; 73 | GetMainWindow().Close(); 74 | } 75 | 76 | public static bool SafeClipboardSetText( string text ) 77 | { 78 | try { 79 | // Does retries internally if needed (System.Windows.Clipboard does not do this) 80 | WinForms.Clipboard.SetDataObject(text, true); 81 | return true; 82 | } 83 | catch (ExternalException) { 84 | return false; 85 | } 86 | } 87 | 88 | private static bool ServiceCertificateValidationCallback(object obt, X509Certificate cert, X509Chain chain, SslPolicyErrors sslPolicyErrors) 89 | { 90 | if (sslPolicyErrors == SslPolicyErrors.None) { 91 | return true; 92 | } 93 | 94 | var cert2 = new X509Certificate2(cert); 95 | var commonName = cert2.GetNameInfo(X509NameType.SimpleName, false); 96 | 97 | if (commonName == JUIS.GetServerName()) { 98 | return true; 99 | } 100 | 101 | return false; 102 | } 103 | 104 | // Event handler: Exit 105 | 106 | private void Exit_Handler( object sender, ExitEventArgs evt ) 107 | { 108 | if (!IsPortableMode) { 109 | programSettings.Save(); 110 | } 111 | 112 | if (RestartPending) { 113 | Process.Start(App.GetLocation()); 114 | } 115 | } 116 | 117 | // Event handler: Startup 118 | 119 | private void Startup_Handler( object sender, StartupEventArgs evt ) 120 | { 121 | string assemblyName = GetAssemblyName(); 122 | string programDirectory = GetProgramDirectory(); 123 | string programName = GetProgramFileName(); 124 | 125 | // Portable mode 126 | 127 | IsPortableMode = string.Compare(programName, portableProgramFileName, defaultFileNameComparison) == 0; 128 | 129 | // Initialize settings 130 | 131 | if (IsPortableMode) { 132 | programSettings.Reset(); 133 | programSettings.AutoLoadFile = Path.Combine(programDirectory, defaultDataFileName); 134 | programSettings.LastDocumentDirectory = programDirectory; 135 | programSettings.LastDownloadDirectory = programDirectory; 136 | } else 137 | if (programSettings.SettingsUpgradeRequired) { 138 | programSettings.Upgrade(); 139 | programSettings.SettingsUpgradeRequired = false; 140 | } 141 | 142 | // Additional languages (using resource dictionaries) 143 | 144 | if (IsPortableMode) { 145 | IsLanguageSelectionEnabled = false; 146 | } else { 147 | foreach (string language in AdditionalLanguages.ToList()) { 148 | if (!File.Exists(Path.Combine(programDirectory, language, $"{assemblyName}.resources.dll"))) { 149 | AdditionalLanguages.Remove(language); 150 | } 151 | } 152 | 153 | if (AdditionalLanguages.Count == 0) { 154 | programSettings.UserInterfaceLanguage = "auto"; 155 | } 156 | 157 | IsLanguageSelectionEnabled = AdditionalLanguages.Count != 0; 158 | } 159 | 160 | // Set user interface language 161 | 162 | CultureInfo cultureInfo; 163 | try { 164 | cultureInfo = new CultureInfo(programSettings.UserInterfaceLanguage); 165 | } 166 | catch (CultureNotFoundException) { 167 | cultureInfo = CultureInfo.InstalledUICulture; 168 | } 169 | Thread.CurrentThread.CurrentUICulture = cultureInfo; 170 | 171 | // SSL/TLS 172 | 173 | ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3; // Deprecated 174 | ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls; // Deprecated 175 | ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls11; // Deprecated 176 | ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; 177 | 178 | // Ignore certificate errors for JUIS queries (AVM uses a private root CA that is not globally trused) 179 | 180 | ServicePointManager.ServerCertificateValidationCallback += ServiceCertificateValidationCallback; 181 | } 182 | 183 | // Event handler: DispatcherUnhandledException 184 | 185 | private void DispatcherUnhandledException_Handler( object sender, DispatcherUnhandledExceptionEventArgs evt ) 186 | { 187 | string exceptionText = string.Empty; 188 | 189 | for (Exception exception = evt.Exception; exception != null; exception = exception.InnerException) { 190 | exceptionText += $"Type = {exception.GetType().Name}\r\n"; 191 | exceptionText += $"Message = {exception.Message}\r\n"; 192 | 193 | if (exception is ExternalException externalException) { 194 | exceptionText += $"HResult = 0x{externalException.ErrorCode:X8}"; 195 | } 196 | 197 | if (exception is XamlParseException xamlParseException) { 198 | exceptionText += $"XAML URI = {xamlParseException.BaseUri}\r\n"; 199 | exceptionText += $"XAML line = {xamlParseException.LineNumber}\r\n"; 200 | exceptionText += $"XAML pos = {xamlParseException.LinePosition}\r\n"; 201 | exceptionText += $"XAML key = {xamlParseException.KeyContext}\r\n"; 202 | exceptionText += $"XAML name = {xamlParseException.NameContext}\r\n"; 203 | } 204 | 205 | exceptionText += $"HasInner = {exception.InnerException != null}\r\n"; 206 | exceptionText += $"{exception.StackTrace}\r\n\r\n"; 207 | } 208 | 209 | string message; 210 | if (SafeClipboardSetText(exceptionText)) { 211 | message = JCstring.MessageTextUnhandledExceptionCopySuccess.Unescape(); 212 | } else { 213 | message = JCstring.MessageTextUnhandledExceptionCopyFailure.Unescape(); 214 | } 215 | 216 | _ = MessageBoxEx.Show(new MessageBoxExParams { 217 | CaptionText = JCstring.MessageCaptionFatalError, 218 | MessageText = string.Format(CultureInfo.CurrentCulture, message, evt.Exception.GetType().Name), 219 | Image = MessageBoxExImage.Error, 220 | ButtonText = new string[] { JCstring.DialogButtonTextOk } 221 | }); 222 | 223 | Environment.Exit(1); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /JuisCheck/CollectionSettings.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | using System.Globalization; 11 | using System.Runtime.CompilerServices; 12 | 13 | using JuisCheck.Properties; 14 | 15 | namespace JuisCheck 16 | { 17 | public sealed class CollectionSettings : INotifyPropertyChanged 18 | { 19 | private static readonly Settings programSettings = Settings.Default; 20 | private readonly Dictionary settings = new Dictionary(); 21 | 22 | public const string keyDataGridColumnVisibleCountry = "DataGridColumnVisibleCountry"; 23 | public bool DataGridColumnVisibleCountry 24 | { 25 | get => GetBoolValue(keyDataGridColumnVisibleCountry); 26 | set { 27 | settings[keyDataGridColumnVisibleCountry] = value.ToString(CultureInfo.InvariantCulture); 28 | NotifyPropertyChanged(); 29 | } 30 | } 31 | 32 | public const string keyDataGridColumnVisibleDeviceAddress = "DataGridColumnVisibleDeviceAddress"; 33 | public bool DataGridColumnVisibleDeviceAddress 34 | { 35 | get => GetBoolValue(keyDataGridColumnVisibleDeviceAddress); 36 | set { 37 | settings[keyDataGridColumnVisibleDeviceAddress] = value.ToString(CultureInfo.InvariantCulture); 38 | NotifyPropertyChanged(); 39 | } 40 | } 41 | 42 | public const string keyDataGridColumnVisibleFirmware = "DataGridColumnVisibleFirmware"; 43 | public bool DataGridColumnVisibleFirmware 44 | { 45 | get => GetBoolValue(keyDataGridColumnVisibleFirmware); 46 | set { 47 | settings[keyDataGridColumnVisibleFirmware] = value.ToString(CultureInfo.InvariantCulture); 48 | NotifyPropertyChanged(); 49 | } 50 | } 51 | 52 | public const string keyDataGridColumnVisibleFirmwareBuildType = "DataGridColumnVisibleFirmwareBuildType"; 53 | public bool DataGridColumnVisibleFirmwareBuildType 54 | { 55 | get => GetBoolValue(keyDataGridColumnVisibleFirmwareBuildType); 56 | set { 57 | settings[keyDataGridColumnVisibleFirmwareBuildType] = value.ToString(CultureInfo.InvariantCulture); 58 | NotifyPropertyChanged(); 59 | } 60 | } 61 | 62 | public const string keyDataGridColumnVisibleHardware = "DataGridColumnVisibleHardware"; 63 | public bool DataGridColumnVisibleHardware 64 | { 65 | get => GetBoolValue(keyDataGridColumnVisibleHardware); 66 | set { 67 | settings[keyDataGridColumnVisibleHardware] = value.ToString(CultureInfo.InvariantCulture); 68 | NotifyPropertyChanged(); 69 | } 70 | } 71 | 72 | public const string keyDataGridColumnVisibleLanguage = "DataGridColumnVisibleLanguage"; 73 | public bool DataGridColumnVisibleLanguage 74 | { 75 | get => GetBoolValue(keyDataGridColumnVisibleLanguage); 76 | set { 77 | settings[keyDataGridColumnVisibleLanguage] = value.ToString(CultureInfo.InvariantCulture); 78 | NotifyPropertyChanged(); 79 | } 80 | } 81 | 82 | public const string keyDataGridColumnVisibleMasterBase = "DataGridColumnVisibleMasterBase"; 83 | public bool DataGridColumnVisibleMasterBase 84 | { 85 | get => GetBoolValue(keyDataGridColumnVisibleMasterBase); 86 | set { 87 | settings[keyDataGridColumnVisibleMasterBase] = value.ToString(CultureInfo.InvariantCulture); 88 | NotifyPropertyChanged(); 89 | } 90 | } 91 | 92 | public const string keyDataGridColumnVisibleOEM = "DataGridColumnVisibleOEM"; 93 | public bool DataGridColumnVisibleOEM 94 | { 95 | get => GetBoolValue(keyDataGridColumnVisibleOEM); 96 | set { 97 | settings[keyDataGridColumnVisibleOEM] = value.ToString(CultureInfo.InvariantCulture); 98 | NotifyPropertyChanged(); 99 | } 100 | } 101 | 102 | public const string keyDataGridColumnVisibleProductName = "DataGridColumnVisibleProductName"; 103 | public bool DataGridColumnVisibleProductName 104 | { 105 | get => GetBoolValue(keyDataGridColumnVisibleProductName); 106 | set { 107 | settings[keyDataGridColumnVisibleProductName] = value.ToString(CultureInfo.InvariantCulture); 108 | NotifyPropertyChanged(); 109 | } 110 | } 111 | 112 | public const string keyDataGridColumnVisibleUpdateFileName = "DataGridColumnVisibleUpdateFileName"; 113 | public bool DataGridColumnVisibleUpdateFileName 114 | { 115 | get => GetBoolValue(keyDataGridColumnVisibleUpdateFileName); 116 | set { 117 | settings[keyDataGridColumnVisibleUpdateFileName] = value.ToString(CultureInfo.InvariantCulture); 118 | NotifyPropertyChanged(); 119 | } 120 | } 121 | 122 | public const string keyDataGridColumnVisibleUpdateInfo = "DataGridColumnVisibleUpdateInfo"; 123 | public bool DataGridColumnVisibleUpdateInfo 124 | { 125 | get => GetBoolValue(keyDataGridColumnVisibleUpdateInfo); 126 | set { 127 | settings[keyDataGridColumnVisibleUpdateInfo] = value.ToString(CultureInfo.InvariantCulture); 128 | NotifyPropertyChanged(); 129 | } 130 | } 131 | 132 | public const string keyDataGridColumnVisibleUpdateLastChecked = "DataGridColumnVisibleUpdateLastChecked"; 133 | public bool DataGridColumnVisibleUpdateLastChecked 134 | { 135 | get => GetBoolValue(keyDataGridColumnVisibleUpdateLastChecked); 136 | set { 137 | settings[keyDataGridColumnVisibleUpdateLastChecked] = value.ToString(CultureInfo.InvariantCulture); 138 | NotifyPropertyChanged(); 139 | } 140 | } 141 | 142 | /****************/ 143 | /* Constructors */ 144 | /****************/ 145 | 146 | public CollectionSettings() 147 | { 148 | Reset(); 149 | } 150 | 151 | /******************/ 152 | /* Other medthods */ 153 | /******************/ 154 | 155 | public void Add( string settingName, string settingValue ) 156 | { 157 | if (settingName == null) { throw new ArgumentNullException(nameof(settingName)); } 158 | if (settingValue == null) { throw new ArgumentNullException(nameof(settingValue)); } 159 | 160 | settings[settingName] = settingValue; 161 | } 162 | 163 | private bool GetBoolValue( string settingName, bool defaultValue = false ) { 164 | if (settingName == null) { throw new ArgumentNullException(nameof(settingName)); } 165 | 166 | if (settings.TryGetValue(settingName, out string stringValue)) { 167 | if (bool.TryParse(stringValue, out bool value)) { 168 | return value; 169 | } 170 | } 171 | 172 | return defaultValue; 173 | } 174 | 175 | public Dictionary GetDictionary() 176 | { 177 | return settings; 178 | } 179 | 180 | public void Reset() 181 | { 182 | SetDefaultsValues(); 183 | } 184 | 185 | public void NotifySettingsProperties() 186 | { 187 | NotifyPropertyChanged(nameof(DataGridColumnVisibleCountry)); 188 | NotifyPropertyChanged(nameof(DataGridColumnVisibleDeviceAddress)); 189 | NotifyPropertyChanged(nameof(DataGridColumnVisibleFirmware)); 190 | NotifyPropertyChanged(nameof(DataGridColumnVisibleFirmwareBuildType)); 191 | NotifyPropertyChanged(nameof(DataGridColumnVisibleHardware)); 192 | NotifyPropertyChanged(nameof(DataGridColumnVisibleLanguage)); 193 | NotifyPropertyChanged(nameof(DataGridColumnVisibleMasterBase)); 194 | NotifyPropertyChanged(nameof(DataGridColumnVisibleOEM)); 195 | NotifyPropertyChanged(nameof(DataGridColumnVisibleProductName)); 196 | NotifyPropertyChanged(nameof(DataGridColumnVisibleUpdateFileName)); 197 | NotifyPropertyChanged(nameof(DataGridColumnVisibleUpdateInfo)); 198 | NotifyPropertyChanged(nameof(DataGridColumnVisibleUpdateLastChecked)); 199 | } 200 | 201 | private void SetDefaultsValues() 202 | { 203 | DataGridColumnVisibleCountry = programSettings.DefaultDataGridColumnVisibleCountry; 204 | DataGridColumnVisibleDeviceAddress = programSettings.DefaultDataGridColumnVisibleDeviceAddress; 205 | DataGridColumnVisibleFirmware = programSettings.DefaultDataGridColumnVisibleFirmware; 206 | DataGridColumnVisibleFirmwareBuildType = programSettings.DefaultDataGridColumnVisibleFirmwareBuildType; 207 | DataGridColumnVisibleHardware = programSettings.DefaultDataGridColumnVisibleHardware; 208 | DataGridColumnVisibleLanguage = programSettings.DefaultDataGridColumnVisibleLanguage; 209 | DataGridColumnVisibleMasterBase = programSettings.DefaultDataGridColumnVisibleMasterBase; 210 | DataGridColumnVisibleOEM = programSettings.DefaultDataGridColumnVisibleOEM; 211 | DataGridColumnVisibleProductName = programSettings.DefaultDataGridColumnVisibleProductName; 212 | DataGridColumnVisibleUpdateFileName = programSettings.DefaultDataGridColumnVisibleUpdateFileName; 213 | DataGridColumnVisibleUpdateInfo = programSettings.DefaultDataGridColumnVisibleUpdateInfo; 214 | DataGridColumnVisibleUpdateLastChecked = programSettings.DefaultDataGridColumnVisibleUpdateLastChecked; 215 | } 216 | 217 | // Interface: INotifyPropertyChanged 218 | 219 | public event PropertyChangedEventHandler PropertyChanged; 220 | 221 | private void NotifyPropertyChanged( [CallerMemberName] string propertyName = null ) 222 | { 223 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /JuisCheck/ComboBoxEx.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Threading; 11 | 12 | namespace JuisCheck 13 | { 14 | public class ComboBoxEx : ComboBox 15 | { 16 | // DependencyProperty: MaxDropDownItems 17 | 18 | public static readonly DependencyProperty MaxDropDownItemsProperty = DependencyProperty.Register("MaxDropDownItems", typeof(int), typeof(ComboBoxEx), new FrameworkPropertyMetadata(0)); 19 | 20 | public int MaxDropDownItems 21 | { 22 | get => (int)GetValue(MaxDropDownItemsProperty); 23 | set => SetValue(MaxDropDownItemsProperty, value); 24 | } 25 | 26 | // Event: DropDownOpened 27 | 28 | protected override void OnDropDownOpened( EventArgs evt ) 29 | { 30 | base.OnDropDownOpened(evt); 31 | 32 | if (MaxDropDownItems > 0) { 33 | Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { 34 | if (ItemContainerGenerator.ContainerFromIndex(0) is UIElement container) { 35 | if (container.RenderSize.Height > 0) { 36 | MaxDropDownHeight = container.RenderSize.Height * MaxDropDownItems + 2; 37 | } 38 | } 39 | })); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /JuisCheck/ComboBoxValue.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Globalization; 10 | using System.Linq; 11 | 12 | using JuisCheck.Lang; 13 | 14 | namespace JuisCheck 15 | { 16 | public class ComboBoxValue 17 | { 18 | public string Value { get; private set; } 19 | public string DisplayString { get; private set; } 20 | 21 | public ComboBoxValue( string value, string displayString ) 22 | { 23 | Value = value; 24 | DisplayString = displayString; 25 | } 26 | } 27 | 28 | public static class ComboBoxValueExt 29 | { 30 | public static List AppendMissingAsUnknown( this List values, int currentValue ) 31 | { 32 | if (values == null) { 33 | throw new ArgumentNullException(nameof(values)); 34 | } 35 | 36 | if (currentValue >= 0) { 37 | string currentValueStr = currentValue.ToString(CultureInfo.InvariantCulture); 38 | if (!values.Any( v => currentValueStr == v.Value )) { 39 | values.Add(new ComboBoxValue(currentValueStr, string.Format(CultureInfo.CurrentCulture, JCstring.ComboBoxValueUnknown, currentValueStr))); 40 | } 41 | } 42 | 43 | return values; 44 | } 45 | 46 | public static List AppendMissingAsUnknown( this List values, string currentValue ) 47 | { 48 | if (values == null) { 49 | throw new ArgumentNullException(nameof(values)); 50 | } 51 | 52 | if (!string.IsNullOrWhiteSpace(currentValue)) { 53 | if (!values.Any( v => currentValue == v.Value )) { 54 | values.Add(new ComboBoxValue(currentValue, string.Format(CultureInfo.CurrentCulture, JCstring.ComboBoxValueUnknown, currentValue))); 55 | } 56 | } 57 | 58 | return values; 59 | } 60 | 61 | public static List Prepend( this List values, string value, string displayString ) 62 | { 63 | values.Insert(0, new ComboBoxValue(value ?? throw new ArgumentNullException(nameof(value)), displayString ?? throw new ArgumentNullException(nameof(displayString)))); 64 | 65 | return values; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /JuisCheck/ComboBoxValueComparer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace JuisCheck 11 | { 12 | public sealed class ComboBoxValueComparer : Comparer 13 | { 14 | private readonly IComparer comparer; 15 | 16 | public ComboBoxValueComparer( StringComparison stringComparison ) 17 | { 18 | switch (stringComparison) { 19 | case StringComparison.CurrentCulture: comparer = StringComparer.CurrentCulture; break; 20 | case StringComparison.CurrentCultureIgnoreCase: comparer = StringComparer.CurrentCultureIgnoreCase; break; 21 | case StringComparison.InvariantCulture: comparer = StringComparer.InvariantCulture; break; 22 | case StringComparison.InvariantCultureIgnoreCase: comparer = StringComparer.InvariantCultureIgnoreCase; break; 23 | case StringComparison.Ordinal: comparer = StringComparer.Ordinal; break; 24 | case StringComparison.OrdinalIgnoreCase: comparer = StringComparer.OrdinalIgnoreCase; break; 25 | default: throw new ArgumentOutOfRangeException(nameof(stringComparison)); 26 | } 27 | } 28 | 29 | public ComboBoxValueComparer( IComparer stringComparer ) 30 | { 31 | comparer = stringComparer ?? throw new ArgumentNullException(nameof(stringComparer)); 32 | } 33 | 34 | public override int Compare( ComboBoxValue value1, ComboBoxValue value2 ) 35 | { 36 | if (value1 == null) { 37 | throw new ArgumentNullException(nameof(value1)); 38 | } 39 | if (value2 == null) { 40 | throw new ArgumentNullException(nameof(value2)); 41 | } 42 | 43 | return comparer.Compare(value1.DisplayString, value2.DisplayString); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /JuisCheck/ContextMenuHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Windows.Controls; 4 | 5 | namespace JuisCheck 6 | { 7 | public static class ContextMenuHelper 8 | { 9 | public static UIElement GetPlacementTarget(object o) 10 | { 11 | if (o == null) { 12 | throw new ArgumentNullException(nameof(o)); 13 | } 14 | 15 | if (o is DependencyObject element) { 16 | while (element != null) { 17 | if (element is ContextMenu contextMenu) { 18 | return contextMenu.PlacementTarget; 19 | } 20 | element = LogicalTreeHelper.GetParent(element); 21 | } 22 | } 23 | 24 | return null; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /JuisCheck/DectDeviceDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using Muon.Dotnet.Extensions; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Linq; 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Input; 14 | 15 | namespace JuisCheck 16 | { 17 | /// 18 | /// Interaction logic for DectDeviceDialog.xaml 19 | /// 20 | public sealed partial class DectDeviceDialog : Window 21 | { 22 | private readonly DectDevice origDevice; 23 | 24 | public DectDevice DeviceData { get; private set; } 25 | public int SelectedIndex { get; set; } // Dummy for ComboBox SelectedIndex validation 26 | 27 | public List CountryValues { get; private set; } 28 | public List DectBaseValues { get; private set; } 29 | public List LanguageValues { get; private set; } 30 | public List OEMValues { get; private set; } 31 | 32 | public DectDeviceDialog( DectDevice device ) 33 | { 34 | origDevice = device ?? throw new ArgumentNullException(nameof(device)); 35 | DeviceData = new DectDevice(device); 36 | 37 | InitComboBoxValues(device); 38 | InitializeComponent(); 39 | DataContext = this; 40 | } 41 | 42 | private void InitComboBoxValues(DectDevice device) 43 | { 44 | CountryValues = Device.GetCountryValues().AppendMissingAsUnknown(device.Country); 45 | LanguageValues = Device.GetLanguageValues().AppendMissingAsUnknown(device.Language); 46 | OEMValues = Device.GetOemValues().AppendMissingAsUnknown(device.OEM); 47 | 48 | DectBaseValues = new List(); 49 | foreach (JuisDevice baseDevice in App.GetMainWindow().Devices.Where(d => d is JuisDevice)) { 50 | DectBaseValues.Add(new ComboBoxValue(baseDevice.ID, baseDevice.DeviceName)); 51 | } 52 | DectBaseValues.Add(new ComboBoxValue(DectDevice.predefinedDectBaseID, DectDevice.GetPredefinedDectBaseText())); 53 | DectBaseValues.Sort(new ComboBoxValueComparer(new NaturalStringComparer(App.defaultDisplayStringComparison))); 54 | DectBaseValues.AppendMissingAsUnknown(device.DectBase); 55 | } 56 | 57 | // Routed command: CmdOk 58 | 59 | public static readonly RoutedCommand CmdOK = new RoutedCommand(); 60 | 61 | private void CmdOK_CanExecute( object sender, CanExecuteRoutedEventArgs evt ) 62 | { 63 | evt.CanExecute = !this.GetTreeHasError(true, true); 64 | } 65 | 66 | private void CmdOK_Executed( object sender, ExecutedRoutedEventArgs evt ) 67 | { 68 | DeviceData.TrimStrings(); 69 | origDevice.CopyFrom(DeviceData); 70 | 71 | DialogResult = true; 72 | } 73 | 74 | // Event: TextBox_GotFocus 75 | 76 | private void TextBox_GotFocus_Handler( object sender, RoutedEventArgs evt ) 77 | { 78 | if (sender is TextBox textBox) { 79 | textBox.SelectAll(); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /JuisCheck/DeviceCollection.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections; 9 | using System.Collections.ObjectModel; 10 | using System.Collections.Specialized; 11 | using System.ComponentModel; 12 | using System.Linq; 13 | using System.Runtime.CompilerServices; 14 | using System.Windows.Threading; 15 | 16 | namespace JuisCheck 17 | { 18 | public class DeviceCollection : ObservableCollection 19 | { 20 | public CollectionSettings Settings { get; protected set; } = new CollectionSettings(); 21 | 22 | private string _FileName = null; 23 | public string FileName 24 | { 25 | get => _FileName; 26 | protected set { 27 | if (_FileName != value) { 28 | _FileName = value; 29 | NotifyPropertyChanged(); 30 | } 31 | 32 | } 33 | } 34 | 35 | private bool _IsModified = false; 36 | public bool IsModified 37 | { 38 | get => _IsModified; 39 | protected set { 40 | if (_IsModified != value) { 41 | _IsModified = value; 42 | NotifyPropertyChanged(); 43 | } 44 | } 45 | } 46 | 47 | /****************/ 48 | /* Constructors */ 49 | /****************/ 50 | 51 | public DeviceCollection () : base() 52 | { 53 | CollectionChanged += CollectionChanged_Handler; 54 | Settings.PropertyChanged += Settings_PropertyChanged_Handler; 55 | } 56 | 57 | /*****************/ 58 | /* Other methods */ 59 | /*****************/ 60 | 61 | protected void AddItemPropertyChangedHandlers() 62 | { 63 | AddItemPropertyChangedHandlers((IList)Items); 64 | } 65 | 66 | protected void AddItemPropertyChangedHandlers( IList devices ) 67 | { 68 | if (devices == null) { 69 | throw new ArgumentNullException(nameof(devices)); 70 | } 71 | 72 | foreach (Device device in devices) { 73 | device.PropertyChanged += Item_PropertyChanged_Handler; 74 | } 75 | } 76 | 77 | public void Empty() 78 | { 79 | Clear(); 80 | 81 | FileName = null; 82 | IsModified = false; 83 | } 84 | 85 | public Device FindByID( string id ) 86 | { 87 | return this.FirstOrDefault( d => d.ID == id ); 88 | } 89 | 90 | public void Load( string fileName ) 91 | { 92 | FileName = fileName; 93 | 94 | bool isModified = XML.JCData.LoadFromFile(fileName, this); 95 | foreach (Device device in this) { 96 | if (string.IsNullOrWhiteSpace(device.ID)) { 97 | device.ID = Guid.NewGuid().ToString(); 98 | isModified = true; 99 | } 100 | } 101 | Settings.NotifySettingsProperties(); 102 | 103 | IsModified = isModified; 104 | } 105 | 106 | protected void RemoveItemPropertyChangedHandlers( IList devices ) 107 | { 108 | if (devices == null) { 109 | throw new ArgumentNullException(nameof(devices)); 110 | } 111 | 112 | foreach (Device device in devices) { 113 | device.PropertyChanged -= Item_PropertyChanged_Handler; 114 | } 115 | } 116 | 117 | public void Save( string fileName = null ) 118 | { 119 | FileName = fileName ?? FileName; 120 | XML.JCData.SaveToFile(FileName, this); 121 | 122 | IsModified = false; 123 | } 124 | 125 | // Event handler: CollectionChanged 126 | 127 | private void CollectionChanged_Handler( object sender, NotifyCollectionChangedEventArgs evt ) 128 | { 129 | switch (evt.Action) { 130 | case NotifyCollectionChangedAction.Add: 131 | AddItemPropertyChangedHandlers(evt.NewItems); 132 | IsModified = true; 133 | break; 134 | 135 | case NotifyCollectionChangedAction.Move: 136 | IsModified = true; 137 | break; 138 | 139 | case NotifyCollectionChangedAction.Remove: 140 | RemoveItemPropertyChangedHandlers(evt.OldItems); 141 | IsModified = true; 142 | break; 143 | 144 | case NotifyCollectionChangedAction.Replace: 145 | RemoveItemPropertyChangedHandlers(evt.OldItems); 146 | AddItemPropertyChangedHandlers(evt.NewItems); 147 | IsModified = true; 148 | break; 149 | 150 | case NotifyCollectionChangedAction.Reset: 151 | IsModified = true; 152 | break; 153 | } 154 | } 155 | 156 | // Event handler: Item_PropertyChanged 157 | 158 | private void Item_PropertyChanged_Handler( object sender, PropertyChangedEventArgs evt ) 159 | { 160 | if (evt.PropertyName == nameof(Device.DeviceName)) { 161 | foreach (Device device in this) { 162 | device.NotifyDeviceNameChanged(((Device)sender).ID); 163 | } 164 | } 165 | 166 | if (evt.PropertyName != nameof(Device.IsSelected)) { 167 | IsModified = true; 168 | } 169 | } 170 | 171 | // Event handler: Settings_PropertyChanged 172 | 173 | private void Settings_PropertyChanged_Handler( object sender, PropertyChangedEventArgs evt ) 174 | { 175 | IsModified = true; 176 | } 177 | 178 | // Event source: CollectionPropertyChanged 179 | // 180 | // Note: we cannot use the INotifyPropertyChanged implementation from the 181 | // ObservableCollection class because PropertyChanged is protected. 182 | 183 | public event PropertyChangedEventHandler CollectionPropertyChanged; 184 | 185 | protected void NotifyPropertyChanged( [CallerMemberName] string propertyName = null ) 186 | { 187 | CollectionPropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /JuisCheck/DeviceComparer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | using System.ComponentModel; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck 14 | { 15 | public sealed class DeviceComparer : Comparer 16 | { 17 | private readonly DeviceProperty sortProperty; 18 | private readonly ListSortDirection sortDirection; 19 | private readonly NaturalStringComparer stringComparer; 20 | 21 | public DeviceComparer( DeviceProperty property, ListSortDirection direction ) 22 | { 23 | if (!Enum.IsDefined(typeof(DeviceProperty), property)) { 24 | throw new ArgumentOutOfRangeException(nameof(property)); 25 | } 26 | if (!Enum.IsDefined(typeof(ListSortDirection), direction)) { 27 | throw new ArgumentOutOfRangeException(nameof(direction)); 28 | } 29 | 30 | sortProperty = property; 31 | sortDirection = direction; 32 | stringComparer = new NaturalStringComparer(App.defaultDisplayStringComparison); 33 | } 34 | 35 | public override int Compare( Device device1, Device device2 ) 36 | { 37 | if (device1 == null) { 38 | throw new ArgumentNullException(nameof(device1)); 39 | } 40 | if (device2 == null) { 41 | throw new ArgumentNullException(nameof(device2)); 42 | } 43 | 44 | int result; 45 | 46 | switch (sortProperty) { 47 | case DeviceProperty.DeviceAddressStr: result = stringComparer.Compare(device1.DeviceAddressStr, device2.DeviceAddressStr); break; 48 | case DeviceProperty.DeviceName: result = stringComparer.Compare(device1.DeviceName, device2.DeviceName); break; 49 | case DeviceProperty.FirmwareStr: result = stringComparer.Compare(device1.FirmwareStr, device2.FirmwareStr); break; 50 | case DeviceProperty.ProductName: result = stringComparer.Compare(device1.ProductName, device2.ProductName); break; 51 | default: throw new ApplicationException("Unsupported comparison"); 52 | } 53 | 54 | return sortDirection == ListSortDirection.Ascending ? result : -result; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /JuisCheck/DeviceProperty.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | namespace JuisCheck 8 | { 9 | public enum DeviceProperty 10 | { 11 | DeviceAddressStr, 12 | DeviceName, 13 | FirmwareStr, 14 | ProductName 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /JuisCheck/DownloadDialog.xaml: -------------------------------------------------------------------------------- 1 |  13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 24 | 25 | 25 | 26 | 16 | 19 | 24 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /JuisCheck/MessageBoxEx.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Media; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using System.Windows.Documents; 7 | using System.Windows.Interop; 8 | using System.Windows.Input; 9 | using System.Windows.Media.Imaging; 10 | 11 | #pragma warning disable CA1819 // Properties should not return arrays 12 | 13 | namespace JuisCheck 14 | { 15 | public enum MessageBoxExImage 16 | { 17 | None = 0, 18 | Question = 1, 19 | Information = 2, 20 | Warning = 3, 21 | Error = 4 22 | } 23 | 24 | public sealed class MessageBoxExParams 25 | { 26 | public string[] ButtonText { get; set; } = { "OK" }; 27 | public string CaptionText { get; set; } = null; 28 | public string CheckboxText { get; set; } = null; 29 | public bool CheckboxValue { get; set; } = false; 30 | public int DefaultButton { get; set; } = -1; 31 | public MessageBoxExImage Image { get; set; } = MessageBoxExImage.None; 32 | public string MessageText { get; set; } = null; 33 | public Window Owner { get; set; } = null; 34 | public SystemSound Sound { get; set; } = null; 35 | } 36 | 37 | public sealed partial class MessageBoxEx : Window 38 | { 39 | // 40 | // Static members 41 | // 42 | 43 | public static int Show(MessageBoxExParams msgParams) 44 | { 45 | return Show(msgParams, false, out bool _); 46 | } 47 | 48 | public static int Show(MessageBoxExParams msgParams, out bool cbValue) 49 | { 50 | return Show(msgParams, true, out cbValue); 51 | } 52 | 53 | private static int Show(MessageBoxExParams msgParams, bool cbShow, out bool cbValue) 54 | { 55 | if (msgParams == null) { 56 | throw new ArgumentNullException(nameof(msgParams)); 57 | } 58 | 59 | if (msgParams.MessageText == null) { 60 | throw new ArgumentException($"{nameof(msgParams)}.{nameof(msgParams.MessageText)}"); 61 | } 62 | if (msgParams.CheckboxText == null && cbShow) { 63 | throw new ArgumentException($"{nameof(msgParams)}.{nameof(msgParams.CheckboxText)}"); 64 | } 65 | if (msgParams.ButtonText == null) { 66 | throw new ArgumentException($"{nameof(msgParams)}: {nameof(msgParams.ButtonText)}"); 67 | } 68 | if (msgParams.ButtonText.Length == 0) { 69 | throw new ArgumentException($"{nameof(msgParams)}.{nameof(msgParams.ButtonText)}"); 70 | } 71 | 72 | if (msgParams.Sound != null) { 73 | msgParams.Sound.Play(); 74 | } 75 | 76 | MessageBoxEx msgBox = new MessageBoxEx() { 77 | Title = msgParams.CaptionText ?? string.Empty 78 | }; 79 | 80 | if (msgParams.Owner != null) { 81 | try { 82 | msgBox.Owner = msgParams.Owner; 83 | msgBox.WindowStartupLocation = WindowStartupLocation.CenterOwner; 84 | } 85 | catch (InvalidOperationException) { 86 | msgBox.WindowStartupLocation = WindowStartupLocation.CenterScreen; 87 | } 88 | } else { 89 | msgBox.WindowStartupLocation = WindowStartupLocation.CenterScreen; 90 | } 91 | 92 | msgBox.SetButtons(msgParams.ButtonText); 93 | msgBox.SetCheckbox(cbShow, msgParams.CheckboxText, msgParams.CheckboxValue); 94 | msgBox.SetImage(msgParams.Image); 95 | msgBox.SetMessage(msgParams.MessageText); 96 | msgBox.ShowDialog(); 97 | 98 | cbValue = (bool)msgBox.cbCheckbox.IsChecked; 99 | 100 | return msgBox.result; 101 | } 102 | 103 | // 104 | // Other members 105 | // 106 | 107 | private int result = -1; 108 | 109 | private MessageBoxEx() 110 | { 111 | InitializeComponent(); 112 | } 113 | 114 | private void AddButton(string text, int result) 115 | { 116 | Button button = new Button { 117 | Content = text, 118 | Tag = result 119 | }; 120 | button.Click += Button_Click_Handler; 121 | 122 | ugButtons.Children.Add(button); 123 | ugButtons.Columns++; 124 | } 125 | 126 | private void SetButtons(string[] buttonText) 127 | { 128 | for (int i = 0; i < buttonText.Length; i++) { 129 | AddButton(buttonText[i], i); 130 | } 131 | } 132 | 133 | private void SetCheckbox(bool cbShow, string cbText, bool cbValue) 134 | { 135 | dpCheckbox.Visibility = cbShow ? Visibility.Visible : Visibility.Collapsed; 136 | 137 | if (cbShow) { 138 | cbCheckbox.IsChecked = cbValue; 139 | 140 | foreach (string line in cbText.Split('\n')) { 141 | tbkCheckboxText.Inlines.Add(new Run(line)); 142 | tbkCheckboxText.Inlines.Add(new LineBreak()); 143 | } 144 | } 145 | } 146 | 147 | private void SetImage(MessageBoxExImage image) 148 | { 149 | Icon icon; 150 | 151 | switch (image) { 152 | case MessageBoxExImage.Error: icon = SystemIcons.Error; break; 153 | case MessageBoxExImage.Information: icon = SystemIcons.Information; break; 154 | case MessageBoxExImage.None: icon = null; break; 155 | case MessageBoxExImage.Question: icon = SystemIcons.Question; break; 156 | case MessageBoxExImage.Warning: icon = SystemIcons.Warning; break; 157 | 158 | default: 159 | throw new ArgumentOutOfRangeException(nameof(image)); 160 | } 161 | 162 | if (icon == null) { 163 | imgMessageIcon.Visibility = Visibility.Collapsed; 164 | } else { 165 | imgMessageIcon.Source = Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); 166 | imgMessageIcon.Visibility = Visibility.Visible; 167 | } 168 | } 169 | 170 | private void SetMessage(string text) 171 | { 172 | foreach (string line in text.Split('\n')) { 173 | tbkMessageText.Inlines.Add(new Run(line)); 174 | tbkMessageText.Inlines.Add(new LineBreak()); 175 | } 176 | } 177 | 178 | // 179 | // Event handlers 180 | // 181 | 182 | private void Button_Click_Handler(object sender, RoutedEventArgs evt) 183 | { 184 | result = (int)(sender as Button).Tag; 185 | Close(); 186 | } 187 | 188 | private void KeyUp_Handler(object sender, KeyEventArgs evt) 189 | { 190 | if (evt.Key == Key.Escape) { 191 | Close(); 192 | } 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /JuisCheck/MultiSelectDataGrid.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System.Windows.Controls; 8 | 9 | namespace JuisCheck 10 | { 11 | public class MultiSelectDataGrid : DataGrid 12 | { 13 | public MultiSelectDataGrid() : base() 14 | { 15 | CanSelectMultipleItems = true; 16 | EnableColumnVirtualization = false; 17 | EnableRowVirtualization = false; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JuisCheck/NaturalStringComparer.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Collections.Generic; 9 | 10 | namespace JuisCheck 11 | { 12 | public class NaturalStringComparer : Comparer 13 | { 14 | private enum TokenType 15 | { 16 | Nothing, 17 | Numerical, 18 | String, 19 | End 20 | } 21 | 22 | private sealed class StringParser 23 | { 24 | private string mSource; 25 | private int mLength; 26 | private int mCurrentIndex; 27 | private char mCurrentChar; 28 | 29 | internal void Init( string str ) 30 | { 31 | mSource = str ?? string.Empty; 32 | mLength = mSource.Length; 33 | mCurrentIndex = -1; 34 | 35 | TokenType = TokenType.Nothing; 36 | NumericalValue = 0; 37 | StringValue = null; 38 | 39 | NextChar(); 40 | } 41 | 42 | private void NextChar() 43 | { 44 | mCurrentIndex++; 45 | mCurrentChar = mCurrentIndex >= mLength ? '\0' : mSource[mCurrentIndex]; 46 | } 47 | 48 | internal void NextToken() 49 | { 50 | NumericalValue = 0; 51 | StringValue = null; 52 | 53 | do { 54 | // End of string 55 | if (mCurrentChar == '\0') { 56 | TokenType = TokenType.End; 57 | return; 58 | } 59 | 60 | // Numerical token 61 | if (char.IsDigit(mCurrentChar)) { 62 | int startIndex = mCurrentIndex; 63 | 64 | do { 65 | NextChar(); 66 | } 67 | while (char.IsDigit(mCurrentChar)); 68 | 69 | StringValue = mSource.Substring(startIndex, mCurrentIndex - startIndex); 70 | TokenType = TokenType.String; 71 | 72 | if (decimal.TryParse(StringValue, out decimal value)) { 73 | NumericalValue = value; 74 | TokenType = TokenType.Numerical; 75 | } 76 | 77 | return; 78 | } 79 | 80 | // String token 81 | if (char.IsLetter(mCurrentChar)) { 82 | int startIndex = mCurrentIndex; 83 | 84 | do { 85 | NextChar(); 86 | } 87 | while (char.IsLetter(mCurrentChar)); 88 | 89 | StringValue = mSource.Substring(startIndex, mCurrentIndex - startIndex); 90 | TokenType = TokenType.String; 91 | return; 92 | } 93 | 94 | NextChar(); 95 | } 96 | while (true); 97 | } 98 | 99 | internal decimal NumericalValue { get; private set; } = 0; 100 | internal string StringValue { get; private set; } = null; 101 | internal TokenType TokenType { get; private set; } = TokenType.Nothing; 102 | } 103 | 104 | private readonly StringParser mParser1; 105 | private readonly StringParser mParser2; 106 | private readonly StringComparison mStringComparison; 107 | 108 | public NaturalStringComparer( StringComparison stringComparison ) 109 | { 110 | mParser1 = new StringParser(); 111 | mParser2 = new StringParser(); 112 | mStringComparison = stringComparison; 113 | } 114 | 115 | public override int Compare( string str1, string str2 ) 116 | { 117 | int result; 118 | 119 | mParser1.Init(str1); 120 | mParser2.Init(str2); 121 | 122 | do { 123 | mParser1.NextToken(); 124 | mParser2.NextToken(); 125 | 126 | if (mParser1.TokenType == TokenType.Numerical && mParser2.TokenType == TokenType.Numerical) { 127 | result = decimal.Compare(mParser1.NumericalValue, mParser2.NumericalValue); 128 | if (result != 0) { 129 | return result; 130 | } 131 | } 132 | 133 | result = string.Compare(mParser1.StringValue, mParser2.StringValue, mStringComparison); 134 | if (result != 0) { 135 | return result; 136 | } 137 | } 138 | while (mParser1.TokenType != TokenType.End || mParser2.TokenType != TokenType.End); 139 | 140 | return 0; 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /JuisCheck/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("JuisCheck for Windows")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("JuisCheck")] 15 | [assembly: AssemblyCopyright("Copyright © Roger Hünen")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("2.1.3.0")] 55 | [assembly: AssemblyFileVersion("2.1.3.0")] 56 | [assembly: NeutralResourcesLanguage("en")] 57 | -------------------------------------------------------------------------------- /JuisCheck/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace JuisCheck.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JuisCheck.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /JuisCheck/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /JuisCheck/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | False 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | False 19 | 20 | 21 | True 22 | 23 | 24 | True 25 | 26 | 27 | True 28 | 29 | 30 | False 31 | 32 | 33 | False 34 | 35 | 36 | False 37 | 38 | 39 | True 40 | 41 | 42 | True 43 | 44 | 45 | False 46 | 47 | 48 | True 49 | 50 | 51 | True 52 | 53 | 54 | -1 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | False 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | NaN 73 | 74 | 75 | NaN 76 | 77 | 78 | False 79 | 80 | 81 | True 82 | 83 | 84 | NaN 85 | 86 | 87 | NaN 88 | 89 | 90 | 91 | 92 | 93 | 10 94 | 95 | 96 | True 97 | 98 | 99 | auto 100 | 101 | 102 | -------------------------------------------------------------------------------- /JuisCheck/RecentFileButton.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using System.Windows.Media; 4 | 5 | namespace JuisCheck 6 | { 7 | public class RecentFileButton : Button 8 | { 9 | static RecentFileButton() 10 | { 11 | DefaultStyleKeyProperty.OverrideMetadata(typeof(RecentFileButton), new FrameworkPropertyMetadata(typeof(RecentFileButton))); 12 | } 13 | 14 | // DependencyProperty: DirPath 15 | 16 | public static readonly DependencyProperty DirPathProperty = DependencyProperty.Register("DirPath", typeof(string), typeof(RecentFileButton)); 17 | 18 | public string DirPath 19 | { 20 | get => (string)GetValue(DirPathProperty); 21 | set => SetValue(DirPathProperty, value); 22 | } 23 | 24 | // DependencyProperty: DirPathFontSize 25 | 26 | public static readonly DependencyProperty DirPathFontSizeProperty = DependencyProperty.Register("DirPathFontSize", typeof(double), typeof(RecentFileButton)); 27 | 28 | public double DirPathFontSize 29 | { 30 | get => (double)GetValue(DirPathFontSizeProperty); 31 | set => SetValue(DirPathFontSizeProperty, value); 32 | } 33 | 34 | // DependencyProperty: DirPathFontWeight 35 | 36 | public static readonly DependencyProperty DirPathFontWeightProperty = DependencyProperty.Register("DirPathFontWeight", typeof(FontWeight), typeof(RecentFileButton)); 37 | 38 | public FontWeight DirPathFontWeight 39 | { 40 | get => (FontWeight)GetValue(DirPathFontWeightProperty); 41 | set => SetValue(DirPathFontWeightProperty, value); 42 | } 43 | 44 | // DependencyProperty: DirPathForeground 45 | 46 | public static readonly DependencyProperty DirPathForegroundProperty = DependencyProperty.Register("DirPathForeground", typeof(Brush), typeof(RecentFileButton)); 47 | 48 | public Brush DirPathForeground 49 | { 50 | get => (Brush)GetValue(DirPathForegroundProperty); 51 | set => SetValue(DirPathForegroundProperty, value); 52 | } 53 | 54 | // DependencyProperty: DirPathMargin 55 | 56 | public static readonly DependencyProperty DirPathMarginProperty = DependencyProperty.Register("DirPathMargin", typeof(Thickness), typeof(RecentFileButton)); 57 | 58 | public Thickness DirPathMargin 59 | { 60 | get => (Thickness)GetValue(DirPathMarginProperty); 61 | set => SetValue(DirPathMarginProperty, value); 62 | } 63 | 64 | // DependencyProperty: FileName 65 | 66 | public static readonly DependencyProperty FileNameProperty = DependencyProperty.Register("FileName", typeof(string), typeof(RecentFileButton)); 67 | 68 | public string FileName 69 | { 70 | get => (string)GetValue(FileNameProperty); 71 | set => SetValue(FileNameProperty, value); 72 | } 73 | 74 | // DependencyProperty: FileNameFontSize 75 | 76 | public static readonly DependencyProperty FileNameFontSizeProperty = DependencyProperty.Register("FileNameFontSize", typeof(double), typeof(RecentFileButton)); 77 | 78 | public double FileNameFontSize 79 | { 80 | get => (double)GetValue(FileNameFontSizeProperty); 81 | set => SetValue(FileNameFontSizeProperty, value); 82 | } 83 | 84 | // DependencyProperty: FileNameFontWeight 85 | 86 | public static readonly DependencyProperty FileNameFontWeightProperty = DependencyProperty.Register("FileNameFontWeight", typeof(FontWeight), typeof(RecentFileButton)); 87 | 88 | public FontWeight FileNameFontWeight 89 | { 90 | get => (FontWeight)GetValue(FileNameFontWeightProperty); 91 | set => SetValue(FileNameFontWeightProperty, value); 92 | } 93 | 94 | // DependencyProperty: FileNameForeground 95 | 96 | public static readonly DependencyProperty FileNameForegroundProperty = DependencyProperty.Register("FileNameForeground", typeof(Brush), typeof(RecentFileButton)); 97 | 98 | public Brush FileNameForeground 99 | { 100 | get => (Brush)GetValue(FileNameForegroundProperty); 101 | set => SetValue(FileNameForegroundProperty, value); 102 | } 103 | 104 | // DependencyProperty: FileNameMargin 105 | 106 | public static readonly DependencyProperty FileNameMarginProperty = DependencyProperty.Register("FileNameMargin", typeof(Thickness), typeof(RecentFileButton)); 107 | 108 | public Thickness FileNameMargin 109 | { 110 | get => (Thickness)GetValue(FileNameMarginProperty); 111 | set => SetValue(FileNameMarginProperty, value); 112 | } 113 | 114 | // DependencyProperty: Image 115 | 116 | public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(ImageSource), typeof(RecentFileButton)); 117 | 118 | public ImageSource Image 119 | { 120 | get => (ImageSource)GetValue(ImageProperty); 121 | set => SetValue(ImageProperty, value); 122 | } 123 | 124 | // DependencyProperty: ImageHeight 125 | 126 | public static readonly DependencyProperty ImageHeightProperty = DependencyProperty.Register("ImageHeight", typeof(double), typeof(RecentFileButton)); 127 | 128 | public double ImageHeight 129 | { 130 | get => (double)GetValue(ImageHeightProperty); 131 | set => SetValue(ImageHeightProperty, value); 132 | } 133 | 134 | // DependencyProperty: ImageMargin 135 | 136 | public static readonly DependencyProperty ImageMarginProperty = DependencyProperty.Register("ImageMargin", typeof(Thickness), typeof(RecentFileButton)); 137 | 138 | public Thickness ImageMargin 139 | { 140 | get => (Thickness)GetValue(ImageMarginProperty); 141 | set => SetValue(ImageMarginProperty, value); 142 | } 143 | 144 | // DependencyProperty: ImageWidth 145 | 146 | public static readonly DependencyProperty ImageWidthProperty = DependencyProperty.Register("ImageWidth", typeof(double), typeof(RecentFileButton)); 147 | 148 | public double ImageWidth 149 | { 150 | get => (double)GetValue(ImageWidthProperty); 151 | set => SetValue(ImageWidthProperty, value); 152 | } 153 | 154 | // DependencyProperty: MouseOverBackground 155 | 156 | public static readonly DependencyProperty MouseOverBackgroundProperty = DependencyProperty.Register("MouseOverBackground", typeof(Brush), typeof(RecentFileButton)); 157 | 158 | public Brush MouseOverBackground 159 | { 160 | get => (Brush)GetValue(MouseOverBackgroundProperty); 161 | set => SetValue(MouseOverBackgroundProperty, value); 162 | } 163 | 164 | // DependencyProperty: MouseOverBorderBrush 165 | 166 | public static readonly DependencyProperty MouseOverBorderBrushProperty = DependencyProperty.Register("MouseOverBorderBrush", typeof(Brush), typeof(RecentFileButton)); 167 | 168 | public Brush MouseOverBorderBrush 169 | { 170 | get => (Brush)GetValue(MouseOverBorderBrushProperty); 171 | set => SetValue(MouseOverBorderBrushProperty, value); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /JuisCheck/RecentItemsCollection.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System.Collections.Generic; 8 | 9 | namespace JuisCheck 10 | { 11 | public class RecentItemsCollection : List 12 | { 13 | /**********************/ 14 | /* Class constructors */ 15 | /**********************/ 16 | 17 | public RecentItemsCollection() 18 | { 19 | } 20 | 21 | public RecentItemsCollection( IEnumerable items ) : base(items) 22 | { 23 | } 24 | 25 | /*****************/ 26 | /* Other methods */ 27 | /*****************/ 28 | 29 | public List GetMaxItems( int maxCount ) 30 | { 31 | return GetRange(0, maxCount < Count ? maxCount : Count); 32 | } 33 | 34 | public void InsertRecent( string item ) 35 | { 36 | Remove(item); 37 | Insert(0, item); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /JuisCheck/Resources/Converters/BoolToVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows; 10 | using System.Windows.Data; 11 | 12 | using JuisCheck.Lang; 13 | 14 | namespace JuisCheck.Resources.Converters 15 | { 16 | [ValueConversion(sourceType: typeof(bool), targetType: typeof(Visibility))] 17 | public class BoolToVisibilityConverter : IValueConverter 18 | { 19 | public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) 20 | { 21 | if (targetType != typeof(Visibility)) { 22 | throw new InvalidOperationException("Invalid target type"); 23 | } 24 | if (!(value is bool)) { 25 | throw new InvalidOperationException("Invalid value type"); 26 | } 27 | 28 | return (bool)value ? Visibility.Visible : Visibility.Collapsed; 29 | } 30 | 31 | public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) 32 | { 33 | return (Visibility)value == Visibility.Visible; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /JuisCheck/Resources/Converters/InverseBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows.Data; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck.Resources.Converters 14 | { 15 | [ValueConversion(sourceType: typeof(bool), targetType: typeof(bool))] 16 | public class InverseBooleanConverter : IValueConverter 17 | { 18 | public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) 19 | { 20 | if (targetType != typeof(bool)) { 21 | throw new InvalidOperationException("Invalid target type"); 22 | } 23 | if (!(value is bool)) { 24 | throw new InvalidOperationException("Invalid value type"); 25 | } 26 | 27 | return !(bool)value; 28 | } 29 | 30 | public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) 31 | { 32 | throw new NotImplementedException(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /JuisCheck/Resources/Converters/NullableDateTimeToStringConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows.Data; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck.Resources.Converters 14 | { 15 | [ValueConversion(sourceType: typeof(DateTime?), targetType: typeof(string))] 16 | public class NullableDateTimeToStringConverter : IValueConverter 17 | { 18 | public object Convert( object value, Type targetType, object parameter, CultureInfo culture ) 19 | { 20 | if (targetType != typeof(string)) { 21 | throw new InvalidOperationException("Invalid target type"); 22 | } 23 | if (value == null) { 24 | return string.Empty; 25 | } 26 | if (!(value is DateTime)) { 27 | throw new InvalidOperationException("Invalid value type"); 28 | } 29 | 30 | return ((DateTime)value).ToString("G", CultureInfo.CurrentCulture); 31 | } 32 | 33 | public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture ) 34 | { 35 | throw new NotImplementedException(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-application-exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-application-exit.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-dialog-warning.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-document-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-document-close.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-document-open-recent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-document-open-recent.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-document-open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-document-open.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-document-save-as.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-document-save-as.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-document-save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-document-save.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-help-about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-help-about.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/16x16/oxygen-preferences-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/16x16/oxygen-preferences-system.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-dialog-information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-dialog-information.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-dialog-ok-apply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-dialog-ok-apply.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-document-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-document-close.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-document-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-document-edit.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-document-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-document-new.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-document-open-recent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-document-open-recent.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-download.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-edit-clear-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-edit-clear-list.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-edit-copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-edit-copy.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-edit-paste.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-edit-paste.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-edit-select-all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-edit-select-all.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-run-build-clean.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-run-build-clean.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/32x32/oxygen-system-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/32x32/oxygen-system-search.png -------------------------------------------------------------------------------- /JuisCheck/Resources/Images/48x48/JuisCheck.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/JuisCheck/Resources/Images/48x48/JuisCheck.ico -------------------------------------------------------------------------------- /JuisCheck/Resources/ValidationRules/ComboBoxValueSelectedRule.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows.Controls; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck.Resources.ValidationRules 14 | { 15 | public class ComboBoxValueSelectedRule : ValidationRule 16 | { 17 | public override ValidationResult Validate( object value, CultureInfo cultureInfo ) 18 | { 19 | if (!(value is int intval)) { 20 | throw new InvalidOperationException("Invalid value type"); 21 | } 22 | 23 | if (intval < 0) { 24 | return new ValidationResult(false, JCstring.ValidationErrorNoValueSelected); 25 | } 26 | 27 | return ValidationResult.ValidResult; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /JuisCheck/Resources/ValidationRules/StringInt32RangeRule.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows.Controls; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck.Resources.ValidationRules 14 | { 15 | public class StringInt32RangeRule : ValidationRule 16 | { 17 | public int Min { get; set; } = int.MinValue; 18 | public int Max { get; set; } = int.MaxValue; 19 | 20 | public override ValidationResult Validate( object value, CultureInfo cultureInfo ) 21 | { 22 | if (!(value is string strval)) { 23 | throw new InvalidOperationException("Invalid value type"); 24 | } 25 | strval = strval.Trim(); 26 | 27 | if (strval.Length == 0) { 28 | return new ValidationResult(false, JCstring.ValidationErrorEmptyOrWhiteSpace); 29 | } 30 | 31 | if (!int.TryParse((string)value, out int intval)) { 32 | return new ValidationResult(false, JCstring.ValidationErrorInvalidCharacters); 33 | } 34 | 35 | if (intval < Min || intval > Max) { 36 | return new ValidationResult(false, string.Format(CultureInfo.CurrentCulture, JCstring.ValidationErrorValueOutOfRange, Min, Max)); 37 | } 38 | 39 | return ValidationResult.ValidResult; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /JuisCheck/Resources/ValidationRules/StringNotNullOrWhiteSpaceRule.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System; 8 | using System.Globalization; 9 | using System.Windows.Controls; 10 | 11 | using JuisCheck.Lang; 12 | 13 | namespace JuisCheck.Resources.ValidationRules 14 | { 15 | public class StringNotNullOrWhiteSpaceRule : ValidationRule 16 | { 17 | public override ValidationResult Validate( object value, CultureInfo cultureInfo ) 18 | { 19 | if (!(value is string strval)) { 20 | throw new InvalidOperationException("Invalid value type"); 21 | } 22 | 23 | if (string.IsNullOrWhiteSpace(strval)) { 24 | return new ValidationResult(false, JCstring.ValidationErrorEmptyOrWhiteSpace); 25 | } 26 | 27 | return ValidationResult.ValidResult; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/BaseStyles.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 17 | 18 | 20 | 21 | 32 | 33 | 36 | 37 | 41 | 42 | 43 | 46 | 47 | 56 | 57 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/ColorsAndBrushes.xaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/Converters.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/MainWindowBackstageStyles.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 33 | 34 | 59 | 60 | 64 | 65 | 68 | 69 | 79 | 80 | 86 | 87 | 93 | 94 | 97 | 98 | 101 | 102 | 103 | 104 | 110 | 111 | 116 | 117 | 118 | 119 | 125 | 126 | 131 | 132 | 136 | 137 | 141 | 142 | 146 | 147 | 150 | 151 | 154 | 155 | 158 | 159 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/MainWindowDataGridTemplates.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/MainWindowRibbonStyles.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 22 | 23 | 27 | 28 | -------------------------------------------------------------------------------- /JuisCheck/Resources/XAML/RecentFileButtonTemplate.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 43 | 44 | 54 | 55 | 62 | 63 | 64 | 67 | 68 | 73 | 74 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC1Data.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Xml; 5 | using System.Xml.Serialization; 6 | 7 | namespace JuisCheck.XML 8 | { 9 | [XmlRoot("Devices")] 10 | public class JC1Data 11 | { 12 | [XmlElement("Device")] 13 | public List Devices { get; } = new List(); 14 | 15 | public static void LoadFromString( string xml, DeviceCollection devices ) 16 | { 17 | if (xml == null) { 18 | throw new ArgumentNullException(nameof(xml)); 19 | } 20 | if (devices == null) { 21 | throw new ArgumentNullException(nameof(devices)); 22 | } 23 | 24 | XmlReaderSettings xmlReaderSettings = new XmlReaderSettings() { IgnoreComments = true, IgnoreWhitespace = true }; 25 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(JC1Data)); 26 | 27 | using (XmlReader xmlReader = XmlReader.Create(new StringReader(xml), xmlReaderSettings)) { 28 | JC1Data jc1data = (JC1Data)xmlSerializer.Deserialize(xmlReader); 29 | 30 | devices.Clear(); 31 | foreach (JC1Device jc1device in jc1data.Devices) { 32 | if (jc1device.DeviceKind == JC1DeviceKind.DECT) { 33 | devices.Add(new DectDevice(jc1device)); 34 | } 35 | if (jc1device.DeviceKind == JC1DeviceKind.JUIS) { 36 | devices.Add(new JuisDevice(jc1device)); 37 | } 38 | } 39 | 40 | devices.Settings.Reset(); 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC1Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml.Serialization; 4 | 5 | namespace JuisCheck.XML 6 | { 7 | public class JC1Device 8 | { 9 | [XmlAttribute("kind")] public JC1DeviceKind DeviceKind { get; set; } = JC1DeviceKind.Unknown; 10 | 11 | [XmlElement("DeviceName")] public string DeviceName { get; set; } 12 | [XmlElement("DeviceAddress")] public string DeviceAddress { get; set; } 13 | [XmlElement("ProductName")] public string ProductName { get; set; } 14 | [XmlElement("HardwareMajor")] public int HardwareMajor { get; set; } 15 | [XmlElement("HardwareMinor")] public int HardwareMinor { get; set; } 16 | [XmlElement("SerialNumber")] public string SerialNumber { get; set; } 17 | [XmlElement("FirmwareMajor")] public int FirmwareMajor { get; set; } 18 | [XmlElement("FirmwareMinor")] public int FirmwareMinor { get; set; } 19 | [XmlElement("FirmwarePatch")] public int FirmwarePatch { get; set; } 20 | [XmlElement("FirmwareBuildNumber")] public int FirmwareBuildNumber { get; set; } 21 | [XmlElement("FirmwareBuildType")] public int FirmwareBuildType { get; set; } 22 | [XmlElement("OEM")] public string OEM { get; set; } 23 | [XmlElement("Annex")] public string Annex { get; set; } 24 | [XmlElement("Country")] public string Country { get; set; } 25 | [XmlElement("Language")] public string Language { get; set; } 26 | [XmlElement("Flag")] public List Flags { get; } = new List(); 27 | [XmlElement("BaseFritzOS")] public string BaseFritzOS { get; set; } // Not used in JuisCheck 2.x 28 | [XmlElement("UpdateAvailable")] public bool UpdateAvailable { get; set; } 29 | [XmlElement("UpdateInfo")] public string UpdateInfo { get; set; } 30 | [XmlElement("UpdateImageURL")] public string UpdateImageURL { get; set; } 31 | [XmlElement("UpdateInfoURL")] public string UpdateInfoURL { get; set; } 32 | [XmlElement("UpdateLastChecked")] public DateTime? UpdateLastChecked { get; set; } 33 | 34 | public JC1Device() 35 | { 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC1DeviceKind.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Program : JuisCheck for Windows 3 | * Copyright : Copyright (C) Roger Hünen 4 | * License : GNU General Public License version 3 (see LICENSE) 5 | */ 6 | 7 | using System.Xml.Serialization; 8 | 9 | namespace JuisCheck.XML 10 | { 11 | public enum JC1DeviceKind 12 | { 13 | [XmlEnum(Name = "Unknown")] 14 | Unknown, 15 | [XmlEnum(Name = "DECT")] 16 | DECT, 17 | [XmlEnum(Name = "JUIS")] 18 | JUIS 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC2Data.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Xml; 5 | using System.Xml.Serialization; 6 | 7 | namespace JuisCheck.XML 8 | { 9 | [XmlRoot("JuisCheck2")] 10 | public class JC2Data 11 | { 12 | public const string xmlRootElementName = "JuisCheck2"; 13 | 14 | // Note: the member order determines the order of elements in the XML output. 15 | 16 | [XmlArray("DectDevices")] public List DectDevices { get; } = new List(); 17 | [XmlArray("JuisDevices")] public List JuisDevices { get; } = new List(); 18 | [XmlArray("Settings")] public List Settings { get; } = new List(); 19 | 20 | public static void LoadFromString( string xml, DeviceCollection devices ) 21 | { 22 | if (xml == null) { 23 | throw new ArgumentNullException(nameof(xml)); 24 | } 25 | if (devices == null) { 26 | throw new ArgumentNullException(nameof(devices)); 27 | } 28 | 29 | XmlReaderSettings xmlReaderSettings = new XmlReaderSettings() { IgnoreComments = true, IgnoreWhitespace = true }; 30 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(JC2Data)); 31 | 32 | using (XmlReader xmlReader = XmlReader.Create(new StringReader(xml), xmlReaderSettings)) { 33 | JC2Data jc2data = (JC2Data)xmlSerializer.Deserialize(xmlReader); 34 | 35 | devices.Clear(); 36 | foreach (JC2DectDevice jc2dectDevice in jc2data.DectDevices) { 37 | devices.Add(new DectDevice(jc2dectDevice)); 38 | } 39 | foreach (JC2JuisDevice jc2juisDevice in jc2data.JuisDevices) { 40 | devices.Add(new JuisDevice(jc2juisDevice)); 41 | } 42 | 43 | devices.Settings.Reset(); 44 | foreach(JC2Setting setting in jc2data.Settings) { 45 | devices.Settings.Add(setting.Name, setting.Value); 46 | } 47 | } 48 | } 49 | 50 | public static void SaveToFile( string fileName, DeviceCollection devices ) 51 | { 52 | if (fileName == null) { 53 | throw new ArgumentNullException(nameof(fileName)); 54 | } 55 | if (devices == null) { 56 | throw new ArgumentNullException(nameof(devices)); 57 | } 58 | 59 | using (XmlWriter xmlWriter = XmlWriter.Create(fileName, new XmlWriterSettings { Indent = true })) { 60 | JC2Data jc2data = new JC2Data(); 61 | 62 | foreach (Device device in devices) { 63 | if (device is DectDevice dectDevice) { 64 | jc2data.DectDevices.Add(new JC2DectDevice(dectDevice)); 65 | } 66 | if (device is JuisDevice juisDevice) { 67 | jc2data.JuisDevices.Add(new JC2JuisDevice(juisDevice)); 68 | } 69 | } 70 | 71 | foreach (KeyValuePair setting in devices.Settings.GetDictionary()) { 72 | jc2data.Settings.Add(new JC2Setting(setting.Key, setting.Value)); 73 | } 74 | 75 | XmlSerializer xmlSerializer = new XmlSerializer(typeof(JC2Data)); 76 | xmlSerializer.Serialize(xmlWriter, jc2data); 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC2DectDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Xml.Serialization; 3 | 4 | namespace JuisCheck.XML 5 | { 6 | [XmlType("DectDevice")] 7 | public class JC2DectDevice 8 | { 9 | // Note: the member order determines the order of attributes in the XML output. 10 | 11 | [XmlAttribute("id")] public string ID { get; set; } 12 | 13 | // Note: the member order determines the order of elements in the XML output. 14 | 15 | [XmlElement("DeviceName")] public string DeviceName { get; set; } 16 | [XmlElement("ProductName")] public string ProductName { get; set; } 17 | [XmlElement("HardwareMajor")] public int HardwareMajor { get; set; } 18 | [XmlElement("HardwareMinor")] public int HardwareMinor { get; set; } 19 | [XmlElement("FirmwareMajor")] public int FirmwareMajor { get; set; } 20 | [XmlElement("FirmwareMinor")] public int FirmwareMinor { get; set; } 21 | [XmlElement("FirmwareMinor2")] public int FirmwareMinor2 { get; set; } 22 | [XmlElement("FirmwareMinor3")] public int FirmwareMinor3 { get; set; } 23 | [XmlElement("FirmwareMinor4")] public int FirmwareMinor4 { get; set; } 24 | [XmlElement("OEM")] public string OEM { get; set; } 25 | [XmlElement("Country")] public string Country { get; set; } 26 | [XmlElement("Language")] public string Language { get; set; } 27 | [XmlElement("DectBase")] public string DectBase { get; set; } 28 | [XmlElement("UpdateAvailable")] public bool UpdateAvailable { get; set; } 29 | [XmlElement("UpdateInfo")] public string UpdateInfo { get; set; } 30 | [XmlElement("UpdateImageURL")] public string UpdateImageURL { get; set; } 31 | [XmlElement("UpdateInfoURL")] public string UpdateInfoURL { get; set; } 32 | [XmlElement("UpdateLastChecked")] public DateTime? UpdateLastChecked { get; set; } 33 | 34 | public JC2DectDevice() 35 | { 36 | } 37 | 38 | public JC2DectDevice( DectDevice dectDevice ) 39 | { 40 | if (dectDevice == null) { 41 | throw new ArgumentNullException(nameof(dectDevice)); 42 | } 43 | 44 | ID = dectDevice.ID; 45 | 46 | DeviceName = dectDevice.DeviceName; 47 | ProductName = dectDevice.ProductName; 48 | HardwareMajor = dectDevice.HardwareMajor; 49 | HardwareMinor = dectDevice.HardwareMinor; 50 | FirmwareMajor = dectDevice.FirmwareMajor; 51 | FirmwareMinor = dectDevice.FirmwareMinor; 52 | FirmwareMinor2 = dectDevice.FirmwareMinor2; 53 | FirmwareMinor3 = dectDevice.FirmwareMinor3; 54 | FirmwareMinor4 = dectDevice.FirmwareMinor4; 55 | OEM = dectDevice.OEM; 56 | Country = dectDevice.Country; 57 | Language = dectDevice.Language; 58 | DectBase = dectDevice.DectBase; 59 | UpdateAvailable = dectDevice.UpdateAvailable; 60 | UpdateImageURL = dectDevice.UpdateImageURL; 61 | UpdateInfo = dectDevice.UpdateVersion; 62 | UpdateInfoURL = dectDevice.UpdateInfoURL; 63 | UpdateLastChecked = dectDevice.UpdateLastChecked; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC2JuisDevice.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Xml.Serialization; 4 | 5 | namespace JuisCheck.XML 6 | { 7 | [XmlType("JuisDevice")] 8 | public class JC2JuisDevice 9 | { 10 | // Note: the member order determines the order of attributes in the XML output. 11 | 12 | [XmlAttribute("id")] public string ID { get; set; } 13 | 14 | // Note: the member order determines the order of elements in the XML output. 15 | 16 | [XmlElement("DeviceName")] public string DeviceName { get; set; } 17 | [XmlElement("DeviceAddress")] public string DeviceAddress { get; set; } 18 | [XmlElement("ProductName")] public string ProductName { get; set; } 19 | [XmlElement("Hardware")] public int Hardware { get; set; } 20 | [XmlElement("SerialNumber")] public string SerialNumber { get; set; } 21 | [XmlElement("FirmwareMajor")] public int FirmwareMajor { get; set; } 22 | [XmlElement("FirmwareMinor")] public int FirmwareMinor { get; set; } 23 | [XmlElement("FirmwarePatch")] public int FirmwarePatch { get; set; } 24 | [XmlElement("FirmwareBuildNumber")] public int FirmwareBuildNumber { get; set; } 25 | [XmlElement("FirmwareBuildType")] public int FirmwareBuildType { get; set; } 26 | [XmlElement("OEM")] public string OEM { get; set; } 27 | [XmlElement("Annex")] public string Annex { get; set; } 28 | [XmlElement("Country")] public string Country { get; set; } 29 | [XmlElement("Language")] public string Language { get; set; } 30 | [XmlArray("Flags")][XmlArrayItem("Flag")] public List Flags { get; } = new List(); 31 | [XmlElement("MeshMaster")] public string MeshMaster { get; set; } 32 | [XmlElement("UpdateAvailable")] public bool UpdateAvailable { get; set; } 33 | [XmlElement("UpdateInfo")] public string UpdateInfo { get; set; } 34 | [XmlElement("UpdateImageURL")] public string UpdateImageURL { get; set; } 35 | [XmlElement("UpdateInfoURL")] public string UpdateInfoURL { get; set; } 36 | [XmlElement("UpdateLastChecked")] public DateTime? UpdateLastChecked { get; set; } 37 | 38 | public JC2JuisDevice() 39 | { 40 | } 41 | 42 | public JC2JuisDevice( JuisDevice juisDevice ) 43 | { 44 | if (juisDevice == null) { 45 | throw new ArgumentNullException(nameof(juisDevice)); 46 | } 47 | 48 | ID = juisDevice.ID; 49 | 50 | DeviceName = juisDevice.DeviceName; 51 | DeviceAddress = juisDevice.DeviceAddress; 52 | ProductName = juisDevice.ProductName; 53 | Hardware = juisDevice.Hardware; 54 | SerialNumber = juisDevice.SerialNumber; 55 | FirmwareMajor = juisDevice.FirmwareMajor; 56 | FirmwareMinor = juisDevice.FirmwareMinor; 57 | FirmwarePatch = juisDevice.FirmwarePatch; 58 | FirmwareBuildNumber = juisDevice.FirmwareBuildNumber; 59 | FirmwareBuildType = juisDevice.FirmwareBuildType; 60 | OEM = juisDevice.OEM; 61 | Annex = juisDevice.Annex; 62 | Country = juisDevice.Country; 63 | Language = juisDevice.Language; 64 | Flags = JuisDevice.FlagsToList(juisDevice.Flags); 65 | MeshMaster = juisDevice.MeshMaster; 66 | UpdateAvailable = juisDevice.UpdateAvailable; 67 | UpdateImageURL = juisDevice.UpdateImageURL; 68 | UpdateInfo = juisDevice.UpdateVersion; 69 | UpdateInfoURL = juisDevice.UpdateInfoURL; 70 | UpdateLastChecked = juisDevice.UpdateLastChecked; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /JuisCheck/XML/JC2Setting.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace JuisCheck.XML 4 | { 5 | [XmlType("Setting")] 6 | public class JC2Setting 7 | { 8 | // Note: the member order determines the order of attributes in the XML output. 9 | 10 | [XmlAttribute("name")] public string Name { get; set; } 11 | 12 | // Note: the member order determines the order of elements in the XML output. 13 | 14 | [XmlElement("Value")] public string Value { get; set; } 15 | 16 | /****************/ 17 | /* Constructors */ 18 | /****************/ 19 | 20 | public JC2Setting() 21 | { 22 | } 23 | 24 | public JC2Setting( string name, string value ) 25 | { 26 | Name = name; 27 | Value = value; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /JuisCheck/XML/JCData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace JuisCheck.XML 5 | { 6 | public static class JCData 7 | { 8 | public static bool LoadFromFile( string fileName, DeviceCollection devices ) 9 | { 10 | if (fileName == null) { 11 | throw new ArgumentNullException(nameof(fileName)); 12 | } 13 | if (devices == null) { 14 | throw new ArgumentNullException(nameof(devices)); 15 | } 16 | 17 | // Read data only once 18 | 19 | string xml = File.ReadAllText(fileName); 20 | 21 | // Try JuisCheck2 file format 22 | 23 | try { 24 | JC2Data.LoadFromString(xml, devices); 25 | return false; 26 | } 27 | catch (InvalidOperationException) { 28 | } 29 | 30 | // Try JuisCheck1 file format 31 | 32 | JC1Data.LoadFromString(xml, devices); 33 | return true; 34 | } 35 | 36 | public static void SaveToFile( string fileName, DeviceCollection devices ) 37 | { 38 | if (fileName == null) { 39 | throw new ArgumentNullException(nameof(fileName)); 40 | } 41 | if (devices == null) { 42 | throw new ArgumentNullException(nameof(devices)); 43 | } 44 | 45 | JC2Data.SaveToFile(fileName, devices); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /JuisCheck/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | False 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | False 28 | 29 | 30 | True 31 | 32 | 33 | True 34 | 35 | 36 | True 37 | 38 | 39 | False 40 | 41 | 42 | False 43 | 44 | 45 | False 46 | 47 | 48 | True 49 | 50 | 51 | True 52 | 53 | 54 | False 55 | 56 | 57 | True 58 | 59 | 60 | True 61 | 62 | 63 | -1 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | False 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | NaN 82 | 83 | 84 | NaN 85 | 86 | 87 | False 88 | 89 | 90 | True 91 | 92 | 93 | NaN 94 | 95 | 96 | NaN 97 | 98 | 99 | 100 | 101 | 102 | 10 103 | 104 | 105 | True 106 | 107 | 108 | auto 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /examples/FritzPowerline_Release.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | FRITZ!Powerline 540E 7 | 8 | FRITZ!Powerline 540E 9 | 201 10 | 11 | 129 12 | 7 13 | 12 14 | 70667 15 | 1 16 | avm 17 | Ohne 18 | 049 19 | de 20 | 21 | 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | FRITZ!Powerline 546E 30 | 31 | FRITZ!Powerline 546E 32 | 190 33 | 34 | 118 35 | 7 36 | 12 37 | 70668 38 | 1 39 | avm 40 | Ohne 41 | 049 42 | de 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | 52 | FRITZ!Powerline 1240E 53 | 54 | FRITZ!Powerline 1240E 55 | 222 56 | 57 | 150 58 | 7 59 | 12 60 | 70669 61 | 1 62 | avm 63 | Ohne 64 | 049 65 | de 66 | 67 | 68 | false 69 | 70 | 71 | 72 | 73 | 74 | 75 | FRITZ!Powerline 1260E 76 | 77 | FRITZ!Powerline 1260E 78 | 229 79 | 80 | 157 81 | 7 82 | 12 83 | 70670 84 | 1 85 | avm 86 | Ohne 87 | 049 88 | de 89 | 90 | 91 | false 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | False 101 | 102 | 103 | False 104 | 105 | 106 | True 107 | 108 | 109 | True 110 | 111 | 112 | False 113 | 114 | 115 | False 116 | 117 | 118 | False 119 | 120 | 121 | True 122 | 123 | 124 | True 125 | 126 | 127 | False 128 | 129 | 130 | True 131 | 132 | 133 | True 134 | 135 | 136 | -------------------------------------------------------------------------------- /examples/FritzWLAN_Obsolete_Release.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | FRITZ!WLAN Repeater 300E 7 | 8 | FRITZ!WLAN Repeater 300E 9 | 173 10 | 11 | 101 12 | 6 13 | 33 14 | 0 15 | 1 16 | avm 17 | Ohne 18 | 049 19 | de 20 | 21 | 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | FRITZ!WLAN Repeater DVB-C 30 | 31 | FRITZ!WLAN Repeater DVB-C 32 | 205 33 | 34 | 133 35 | 7 36 | 1 37 | 63069 38 | 1 39 | avm 40 | Ohne 41 | 049 42 | de 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | False 55 | 56 | 57 | True 58 | 59 | 60 | True 61 | 62 | 63 | True 64 | 65 | 66 | False 67 | 68 | 69 | False 70 | 71 | 72 | False 73 | 74 | 75 | True 76 | 77 | 78 | True 79 | 80 | 81 | False 82 | 83 | 84 | True 85 | 86 | 87 | True 88 | 89 | 90 | -------------------------------------------------------------------------------- /examples/FritzWLAN_Release.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | FRITZ!WLAN Repeater 310A 7 | 8 | FRITZ!WLAN Repeater 310A 9 | 194 10 | 11 | 122 12 | 7 13 | 12 14 | 70773 15 | 1 16 | avm 17 | Ohne 18 | 049 19 | de 20 | 21 | 22 | false 23 | 24 | 25 | 26 | 27 | 28 | 29 | FRITZ!WLAN Repeater 310B 30 | 31 | FRITZ!WLAN Repeater 310B 32 | 215 33 | 34 | 143 35 | 7 36 | 12 37 | 70776 38 | 1 39 | avm 40 | Ohne 41 | 049 42 | de 43 | 44 | 45 | false 46 | 47 | 48 | 49 | 50 | 51 | 52 | FRITZ!WLAN Repeater 450E 53 | 54 | FRITZ!WLAN Repeater 450E 55 | 200 56 | 57 | 128 58 | 7 59 | 12 60 | 70774 61 | 1 62 | avm 63 | Ohne 64 | 049 65 | de 66 | 67 | 68 | false 69 | 70 | 71 | 72 | 73 | 74 | 75 | FRITZ!WLAN Repeater 1160 76 | 77 | FRITZ!WLAN Repeater 1160 78 | 216 79 | 80 | 144 81 | 7 82 | 12 83 | 70777 84 | 1 85 | avm 86 | Ohne 87 | 049 88 | de 89 | 90 | 91 | false 92 | 93 | 94 | 95 | 96 | 97 | 98 | FRITZ!WLAN Repeater 1750E 99 | 100 | FRITZ!WLAN Repeater 1750E 101 | 206 102 | 103 | 134 104 | 7 105 | 12 106 | 70775 107 | 1 108 | avm 109 | Ohne 110 | 049 111 | de 112 | 113 | 114 | false 115 | 116 | 117 | 118 | 119 | 120 | 121 | FRITZ!WLAN Repeater 3000 122 | 123 | FRITZ!WLAN Repeater 3000 124 | 246 125 | 126 | 174 127 | 7 128 | 14 129 | 73940 130 | 1 131 | avm 132 | Ohne 133 | 049 134 | de 135 | 136 | 137 | false 138 | 139 | 140 | 141 | 142 | 143 | 144 | FRITZ!WLAN Repeater 1200 145 | 146 | FRITZ!WLAN Repeater 1200 147 | 244 148 | 149 | 172 150 | 7 151 | 14 152 | 73941 153 | 1 154 | avm 155 | Ohne 156 | 049 157 | de 158 | 159 | 160 | false 161 | 162 | 163 | 164 | 165 | 166 | 167 | FRITZ!WLAN Repeater 600 168 | 169 | FRITZ!WLAN Repeater 600 170 | 240 171 | 172 | 168 173 | 7 174 | 12 175 | 70604 176 | 1 177 | avm 178 | Ohne 179 | 049 180 | de 181 | 182 | 183 | false 184 | 185 | 186 | 187 | 188 | 189 | 190 | FRITZ!WLAN Repeater 2400 191 | 192 | FRITZ!WLAN Repeater 2400 193 | 241 194 | 195 | 169 196 | 7 197 | 12 198 | 70403 199 | 1 200 | avm 201 | Ohne 202 | 049 203 | de 204 | 205 | 206 | false 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | False 216 | 217 | 218 | False 219 | 220 | 221 | True 222 | 223 | 224 | True 225 | 226 | 227 | False 228 | 229 | 230 | False 231 | 232 | 233 | False 234 | 235 | 236 | True 237 | 238 | 239 | True 240 | 241 | 242 | False 243 | 244 | 245 | True 246 | 247 | 248 | True 249 | 250 | 251 | -------------------------------------------------------------------------------- /libraries/Muon.DotNetExtensions.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.DotNetExtensions.dll -------------------------------------------------------------------------------- /libraries/Muon.DotNetExtensions.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.DotNetExtensions.pdb -------------------------------------------------------------------------------- /libraries/Muon.DotNetExtensions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Muon.DotNetExtensions 5 | 6 | 7 | 8 | 9 | This namespace contains extension methods for Microsoft .NET classes. 10 | 11 | 12 | 13 | 14 | Defines extensions to the class. 15 | 16 | 17 | 18 | 19 | Gets the Company attribute of an assembly. 20 | 21 | The assembly. 22 | The Company attribute. 23 | assembly is null. 24 | 25 | 26 | 27 | Gets the Copyright attribute of an assembly. 28 | 29 | The assembly. 30 | The Copyright attribute. 31 | 32 | 33 | 34 | Gets the Description attribute of an assembly. 35 | 36 | The assembly. 37 | The Description attribute. 38 | assembly is null. 39 | 40 | 41 | 42 | Gets the Product attribute of an assembly. 43 | 44 | The assembly. 45 | The Product attribute. 46 | assembly is null. 47 | 48 | 49 | 50 | Gets the Title attribute of an assembly. 51 | 52 | The assembly. 53 | The Title attribute. 54 | assembly is null. 55 | 56 | 57 | 58 | Gets the Version attribute of an assembly. 59 | 60 | The assembly. 61 | The number of version parts to get (1-4). The default is 4. 62 | The Version attribute. 63 | assembly is null. 64 | 65 | 66 | 67 | Defines extensions to the class. 68 | 69 | 70 | 71 | 72 | Returns the unescaped version of a string. See for the supported escape sequences. 73 | 74 | The original string. 75 | The unescaped string. 76 | 77 | 78 | 79 | Returns a new string that contains at most the specified number of 80 | characters of the current instance. 81 | 82 | The original string. 83 | The maximum number of characters to return. 84 | The new string. 85 | 86 | 87 | 88 | Defines extensions to the class. 89 | 90 | 91 | 92 | 93 | Determines if any DependenctObject node in a DependencyObject tree has an error. 94 | 95 | The root node of the DependencyObject tree. 96 | True if the DependencyObject tree has an error. 97 | 98 | 99 | 100 | Determines if any DependenctObject node in a DependencyObject tree has an error. 101 | 102 | The root node of the DependencyObject tree. 103 | If true do not evaluate nodes that are disabled. 104 | If true do not evaluate nodes that are invisible. 105 | True if the DependencyObject tree has an error. 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /libraries/Muon.Windows.Controls.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.Windows.Controls.dll -------------------------------------------------------------------------------- /libraries/Muon.Windows.Controls.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.Windows.Controls.pdb -------------------------------------------------------------------------------- /libraries/Muon.Windows.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.Windows.dll -------------------------------------------------------------------------------- /libraries/Muon.Windows.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kingfisher63/avm_juischeck/986745a49ac9719ba59610d6df2caf565ddcdfcf/libraries/Muon.Windows.pdb --------------------------------------------------------------------------------