diff --git a/ICSharpCode.Decompiler.Tests/Util/ResourcesFileTests.cs b/ICSharpCode.Decompiler.Tests/Util/ResourcesFileTests.cs index 5c02a578e..b7a61bc4f 100644 --- a/ICSharpCode.Decompiler.Tests/Util/ResourcesFileTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/ResourcesFileTests.cs @@ -46,6 +46,44 @@ namespace ICSharpCode.Decompiler.Tests.Util const int TypeCodeStream = 33; const int TypeCodeStartOfUserTypes = 0x40; + [Test] + public void ResXResourceWriter_DisposeWithoutResources_WritesEmptyFile() + { + string fileName = Path.Combine(TestContext.CurrentContext.WorkDirectory, Path.GetRandomFileName() + ".resx"); + try + { + using (new ResXResourceWriter(fileName)) + { + } + + Assert.That(File.Exists(fileName), Is.True); + Assert.That(File.ReadAllText(fileName), Does.Contain("")); + } + finally + { + File.Delete(fileName); + } + } + + [Test] + public void ResXResourceWriter_UsesConfiguredAssemblyNames() + { + using var stream = new MemoryStream(); + using (var writer = new ResXResourceWriter(stream)) + { + writer.WinFormsAssemblyName = ", System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + writer.MSCorLibAssemblyName = ", mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + writer.AddResource("number", 1); + writer.AddResource("missing", (object?)null); + } + + string resx = Encoding.UTF8.GetString(stream.ToArray()); + Assert.That(resx, Does.Contain("System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0")); + Assert.That(resx, Does.Contain("System.Int32, mscorlib, Version=2.0.0.0")); + Assert.That(resx, Does.Contain("System.Resources.ResXNullRef, System.Windows.Forms, Version=2.0.0.0")); + Assert.That(resx, Does.Not.Contain("Version=4.0.0.0")); + } + [Test] public void WellFormedFile_ReadsAllEntryKinds() { diff --git a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs index bc2792758..94a28bc0a 100644 --- a/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs +++ b/ICSharpCode.Decompiler/Util/ResXResourceWriter.cs @@ -98,9 +98,32 @@ namespace ICSharpCode.Decompiler.Util Dispose(false); } - const string WinFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; - const string MSCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; - const string ResXNullRefTypeName = "System.Resources.ResXNullRef" + WinFormsAssemblyName; + const string DefaultWinFormsAssemblyName = ", System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + const string DefaultMSCorLibAssemblyName = ", mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"; + string winFormsAssemblyName = DefaultWinFormsAssemblyName; + string msCorLibAssemblyName = DefaultMSCorLibAssemblyName; + + public string WinFormsAssemblyName { + get => winFormsAssemblyName; + set { + ThrowIfWritingStarted(); + winFormsAssemblyName = value ?? throw new ArgumentNullException(nameof(value)); + } + } + + public string MSCorLibAssemblyName { + get => msCorLibAssemblyName; + set { + ThrowIfWritingStarted(); + msCorLibAssemblyName = value ?? throw new ArgumentNullException(nameof(value)); + } + } + + void ThrowIfWritingStarted() + { + if (writer != null || written) + throw new InvalidOperationException("Assembly names cannot be changed after writing started."); + } void InitWriter() { @@ -222,7 +245,7 @@ namespace ICSharpCode.Decompiler.Util { case null: // nulls written as ResXNullRef - WriteString(name, "", ResXNullRefTypeName, comment); + WriteString(name, "", "System.Resources.ResXNullRef" + WinFormsAssemblyName, comment); break; case string s: WriteString(name, s, null, comment); @@ -295,13 +318,13 @@ namespace ICSharpCode.Decompiler.Util public void Close() { + if (!written) + { + Generate(); + } + if (writer != null) { - if (!written) - { - Generate(); - } - writer.Close(); stream = null; filename = null;