From c1d75a7313b1e68187ca2611acb84a7ad4780461 Mon Sep 17 00:00:00 2001 From: Johann Blais Date: Sat, 17 Jan 2026 15:36:25 +0100 Subject: [PATCH 1/3] Replace Enum.Parse with TryParse for secure enum conversion (#51) - Replace unsafe Enum.Parse calls with TryParse in MessageBoxEnumConverter - Add proper exception handling with descriptive error messages - Update InformationBoxDesigner to use TryParse for user input validation - Update copyright to 2007-2026 across all projects - Add MSBuild path instructions to CLAUDE.md - Update NuGet packages (SourceLink, Roslyn, NUnit) - Modernize NUnit assertions (Assert.IsTrue -> Assert.That) This addresses potential security issues where malicious enum string values could cause unexpected behavior. TryParse provides safer validation. Co-authored-by: Claude Sonnet 4.5 --- .gitignore | 1 + CLAUDE.md | 14 ++++++++--- InfoBox.Designer/InformationBoxDesigner.cs | 18 +++++++++----- InfoBox.Designer/Properties/AssemblyInfo.cs | 2 +- InfoBox/InfoBox.csproj | 9 ++++--- InfoBox/Internals/MessageBoxEnumConverter.cs | 24 ++++++++++++++++--- InfoBox/Properties/AssemblyInfo.cs | 2 +- .../CodeGeneration/CSharpGeneratorTests.cs | 10 ++++---- .../InfoBoxCore.Designer.Tests.csproj | 14 +++++++---- .../InfoBoxCore.Designer.csproj | 21 ++++++++++++++++ InfoBoxCore/InfoBoxCore.csproj | 2 +- 11 files changed, 89 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 105b701..7042daa 100644 --- a/.gitignore +++ b/.gitignore @@ -287,3 +287,4 @@ __pycache__/ *.btm.cs *.odx.cs *.xsd.cs +/.claude diff --git a/CLAUDE.md b/CLAUDE.md index afc58d6..cac1c5b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,12 +8,20 @@ InformationBox is a Windows Forms library providing a customizable alternative t ## Build Commands +**IMPORTANT:** Always use the full MSBuild path when building this project. MSBuild is located at: +`P:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\msbuild.exe` + +Since the solution targets both .NET Framework 4.8 and .NET Core, use MSBuild instead of dotnet: + ```bash # Build all projects -dotnet build InfoBox.sln +"P:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\msbuild.exe" InfoBox.sln + +# Build with specific configuration +"P:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\msbuild.exe" InfoBox.sln /p:Configuration=Release -# Build specific framework -dotnet build InfoBoxCore/InfoBoxCore.csproj -f net10.0-windows +# Rebuild all (clean + build) +"P:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\msbuild.exe" InfoBox.sln /t:Rebuild # Run tests dotnet test diff --git a/InfoBox.Designer/InformationBoxDesigner.cs b/InfoBox.Designer/InformationBoxDesigner.cs index 6e69861..5d628b5 100644 --- a/InfoBox.Designer/InformationBoxDesigner.cs +++ b/InfoBox.Designer/InformationBoxDesigner.cs @@ -479,16 +479,22 @@ private AutoCloseParameters GetAutoClose() if (this.rdbAutoCloseButton.Checked && this.ddlAutoCloseButton.SelectedIndex != -1) { - return new AutoCloseParameters( - Convert.ToInt32(this.nudAutoCloseSeconds.Value), - (InformationBoxDefaultButton)Enum.Parse(typeof(InformationBoxDefaultButton), this.ddlAutoCloseButton.SelectedItem.ToString())); + if (Enum.TryParse(this.ddlAutoCloseButton.SelectedItem.ToString(), out var buttonResult)) + { + return new AutoCloseParameters( + Convert.ToInt32(this.nudAutoCloseSeconds.Value), + buttonResult); + } } if (this.rdbAutoCloseResult.Checked && this.ddlAutoCloseResult.SelectedIndex != -1) { - return new AutoCloseParameters( - Convert.ToInt32(this.nudAutoCloseSeconds.Value), - (InformationBoxResult)Enum.Parse(typeof(InformationBoxResult), this.ddlAutoCloseResult.SelectedItem.ToString())); + if (Enum.TryParse(this.ddlAutoCloseResult.SelectedItem.ToString(), out var resultValue)) + { + return new AutoCloseParameters( + Convert.ToInt32(this.nudAutoCloseSeconds.Value), + resultValue); + } } return new AutoCloseParameters(Convert.ToInt32(this.nudAutoCloseSeconds.Value)); diff --git a/InfoBox.Designer/Properties/AssemblyInfo.cs b/InfoBox.Designer/Properties/AssemblyInfo.cs index 8618cf8..08afeed 100644 --- a/InfoBox.Designer/Properties/AssemblyInfo.cs +++ b/InfoBox.Designer/Properties/AssemblyInfo.cs @@ -17,7 +17,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Johann Blais")] [assembly: AssemblyProduct("InformationBox Designer")] -[assembly: AssemblyCopyright("Copyright © Johann Blais 2007-2013")] +[assembly: AssemblyCopyright("Copyright © Johann Blais 2007-2026")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/InfoBox/InfoBox.csproj b/InfoBox/InfoBox.csproj index a8fe0fe..bd0cc1c 100644 --- a/InfoBox/InfoBox.csproj +++ b/InfoBox/InfoBox.csproj @@ -50,6 +50,8 @@ true + + true @@ -81,7 +83,7 @@ False True True - AllRules.ruleset + MinimumRecommendedRules.ruleset false @@ -101,12 +103,13 @@ - + - 6.3.4 + 7.0.1 runtime; build; native; contentfiles; analyzers; buildtransitive all + diff --git a/InfoBox/Internals/MessageBoxEnumConverter.cs b/InfoBox/Internals/MessageBoxEnumConverter.cs index b64fa3b..22eec58 100644 --- a/InfoBox/Internals/MessageBoxEnumConverter.cs +++ b/InfoBox/Internals/MessageBoxEnumConverter.cs @@ -19,9 +19,15 @@ internal static class MessageBoxEnumConverter /// /// The value. /// The converted value + /// Thrown when conversion fails. internal static InformationBoxButtons Parse(MessageBoxButtons value) { - return (InformationBoxButtons)Enum.Parse(typeof(InformationBoxButtons), value.ToString()); + if (Enum.TryParse(value.ToString(), out var result)) + { + return result; + } + + throw new ArgumentException($"Cannot convert '{value}' to InformationBoxButtons", nameof(value)); } /// @@ -29,9 +35,15 @@ internal static InformationBoxButtons Parse(MessageBoxButtons value) /// /// The value. /// The converted value + /// Thrown when conversion fails. internal static InformationBoxIcon Parse(MessageBoxIcon value) { - return (InformationBoxIcon)Enum.Parse(typeof(InformationBoxIcon), value.ToString()); + if (Enum.TryParse(value.ToString(), out var result)) + { + return result; + } + + throw new ArgumentException($"Cannot convert '{value}' to InformationBoxIcon", nameof(value)); } /// @@ -39,9 +51,15 @@ internal static InformationBoxIcon Parse(MessageBoxIcon value) /// /// The value. /// The converted value + /// Thrown when conversion fails. internal static InformationBoxDefaultButton Parse(MessageBoxDefaultButton value) { - return (InformationBoxDefaultButton)Enum.Parse(typeof(InformationBoxDefaultButton), value.ToString()); + if (Enum.TryParse(value.ToString(), out var result)) + { + return result; + } + + throw new ArgumentException($"Cannot convert '{value}' to InformationBoxDefaultButton", nameof(value)); } } } \ No newline at end of file diff --git a/InfoBox/Properties/AssemblyInfo.cs b/InfoBox/Properties/AssemblyInfo.cs index 06b3dba..a4fbf4f 100644 --- a/InfoBox/Properties/AssemblyInfo.cs +++ b/InfoBox/Properties/AssemblyInfo.cs @@ -21,7 +21,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Johann Blais")] [assembly: AssemblyProduct("InformationBox")] -[assembly: AssemblyCopyright("Copyright © Johann Blais 2007-2022")] +[assembly: AssemblyCopyright("Copyright © Johann Blais 2007-2026")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/InfoBoxCore.Designer.Tests/CodeGeneration/CSharpGeneratorTests.cs b/InfoBoxCore.Designer.Tests/CodeGeneration/CSharpGeneratorTests.cs index 3757ed5..6143e92 100644 --- a/InfoBoxCore.Designer.Tests/CodeGeneration/CSharpGeneratorTests.cs +++ b/InfoBoxCore.Designer.Tests/CodeGeneration/CSharpGeneratorTests.cs @@ -78,7 +78,7 @@ public void Test0001() order: InformationBoxOrder.Default, sound: InformationBoxSound.Default); - Assert.IsTrue(CompileCode(code).Success); + Assert.That(CompileCode(code).Success); } [Test] @@ -113,7 +113,7 @@ public void Test0002() order: InformationBoxOrder.Default, sound: InformationBoxSound.Default); - Assert.IsTrue(CompileCode(code).Success); + Assert.That(CompileCode(code).Success); } [Test] @@ -148,7 +148,7 @@ public void Test0003() order: InformationBoxOrder.Default, sound: InformationBoxSound.Default); - Assert.IsTrue(CompileCode(code).Success); + Assert.That(CompileCode(code).Success); } [Test] @@ -183,7 +183,7 @@ public void Test0004() order: InformationBoxOrder.Default, sound: InformationBoxSound.Default); - Assert.IsTrue(CompileCode(code).Success); + Assert.That(CompileCode(code).Success); } [Test] @@ -218,7 +218,7 @@ public void Test0005() order: InformationBoxOrder.Default, sound: InformationBoxSound.Default); - Assert.IsTrue(CompileCode(code).Success); + Assert.That(CompileCode(code).Success); } private EmitResult CompileCode(string sourceCode) diff --git a/InfoBoxCore.Designer.Tests/InfoBoxCore.Designer.Tests.csproj b/InfoBoxCore.Designer.Tests/InfoBoxCore.Designer.Tests.csproj index 0b1e32f..d07e97f 100644 --- a/InfoBoxCore.Designer.Tests/InfoBoxCore.Designer.Tests.csproj +++ b/InfoBoxCore.Designer.Tests/InfoBoxCore.Designer.Tests.csproj @@ -3,14 +3,18 @@ net10.0-windows7.0 false + Johann Blais + Johann Blais + InformationBox Designer Tests + Copyright © Johann Blais 2007-2026 - - - - - + + + + + diff --git a/InfoBoxCore.Designer/InfoBoxCore.Designer.csproj b/InfoBoxCore.Designer/InfoBoxCore.Designer.csproj index d299ad5..f798526 100644 --- a/InfoBoxCore.Designer/InfoBoxCore.Designer.csproj +++ b/InfoBoxCore.Designer/InfoBoxCore.Designer.csproj @@ -8,6 +8,27 @@ false InfoBox.Designer InfoBox.Designer + Johann Blais + Johann Blais + InformationBox Designer + Copyright © Johann Blais 2007-2026 + en + + + + 8 + + + + 8 + + + + 8 + + + + 8 diff --git a/InfoBoxCore/InfoBoxCore.csproj b/InfoBoxCore/InfoBoxCore.csproj index c1ed11c..1e2d0b0 100644 --- a/InfoBoxCore/InfoBoxCore.csproj +++ b/InfoBoxCore/InfoBoxCore.csproj @@ -16,6 +16,6 @@ - + \ No newline at end of file From ae12a65e31a4ae2af670708712f85d6080665ccf Mon Sep 17 00:00:00 2001 From: Johann Blais Date: Sat, 17 Jan 2026 17:39:02 +0100 Subject: [PATCH 2/3] Fixed the BinaryFormatter issue (#52) --- InfoBox.sln | 4 ++-- InfoBox/InfoBox.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InfoBox.sln b/InfoBox.sln index 8b4cc7a..dd07fa1 100644 --- a/InfoBox.sln +++ b/InfoBox.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.3.32819.101 +# Visual Studio Version 18 +VisualStudioVersion = 18.2.11408.102 d18.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{11BF73EF-1C37-4B34-BB1B-E378D733E8DC}" EndProject diff --git a/InfoBox/InfoBox.csproj b/InfoBox/InfoBox.csproj index bd0cc1c..e2df245 100644 --- a/InfoBox/InfoBox.csproj +++ b/InfoBox/InfoBox.csproj @@ -51,7 +51,7 @@ - + false true From 59510da702cddb770250dc3e00744f69cdf82c82 Mon Sep 17 00:00:00 2001 From: Johann Blais Date: Sat, 17 Jan 2026 18:13:46 +0100 Subject: [PATCH 3/3] Updated nuspec package for backward compatibility --- InfoBox/InfoBox.nuspec | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/InfoBox/InfoBox.nuspec b/InfoBox/InfoBox.nuspec index 32a7c21..7b144c8 100644 --- a/InfoBox/InfoBox.nuspec +++ b/InfoBox/InfoBox.nuspec @@ -20,14 +20,14 @@ Stop wasting time developing your own custom MessageBox, everything you need is - Removed support for .NET 6.0 (Windows) - Added support for .NET 10.0 (Windows) - Copyright 2025 + Copyright 2026 en-US MessageBox Winforms - - - + + + README.md @@ -36,15 +36,15 @@ Stop wasting time developing your own custom MessageBox, everything you need is - - - - - - - - - + + + + + + + + +