From 54ba78dbb0badc212da6fd0d6fb68f91ee4d5a97 Mon Sep 17 00:00:00 2001 From: Yury Malich Date: Fri, 6 Nov 2020 18:17:26 +0100 Subject: [PATCH 1/4] Bug#277: Fixed re-saving image resources for NET Core WindowsForms assemblies. --- ILRepack/ResReader.cs | 3 ++- ILRepack/Steps/ResourcesRepackStep.cs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ILRepack/ResReader.cs b/ILRepack/ResReader.cs index bf06efcb..8471ef4d 100644 --- a/ILRepack/ResReader.cs +++ b/ILRepack/ResReader.cs @@ -187,6 +187,7 @@ public bool IsString internal sealed class ResReader : IEnumerable, IDisposable { + public string ReaderType { get; private set; } private BinaryReader _store; // backing store we're reading from. private readonly long _nameSectionOffset; // Offset to name section of file. private readonly long _dataSectionOffset; // Offset to Data section of file. @@ -226,7 +227,7 @@ public ResReader(Stream stream) // Read in type name for a suitable ResourceReader // Note ResourceWriter & InternalResGen use different Strings. - String readerType = _store.ReadString(); + ReaderType = _store.ReadString(); // Skip over type name for a suitable ResourceSet SkipString(); diff --git a/ILRepack/Steps/ResourcesRepackStep.cs b/ILRepack/Steps/ResourcesRepackStep.cs index 4331f772..f92f910d 100644 --- a/ILRepack/Steps/ResourcesRepackStep.cs +++ b/ILRepack/Steps/ResourcesRepackStep.cs @@ -257,9 +257,12 @@ private Resource FixResxResource( MemoryStream stream = (MemoryStream)er.GetResourceStream(); var output = new MemoryStream((int)stream.Length); var rw = new ResourceWriter(output); + var resourceBytes = stream.ToArray(); + string readerType; using (var rr = new ResReader(stream)) { + readerType = rr.ReaderType; foreach (var res in rr) { foreach (var processor in resourcePrcessors) @@ -275,6 +278,18 @@ private Resource FixResxResource( rw.Generate(); output.Position = 0; + + if (readerType.StartsWith("System.Resources.Extensions.DeserializingResourceReader")) + { + // Bugfix#277 + // Default ResourceWriter creates incompatible resourses for NET Core WindowsForms applications + // because the new deserializer of type "System.Resources.Extensions.DeserializingResourceReader" is used there. + // Therefore unchanged original resourceBytes must be passed in EmbeddedResource constructor for an NET Core WindowsForms applications + // if the readerType is the new type "System.Resources.Extensions.DeserializingResourceReader" + + return new EmbeddedResource(er.Name, er.Attributes, new MemoryStream(resourceBytes)); + } + return new EmbeddedResource(er.Name, er.Attributes, output); } From 984835bd41def58a87dcaeda6abddce616134b96 Mon Sep 17 00:00:00 2001 From: Yury Malich Date: Fri, 6 Nov 2020 18:23:30 +0100 Subject: [PATCH 2/4] Bug#277 - Added new Integration tests for NET Core applications (Winforms and WPF). - Fixed problem - Nuget download doesn't work without SecurityProtocolType.Tls12 anymore. - Added NUnitTestAdapter package to run tests in VS 2019 TestExplorer. --- .../ILRepack.IntegrationTests.csproj | 33 ++++- .../NuGet/NuGetHelpers.cs | 2 + ILRepack.IntegrationTests/Scenarios.cs | 12 ++ .../Scenarios/ClassLibrary/packages.config | 15 +++ .../ClassLibraryCore/ClassLibraryCore.csproj | 33 +++++ .../ClassLibraryCore/DummyUserControl.xaml | 14 ++ .../ClassLibraryCore/DummyUserControl.xaml.cs | 31 +++++ .../Properties/Resources.Designer.cs | 73 +++++++++++ .../Properties/Resources.resx | 124 ++++++++++++++++++ .../ClassLibraryCore/Resources/image.png | Bin 0 -> 182 bytes .../ClassLibraryCore/TextBlockStyles.xaml | 8 ++ .../DesignTimeBuild/.dtbcache.v2 | Bin 0 -> 81058 bytes .../WPFSampleApplicationCore/AssemblyInfo.cs | 10 ++ .../WPFSampleApplicationCore/MainWindow.xaml | 17 +++ .../MainWindow.xaml.cs | 27 ++++ .../WPFSampleApplicationCore/Program.cs | 23 ++++ .../WPFSampleApplicationCore.csproj | 21 +++ .../test_sign_key.snk | Bin 0 -> 596 bytes .../Form1.Designer.cs | 60 +++++++++ .../WindowsFormsTestNetCoreApp/Form1.cs | 33 +++++ .../WindowsFormsTestNetCoreApp/Form1.resx | 60 +++++++++ .../WindowsFormsTestNetCoreApp/Program.cs | 28 ++++ .../Properties/Resources.Designer.cs | 73 +++++++++++ .../Properties/Resources.resx | 124 ++++++++++++++++++ .../Properties/launchSettings.json | 7 + .../WindowsFormsTestNetCoreApp.csproj | 34 +++++ .../checkbox_checked.png | Bin 0 -> 174 bytes ILRepack.IntegrationTests/packages.config | 3 + ILRepack.Tests/ILRepack.Tests.csproj | 31 ++++- ILRepack.Tests/packages.config | 5 +- ILRepack.sln | 31 ++++- 31 files changed, 921 insertions(+), 11 deletions(-) create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibrary/packages.config create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/ClassLibraryCore.csproj create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.Designer.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.resx create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Resources/image.png create mode 100644 ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/TextBlockStyles.xaml create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/.vs/WPFSampleApplicationCore/DesignTimeBuild/.dtbcache.v2 create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/AssemblyInfo.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/MainWindow.xaml create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/MainWindow.xaml.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/Program.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/WPFSampleApplicationCore.csproj create mode 100644 ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/test_sign_key.snk create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Form1.Designer.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Form1.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Form1.resx create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Program.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Properties/Resources.Designer.cs create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Properties/Resources.resx create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/Properties/launchSettings.json create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/WindowsFormsTestNetCoreApp.csproj create mode 100644 ILRepack.IntegrationTests/Scenarios/WindowsFormsTestNetCoreApp/checkbox_checked.png diff --git a/ILRepack.IntegrationTests/ILRepack.IntegrationTests.csproj b/ILRepack.IntegrationTests/ILRepack.IntegrationTests.csproj index c74c2073..5a666611 100644 --- a/ILRepack.IntegrationTests/ILRepack.IntegrationTests.csproj +++ b/ILRepack.IntegrationTests/ILRepack.IntegrationTests.csproj @@ -1,5 +1,6 @@  + Debug @@ -9,8 +10,9 @@ Properties ILRepack.IntegrationTests ILRepack.IntegrationTests - v4.0 + v4.7.2 512 + true @@ -20,6 +22,7 @@ DEBUG;TRACE prompt 4 + false pdbonly @@ -28,14 +31,19 @@ TRACE prompt 4 + false ..\packages\FSharp.Core.4.0.0.1\lib\net40\FSharp.Core.dll - - ..\packages\NUnit.2.6.4\lib\nunit.framework.dll - True + + ..\packages\NUnitTestAdapter.WithFramework.2.0.0\lib\nunit.core.dll + False + + + ..\packages\NUnitTestAdapter.WithFramework.2.0.0\lib\nunit.core.interfaces.dll + False False @@ -54,6 +62,17 @@ ..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll + + ..\packages\NUnitTestAdapter.WithFramework.2.0.0\lib\nunit.framework.dll + + + ..\packages\NUnitTestAdapter.WithFramework.2.0.0\lib\nunit.util.dll + False + + + ..\packages\NUnitTestAdapter.WithFramework.2.0.0\lib\NUnit.VisualStudio.TestAdapter.dll + False + ..\packages\Rx-Core.2.2.5\lib\net40\System.Reactive.Core.dll @@ -107,4 +126,10 @@ + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + \ No newline at end of file diff --git a/ILRepack.IntegrationTests/NuGet/NuGetHelpers.cs b/ILRepack.IntegrationTests/NuGet/NuGetHelpers.cs index 3cbd9fdf..d367a0c6 100644 --- a/ILRepack.IntegrationTests/NuGet/NuGetHelpers.cs +++ b/ILRepack.IntegrationTests/NuGet/NuGetHelpers.cs @@ -55,6 +55,8 @@ public static IObservable>> GetNupkgAssembliesAsync(P public static IObservable>> GetNupkgContentAsync(Package package) { + // can't download from nuget.org without Tls12 anymore, net472 is needed for Tls12 + ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var o = CreateDownloadObservable(new Uri($"http://nuget.org/api/v2/package/{package.Name}/{package.Version}")); return o.SelectMany(input => { return Observable.Create>(observer => { diff --git a/ILRepack.IntegrationTests/Scenarios.cs b/ILRepack.IntegrationTests/Scenarios.cs index 76335a42..e52b1a5f 100644 --- a/ILRepack.IntegrationTests/Scenarios.cs +++ b/ILRepack.IntegrationTests/Scenarios.cs @@ -53,6 +53,18 @@ public void GivenDotNet462AppUsingNetStandard2LibrarySetAndReflection_MergedAppl RunScenario("DotNet462NetStandard2"); } + [Test] + public void GivenNetCore3WinFormsAppUsesImageResources_MergedCore3WinFormsApplicationRunsSuccessfully() + { + RunScenario("WindowsFormsTestNetCoreApp"); + } + + [Test] + public void GivenNetCore3WpfAppUsesImageResources_MergedCore3WpfApplicationRunsSuccessfully() + { + RunScenario("WPFSampleApplicationCore"); + } + private void RunScenario(string scenarioName) { string scenarioExecutable = GetScenarioExecutable(scenarioName); diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibrary/packages.config b/ILRepack.IntegrationTests/Scenarios/ClassLibrary/packages.config new file mode 100644 index 00000000..7547653d --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibrary/packages.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/ClassLibraryCore.csproj b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/ClassLibraryCore.csproj new file mode 100644 index 00000000..ee177907 --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/ClassLibraryCore.csproj @@ -0,0 +1,33 @@ + + + + netcoreapp3.1 + true + true + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml new file mode 100644 index 00000000..37172f95 --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml @@ -0,0 +1,14 @@ + + + /ClassLibraryCore;component/Resources/image.png + + + + + + + + diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml.cs b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml.cs new file mode 100644 index 00000000..d32e3fa2 --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/DummyUserControl.xaml.cs @@ -0,0 +1,31 @@ + +using System; +using System.Windows; + +namespace ClassLibraryCore +{ + public partial class DummyUserControl + { + public DummyUserControl() + { + InitializeComponent(); + + Loaded += OnLoaded; + + if (Properties.Resources.image.Size.Width <= 0) + { + throw new Exception("Image from resource doesn't seem to be loaded! :("); + } + } + + private void OnLoaded(object sender, RoutedEventArgs routedEventArgs) + { + /* + if (TheImage.ActualWidth <= 0) + { + throw new Exception("Image doesn't seem to be loaded! :("); + } + */ + } + } +} diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.Designer.cs b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.Designer.cs new file mode 100644 index 00000000..0281d64f --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.Designer.cs @@ -0,0 +1,73 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ClassLibraryCore.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ClassLibraryCore.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap image { + get { + object obj = ResourceManager.GetObject("image", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.resx b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.resx new file mode 100644 index 00000000..99f83cee --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Properties/Resources.resx @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + \ No newline at end of file diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Resources/image.png b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/Resources/image.png new file mode 100644 index 0000000000000000000000000000000000000000..7eb2b9ad8705a5c9b521a00ebfa3849dfecc8af8 GIT binary patch literal 182 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_>3?$zOPHh5G(g8jpu4m4inKo_Os#UADZ{NOg zNOuZqb%w(bDpwecm^^DC&S7B0Bo;>Se apb<}hbENYsC8hxlWAJqKb6Mw<&;$U~ggUnX literal 0 HcmV?d00001 diff --git a/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/TextBlockStyles.xaml b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/TextBlockStyles.xaml new file mode 100644 index 00000000..5c0a3270 --- /dev/null +++ b/ILRepack.IntegrationTests/Scenarios/ClassLibraryCore/TextBlockStyles.xaml @@ -0,0 +1,8 @@ + + + + diff --git a/ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/.vs/WPFSampleApplicationCore/DesignTimeBuild/.dtbcache.v2 b/ILRepack.IntegrationTests/Scenarios/WPFSampleApplicationCore/.vs/WPFSampleApplicationCore/DesignTimeBuild/.dtbcache.v2 new file mode 100644 index 0000000000000000000000000000000000000000..1708aa10e581e469e99438db43df9c292c4fa4a2 GIT binary patch literal 81058 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 + +