From c61d3b3ab29467b427c748ca5b229a285974f72f Mon Sep 17 00:00:00 2001 From: pentp Date: Wed, 23 Feb 2011 03:25:15 +0200 Subject: [PATCH 1/7] Fix for handler blocks ending at method body end --- ICSharpCode.Decompiler/Disassembler/ILStructure.cs | 2 +- ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 52d359a2a..56f35792b 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.Disassembler AddNestedStructure(new ILStructure(ILStructureType.Try, eh.TryStart.Offset, eh.TryEnd.Offset, eh)); if (eh.HandlerType == ExceptionHandlerType.Filter) AddNestedStructure(new ILStructure(ILStructureType.Filter, eh.FilterStart.Offset, eh.FilterEnd.Offset, eh)); - AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd.Offset, eh)); + AddNestedStructure(new ILStructure(ILStructureType.Handler, eh.HandlerStart.Offset, eh.HandlerEnd == null ? body.CodeSize : eh.HandlerEnd.Offset, eh)); } // Very simple loop detection: look for backward branches List> allBranches = FindAllBranches(body); diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index ea228e014..51656fc1a 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -567,8 +567,9 @@ namespace Decompiler int startIndex; for (startIndex = 0; body[startIndex].Offset != eh.HandlerStart.Offset; startIndex++); int endInclusiveIndex; - // Note that the end(exclusiove) instruction may not necessarly be in our body - for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); + if (eh.HandlerEnd == null) endInclusiveIndex = body.Count - 1; + // Note that the end(exclusive) instruction may not necessarly be in our body + else for (endInclusiveIndex = 0; body[endInclusiveIndex].Next.Offset != eh.HandlerEnd.Offset; endInclusiveIndex++); int count = 1 + endInclusiveIndex - startIndex; HashSet nestedEHs = new HashSet(ehs.Where(e => (eh.HandlerStart.Offset <= e.TryStart.Offset && e.TryEnd.Offset < eh.HandlerEnd.Offset) || (eh.HandlerStart.Offset < e.TryStart.Offset && e.TryEnd.Offset <= eh.HandlerEnd.Offset))); ehs.ExceptWith(nestedEHs); From 9971c664d7efcf1ef5b56244f710775a8a1041d2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 17:03:28 +0100 Subject: [PATCH 2/7] Add tests for method ending with finally block/catch handler. --- .../Tests/ExceptionHandling.cs | 25 +++++++++++++++++++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 1 + 2 files changed, 26 insertions(+) create mode 100644 ICSharpCode.Decompiler/Tests/ExceptionHandling.cs diff --git a/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs new file mode 100644 index 000000000..21b259126 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/ExceptionHandling.cs @@ -0,0 +1,25 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +public class ExceptionHandling +{ + public void MethodEndingWithEndFinally() + { + try { + throw null; + } finally { + Console.WriteLine(); + } + } + + public void MethodEndingWithRethrow() + { + try { + throw null; + } catch { + throw; + } + } +} diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 7206c2201..636ea71dc 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -49,6 +49,7 @@ + From e8f3e14102137461b7e0b9cd159528b7f074ae73 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 17:21:28 +0100 Subject: [PATCH 3/7] Fix bugs in type analysis. Closes #38. --- ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs | 6 +- .../Tests/BooleanConsumedAsInteger.il | 59 +++++++++++++++++++ .../Tests/ICSharpCode.Decompiler.Tests.csproj | 7 +++ 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il diff --git a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs index 6c79b565e..e7ed4a7dd 100644 --- a/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs +++ b/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs @@ -286,7 +286,9 @@ namespace Decompiler case ILCode.Ldvirtftn: return typeSystem.IntPtr; case ILCode.Ldc_I4: - return (IsIntegerOrEnum(expectedType) || IsBoolean(expectedType)) ? expectedType : typeSystem.Int32; + if (IsBoolean(expectedType) && ((int)expr.Operand == 0 || (int)expr.Operand == 1)) + return typeSystem.Boolean; + return IsIntegerOrEnum(expectedType) ? expectedType : typeSystem.Int32; case ILCode.Ldc_I8: return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64; case ILCode.Ldc_R4: @@ -561,7 +563,7 @@ namespace Decompiler } else { left.ExpectedType = right.ExpectedType = TypeWithMoreInformation(leftPreferred, rightPreferred); left.InferredType = DoInferTypeForExpression(left, left.ExpectedType); - right.InferredType = DoInferTypeForExpression(left, right.ExpectedType); + right.InferredType = DoInferTypeForExpression(right, right.ExpectedType); return left.ExpectedType; } } diff --git a/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il new file mode 100644 index 000000000..9e3000279 --- /dev/null +++ b/ICSharpCode.Decompiler/Tests/BooleanConsumedAsInteger.il @@ -0,0 +1,59 @@ +.assembly extern mscorlib +{ + .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) + .ver 4:0:0:0 +} +.assembly BooleanConsumedAsInteger +{ + .hash algorithm 0x00008004 + .ver 1:0:0:0 +} +.module BooleanConsumedAsInteger.exe +.imagebase 0x00400000 +.file alignment 0x00000200 +.stackreserve 0x00100000 +.subsystem 0x0003 // WINDOWS_CUI +.corflags 0x00000003 // ILONLY 32BITREQUIRED + +.class private auto ansi beforefieldinit BooleanConsumedAsInteger.Program extends [mscorlib]System.Object +{ + .method public hidebysig static void Main(string[] args) cil managed + { + .entrypoint + .maxstack 8 + + ret + } + + .method public hidebysig static int32 ReturnBoolAsInt() cil managed + { + ldnull + ldnull + call bool [mscorlib] System.Object::Equals(object, object) + ret + } + + .method public hidebysig static int32 BitwiseOperationOnBool() cil managed + { + ldnull + ldnull + call bool [mscorlib] System.Object::Equals(object, object) + ldc.i4 255 + and + ret + } + + .method public hidebysig specialname rtspecialname + instance void .ctor() cil managed + { + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method Program::.ctor + +} // end of class StackTests.Program + + +// ============================================================= diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 636ea71dc..e6d805fb5 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -65,5 +65,12 @@ ICSharpCode.Decompiler + + + + + + + \ No newline at end of file From 53fa2b3e91546f78c33c65e3aa6ef75ff6382a96 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 17:22:29 +0100 Subject: [PATCH 4/7] Even in debug builds: catch decompiler exceptions when no debugger is attached. --- ILSpy/TextView/DecompilerTextView.cs | 38 ++++++++++++++++++---------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 7b628539e..e4355a1ca 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -264,21 +264,31 @@ namespace ICSharpCode.ILSpy.TextView Thread thread = new Thread(new ThreadStart( delegate { - try { - AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); - textOutput.LengthLimit = outputLengthLimit; - DecompileNodes(context, textOutput); - textOutput.PrepareDocument(); - tcs.SetResult(textOutput); - #if DEBUG - } catch (AggregateException ex) { - tcs.SetException(ex); - } catch (OperationCanceledException ex) { - tcs.SetException(ex); - #else - } catch (Exception ex) { - tcs.SetException(ex); + #if DEBUG + if (Debugger.IsAttached) { + try { + AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); + textOutput.LengthLimit = outputLengthLimit; + DecompileNodes(context, textOutput); + textOutput.PrepareDocument(); + tcs.SetResult(textOutput); + } catch (AggregateException ex) { + tcs.SetException(ex); + } catch (OperationCanceledException ex) { + tcs.SetException(ex); + } + } else #endif + { + try { + AvalonEditTextOutput textOutput = new AvalonEditTextOutput(); + textOutput.LengthLimit = outputLengthLimit; + DecompileNodes(context, textOutput); + textOutput.PrepareDocument(); + tcs.SetResult(textOutput); + } catch (Exception ex) { + tcs.SetException(ex); + } } })); thread.Start(); From 20cae3aab462cfe34920deff5897d3ecbbe1b19f Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 17:34:35 +0100 Subject: [PATCH 5/7] Fix duplicate reference to Mono.Cecil. --- .../ICSharpCode.NRefactory.csproj | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 6fdcd0c9f..a001adbd4 100644 --- a/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/NRefactory/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -340,16 +340,6 @@ - - - - - - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} - Mono.Cecil - - {D68133BD-1E63-496E-9EDE-4FBDBF77B486} From 943d47dcfae62e8d1baa450ccf6f3cfe975c8509 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 19:38:34 +0100 Subject: [PATCH 6/7] Export embedded resources when exporting a project. --- ILSpy/CSharpLanguage.cs | 54 ++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index ca17d220c..8502d4a85 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -115,7 +115,9 @@ namespace ICSharpCode.ILSpy { if (options.FullDecompilation) { if (options.SaveAsProjectDirectory != null) { - var files = WriteFilesInProject(assembly, options); + HashSet directories = new HashSet(StringComparer.OrdinalIgnoreCase); + var files = WriteCodeFilesInProject(assembly, options, directories).ToList(); + files.AddRange(WriteResourceFilesInProject(assembly, options, directories)); WriteProjectFile(new TextOutputWriter(output), files, assembly.MainModule); } else { foreach (TypeDefinition type in assembly.MainModule.Types) { @@ -130,7 +132,8 @@ namespace ICSharpCode.ILSpy } } - void WriteProjectFile(TextWriter writer, IEnumerable files, ModuleDefinition module) + #region WriteProjectFile + void WriteProjectFile(TextWriter writer, IEnumerable> files, ModuleDefinition module) { const string ns = "http://schemas.microsoft.com/developer/msbuild/2003"; string platformName; @@ -236,13 +239,15 @@ namespace ICSharpCode.ILSpy } w.WriteEndElement(); // (References) - w.WriteStartElement("ItemGroup"); // Code - foreach (string file in files.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { - w.WriteStartElement("Compile"); - w.WriteAttributeString("Include", file); + foreach (IGrouping gr in (from f in files group f.Item2 by f.Item1 into g orderby g.Key select g)) { + w.WriteStartElement("ItemGroup"); + foreach (string file in gr.OrderBy(f => f, StringComparer.OrdinalIgnoreCase)) { + w.WriteStartElement(gr.Key); + w.WriteAttributeString("Include", file); + w.WriteEndElement(); + } w.WriteEndElement(); } - w.WriteEndElement(); w.WriteStartElement("Import"); w.WriteAttributeString("Project", "$(MSBuildToolsPath)\\Microsoft.CSharp.targets"); @@ -251,8 +256,10 @@ namespace ICSharpCode.ILSpy w.WriteEndDocument(); } } + #endregion - IEnumerable WriteFilesInProject(AssemblyDefinition assembly, DecompilationOptions options) + #region WriteCodeFilesInProject + IEnumerable> WriteCodeFilesInProject(AssemblyDefinition assembly, DecompilationOptions options, HashSet directories) { var files = assembly.MainModule.Types.Where(t => t.Name != "").GroupBy( delegate (TypeDefinition type) { @@ -261,11 +268,11 @@ namespace ICSharpCode.ILSpy return file; } else { string dir = TextView.DecompilerTextView.CleanUpName(type.Namespace); - Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dir)); + if (directories.Add(dir)) + Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dir)); return Path.Combine(dir, file); } }, StringComparer.OrdinalIgnoreCase).ToList(); - AstMethodBodyBuilder.ClearUnhandledOpcodes(); Parallel.ForEach( files, @@ -279,8 +286,33 @@ namespace ICSharpCode.ILSpy } }); AstMethodBodyBuilder.PrintNumberOfUnhandledOpcodes(); - return files.Select(f => f.Key); + return files.Select(f => Tuple.Create("Compile", f.Key)); + } + #endregion + + #region WriteResourceFilesInProject + IEnumerable> WriteResourceFilesInProject(AssemblyDefinition assembly, DecompilationOptions options, HashSet directories) + { + foreach (EmbeddedResource r in assembly.MainModule.Resources.OfType()) { + string[] splitName = r.Name.Split('.'); + string fileName = TextView.DecompilerTextView.CleanUpName(r.Name); + for (int i = splitName.Length - 1; i > 0; i--) { + string ns = string.Join(".", splitName, 0, i); + if (directories.Contains(ns)) { + string name = string.Join(".", splitName, i, splitName.Length - i); + fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name)); + break; + } + } + Stream s = r.GetResourceStream(); + s.Position = 0; + using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) { + s.CopyTo(fs); + } + yield return Tuple.Create("EmbeddedResource", fileName); + } } + #endregion AstBuilder CreateAstBuilder(DecompilationOptions options, TypeDefinition currentType) { From 7f1a9462ffd3ff6e7ea4f659e8eee01716ea536a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 23 Feb 2011 21:01:49 +0100 Subject: [PATCH 7/7] Unpack WPF resources when saving as project. --- ILSpy/CSharpLanguage.cs | 87 ++++++++++++++++++++----- ILSpy/TreeNodes/ResourceEntryNode.cs | 46 ++++++++----- ILSpy/TreeNodes/ResourceListTreeNode.cs | 5 +- 3 files changed, 102 insertions(+), 36 deletions(-) diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs index 8502d4a85..7ff152475 100644 --- a/ILSpy/CSharpLanguage.cs +++ b/ILSpy/CSharpLanguage.cs @@ -17,12 +17,15 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Threading; +using System.Resources; using System.Threading.Tasks; +using System.Xaml; using System.Xml; + using Decompiler; using Decompiler.Transforms; using ICSharpCode.Decompiler; @@ -117,7 +120,7 @@ namespace ICSharpCode.ILSpy if (options.SaveAsProjectDirectory != null) { HashSet directories = new HashSet(StringComparer.OrdinalIgnoreCase); var files = WriteCodeFilesInProject(assembly, options, directories).ToList(); - files.AddRange(WriteResourceFilesInProject(assembly, options, directories)); + files.AddRange(WriteResourceFilesInProject(assembly, fileName, options, directories)); WriteProjectFile(new TextOutputWriter(output), files, assembly.MainModule); } else { foreach (TypeDefinition type in assembly.MainModule.Types) { @@ -291,26 +294,76 @@ namespace ICSharpCode.ILSpy #endregion #region WriteResourceFilesInProject - IEnumerable> WriteResourceFilesInProject(AssemblyDefinition assembly, DecompilationOptions options, HashSet directories) + IEnumerable> WriteResourceFilesInProject(AssemblyDefinition assembly, string assemblyFileName, DecompilationOptions options, HashSet directories) { - foreach (EmbeddedResource r in assembly.MainModule.Resources.OfType()) { - string[] splitName = r.Name.Split('.'); - string fileName = TextView.DecompilerTextView.CleanUpName(r.Name); - for (int i = splitName.Length - 1; i > 0; i--) { - string ns = string.Join(".", splitName, 0, i); - if (directories.Contains(ns)) { - string name = string.Join(".", splitName, i, splitName.Length - i); - fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name)); - break; + AppDomain bamlDecompilerAppDomain = null; + try { + foreach (EmbeddedResource r in assembly.MainModule.Resources.OfType()) { + string fileName; + Stream s = r.GetResourceStream(); + s.Position = 0; + if (r.Name.EndsWith(".g.resources", StringComparison.OrdinalIgnoreCase)) { + IEnumerable rs = null; + try { + rs = new ResourceSet(s).Cast(); + } catch (ArgumentException) { + } + if (rs != null && rs.All(e => e.Value is Stream)) { + foreach (var pair in rs) { + fileName = Path.Combine(((string)pair.Key).Split('/').Select(p => TextView.DecompilerTextView.CleanUpName(p)).ToArray()); + string dirName = Path.GetDirectoryName(fileName); + if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName)) { + Directory.CreateDirectory(Path.Combine(options.SaveAsProjectDirectory, dirName)); + } + Stream entryStream = (Stream)pair.Value; + entryStream.Position = 0; + if (fileName.EndsWith(".baml", StringComparison.OrdinalIgnoreCase)) { + MemoryStream ms = new MemoryStream(); + entryStream.CopyTo(ms); + BamlDecompiler decompiler = TreeNodes.ResourceEntryNode.CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, assemblyFileName); + string xaml = null; + try { + xaml = decompiler.DecompileBaml(ms, assemblyFileName); + } catch (XamlXmlWriterException) {} // ignore XAML writer exceptions + if (xaml != null) { + File.WriteAllText(Path.Combine(options.SaveAsProjectDirectory, Path.ChangeExtension(fileName, ".xaml")), xaml); + yield return Tuple.Create("Page", Path.ChangeExtension(fileName, ".xaml")); + continue; + } + } + using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) { + entryStream.CopyTo(fs); + } + yield return Tuple.Create("Resource", fileName); + } + continue; + } } + fileName = GetFileNameForResource(r.Name, directories); + using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) { + s.CopyTo(fs); + } + yield return Tuple.Create("EmbeddedResource", fileName); } - Stream s = r.GetResourceStream(); - s.Position = 0; - using (FileStream fs = new FileStream(Path.Combine(options.SaveAsProjectDirectory, fileName), FileMode.Create, FileAccess.Write)) { - s.CopyTo(fs); + } finally { + if (bamlDecompilerAppDomain != null) + AppDomain.Unload(bamlDecompilerAppDomain); + } + } + + string GetFileNameForResource(string fullName, HashSet directories) + { + string[] splitName = fullName.Split('.'); + string fileName = TextView.DecompilerTextView.CleanUpName(fullName); + for (int i = splitName.Length - 1; i > 0; i--) { + string ns = string.Join(".", splitName, 0, i); + if (directories.Contains(ns)) { + string name = string.Join(".", splitName, i, splitName.Length - i); + fileName = Path.Combine(ns, TextView.DecompilerTextView.CleanUpName(name)); + break; } - yield return Tuple.Create("EmbeddedResource", fileName); } + return fileName; } #endregion diff --git a/ILSpy/TreeNodes/ResourceEntryNode.cs b/ILSpy/TreeNodes/ResourceEntryNode.cs index a167a916d..dc982bf00 100644 --- a/ILSpy/TreeNodes/ResourceEntryNode.cs +++ b/ILSpy/TreeNodes/ResourceEntryNode.cs @@ -86,24 +86,36 @@ namespace ICSharpCode.ILSpy.TreeNodes { var asm = this.Ancestors().OfType().FirstOrDefault().LoadedAssembly; - // Construct and initialize settings for a second AppDomain. - AppDomainSetup bamlDecompilerAppDomainSetup = new AppDomainSetup(); - bamlDecompilerAppDomainSetup.ApplicationBase = "file:///" + Path.GetDirectoryName(asm.FileName); - bamlDecompilerAppDomainSetup.DisallowBindingRedirects = false; - bamlDecompilerAppDomainSetup.DisallowCodeDownload = true; - bamlDecompilerAppDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + AppDomain bamlDecompilerAppDomain = null; + try { + BamlDecompiler decompiler = CreateBamlDecompilerInAppDomain(ref bamlDecompilerAppDomain, asm.FileName); + + MemoryStream bamlStream = new MemoryStream(); + value.Position = 0; + value.CopyTo(bamlStream); + + output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName)); + return true; + } finally { + if (bamlDecompilerAppDomain != null) + AppDomain.Unload(bamlDecompilerAppDomain); + } + } + + public static BamlDecompiler CreateBamlDecompilerInAppDomain(ref AppDomain appDomain, string assemblyFileName) + { + if (appDomain == null) { + // Construct and initialize settings for a second AppDomain. + AppDomainSetup bamlDecompilerAppDomainSetup = new AppDomainSetup(); + bamlDecompilerAppDomainSetup.ApplicationBase = "file:///" + Path.GetDirectoryName(assemblyFileName); + bamlDecompilerAppDomainSetup.DisallowBindingRedirects = false; + bamlDecompilerAppDomainSetup.DisallowCodeDownload = true; + bamlDecompilerAppDomainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; - // Create the second AppDomain. - AppDomain bamlDecompilerAppDomain = AppDomain.CreateDomain("BamlDecompiler AD", null, bamlDecompilerAppDomainSetup); - - BamlDecompiler decompiler = (BamlDecompiler)bamlDecompilerAppDomain.CreateInstanceFromAndUnwrap(typeof(BamlDecompiler).Assembly.Location, typeof(BamlDecompiler).FullName); - - MemoryStream bamlStream = new MemoryStream(); - value.Position = 0; - value.CopyTo(bamlStream); - - output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName)); - return true; + // Create the second AppDomain. + appDomain = AppDomain.CreateDomain("BamlDecompiler AD", null, bamlDecompilerAppDomainSetup); + } + return (BamlDecompiler)appDomain.CreateInstanceFromAndUnwrap(typeof(BamlDecompiler).Assembly.Location, typeof(BamlDecompiler).FullName); } public override bool Save(DecompilerTextView textView) diff --git a/ILSpy/TreeNodes/ResourceListTreeNode.cs b/ILSpy/TreeNodes/ResourceListTreeNode.cs index f3d3ed5ca..44ae1e2c5 100644 --- a/ILSpy/TreeNodes/ResourceListTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceListTreeNode.cs @@ -156,9 +156,10 @@ namespace ICSharpCode.ILSpy.TreeNodes if (er != null) { try { Stream s = er.GetResourceStream(); + s.Position = 0; if (er.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) { - ResourceSet set = new ResourceSet(s); - foreach (DictionaryEntry entry in set.Cast().OrderBy(e => e.Key.ToString())) { + ResourceReader reader = new ResourceReader(s); + foreach (DictionaryEntry entry in reader.Cast().OrderBy(e => e.Key.ToString())) { if (entry.Value is Stream) Children.Add(new ResourceEntryNode(entry.Key.ToString(), (Stream)entry.Value)); }