Browse Source

use separate AppDomain for decompiling BAML resources

pull/37/head
Siegfried Pammer 15 years ago
parent
commit
2469227ed2
  1. 63
      ILSpy/BamlDecompiler.cs
  2. 1
      ILSpy/ILSpy.csproj
  3. 2
      ILSpy/TextView/DecompilerTextView.cs
  4. 88
      ILSpy/TreeNodes/ResourceEntryNode.cs

63
ILSpy/BamlDecompiler.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
// 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;
using System.IO;
using System.Reflection;
using System.Windows.Baml2006;
using System.Xaml;
using System.Xml;
namespace ICSharpCode.ILSpy
{
/// <remarks>Caution: use in separate AppDomain only!</remarks>
public class BamlDecompiler : MarshalByRefObject
{
public BamlDecompiler()
{
}
public string DecompileBaml(MemoryStream bamlCode, string containingAssemblyFile)
{
bamlCode.Position = 0;
TextWriter w = new StringWriter();
Assembly assembly = Assembly.LoadFile(containingAssemblyFile);
Baml2006Reader reader = new Baml2006Reader(bamlCode, new XamlReaderSettings() { ValuesMustBeString = true, LocalAssembly = assembly });
XamlXmlWriter writer = new XamlXmlWriter(new XmlTextWriter(w) { Formatting = Formatting.Indented }, reader.SchemaContext);
while (reader.Read()) {
switch (reader.NodeType) {
case XamlNodeType.None:
break;
case XamlNodeType.StartObject:
writer.WriteStartObject(reader.Type);
break;
case XamlNodeType.GetObject:
writer.WriteGetObject();
break;
case XamlNodeType.EndObject:
writer.WriteEndObject();
break;
case XamlNodeType.StartMember:
writer.WriteStartMember(reader.Member);
break;
case XamlNodeType.EndMember:
writer.WriteEndMember();
break;
case XamlNodeType.Value:
// requires XamlReaderSettings.ValuesMustBeString = true to work properly
writer.WriteValue(reader.Value);
break;
case XamlNodeType.NamespaceDeclaration:
writer.WriteNamespace(reader.Namespace);
break;
default:
throw new Exception("Invalid value for XamlNodeType");
}
}
return w.ToString();
}
}
}

1
ILSpy/ILSpy.csproj

@ -84,6 +84,7 @@ @@ -84,6 +84,7 @@
</Compile>
<Compile Include="AssemblyList.cs" />
<Compile Include="AssemblyListManager.cs" />
<Compile Include="BamlDecompiler.cs" />
<Compile Include="Controls\SearchBox.cs" />
<Compile Include="Controls\SortableGridViewColumn.cs" />
<Compile Include="CSharpLanguage.cs" />

2
ILSpy/TextView/DecompilerTextView.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy.TextView
/// When the task is cancelled before completing, the callback is not called; and any result
/// of the task (including exceptions) are ignored.
/// </summary>
void RunWithCancellation<T>(Func<CancellationToken, Task<T>> taskCreation, Action<Task<T>> taskCompleted)
public void RunWithCancellation<T>(Func<CancellationToken, Task<T>> taskCreation, Action<Task<T>> taskCompleted)
{
if (waitAdorner.Visibility != Visibility.Visible) {
waitAdorner.Visibility = Visibility.Visible;

88
ILSpy/TreeNodes/ResourceEntryNode.cs

@ -3,12 +3,11 @@ @@ -3,12 +3,11 @@
using System;
using System.IO;
using System.Windows;
using System.Windows.Baml2006;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Media.Imaging;
using System.Xaml;
using System.Xml;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler;
@ -44,17 +43,23 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -44,17 +43,23 @@ namespace ICSharpCode.ILSpy.TreeNodes
internal override bool View(DecompilerTextView textView)
{
AvalonEditTextOutput output = new AvalonEditTextOutput();
try {
if (LoadImage(output))
textView.Show(output, null);
else if (LoadBaml(output)) {
textView.Show(output, HighlightingManager.Instance.GetDefinitionByExtension(".xml"));
} else
return false;
} catch (Exception ex) {
output.Write(ex.ToString());
textView.Show(output, null);
}
IHighlightingDefinition highlighting = null;
textView.RunWithCancellation(
token => Task.Factory.StartNew(
() => {
try {
if (LoadImage(output))
highlighting = null;
else if (LoadBaml(output))
highlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml");
} catch (Exception ex) {
output.Write(ex.ToString());
}
return output;
}),
t => textView.Show(t.Result, highlighting)
);
return true;
}
@ -77,42 +82,25 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -77,42 +82,25 @@ namespace ICSharpCode.ILSpy.TreeNodes
bool LoadBaml(AvalonEditTextOutput output)
{
var asm = this.Ancestors().OfType<AssemblyTreeNode>().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;
// Create the second AppDomain.
AppDomain bamlDecompilerAppDomain = AppDomain.CreateDomain("BamlDecompiler AD", null, bamlDecompilerAppDomainSetup);
BamlDecompiler decompiler = (BamlDecompiler)bamlDecompilerAppDomain.CreateInstanceAndUnwrap(Assembly.GetEntryAssembly().FullName, typeof(BamlDecompiler).FullName);
MemoryStream bamlStream = new MemoryStream();
value.Position = 0;
TextWriter w = new StringWriter();
Baml2006Reader reader = new Baml2006Reader(value, new XamlReaderSettings() { ValuesMustBeString = true });
XamlXmlWriter writer = new XamlXmlWriter(new XmlTextWriter(w) { Formatting = Formatting.Indented }, reader.SchemaContext);
while (reader.Read()) {
switch (reader.NodeType) {
case XamlNodeType.None:
break;
case XamlNodeType.StartObject:
writer.WriteStartObject(reader.Type);
break;
case XamlNodeType.GetObject:
writer.WriteGetObject();
break;
case XamlNodeType.EndObject:
writer.WriteEndObject();
break;
case XamlNodeType.StartMember:
writer.WriteStartMember(reader.Member);
break;
case XamlNodeType.EndMember:
writer.WriteEndMember();
break;
case XamlNodeType.Value:
// requires XamlReaderSettings.ValuesMustBeString = true to work properly
writer.WriteValue(reader.Value);
break;
case XamlNodeType.NamespaceDeclaration:
writer.WriteNamespace(reader.Namespace);
break;
default:
throw new Exception("Invalid value for XamlNodeType");
}
}
output.Write(w.ToString());
value.CopyTo(bamlStream);
output.Write(decompiler.DecompileBaml(bamlStream, asm.FileName));
return true;
}

Loading…
Cancel
Save