Browse Source

Use a custom assembly resolver when decompile a third party assembly. The order is: DefaultAssemblyResolver, folder where the decompiled assembly is located then GAC.

pull/15/merge
Eusebiu Marcu 14 years ago
parent
commit
8f2c5ffc1b
  1. 2
      src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj
  2. 216
      src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/Fusion.cs
  3. 118
      src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyAssemblyResolver.cs
  4. 3
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs

2
src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj

@ -64,6 +64,8 @@
<Link>Properties\GlobalAssemblyInfo.cs</Link> <Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile> </Compile>
<Compile Include="DebuggerDecompilerService.cs" /> <Compile Include="DebuggerDecompilerService.cs" />
<Compile Include="LaunchILSpy\Fusion.cs" />
<Compile Include="LaunchILSpy\ILSpyAssemblyResolver.cs" />
<Compile Include="NavigateToDecompiledEntityService.cs" /> <Compile Include="NavigateToDecompiledEntityService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="LaunchILSpy\ILSpyController.cs" /> <Compile Include="LaunchILSpy\ILSpyController.cs" />

216
src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/Fusion.cs

@ -0,0 +1,216 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
namespace ICSharpCode.ILSpyAddIn.LaunchILSpy
{
// .NET Fusion COM interfaces
[ComImport(), Guid("E707DCDE-D1CD-11D2-BAB9-00C04F8ECEAE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAssemblyCache
{
[PreserveSig()]
int UninstallAssembly(uint dwFlags,
[MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName,
IntPtr pvReserved,
out uint pulDisposition);
[PreserveSig()]
int QueryAssemblyInfo(uint dwFlags,
[MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName,
IntPtr pAsmInfo);
[PreserveSig()]
int CreateAssemblyCacheItem(uint dwFlags,
IntPtr pvReserved,
out IAssemblyCacheItem ppAsmItem,
[MarshalAs(UnmanagedType.LPWStr)] string pszAssemblyName);
[PreserveSig()]
int CreateAssemblyScavenger(out object ppAsmScavenger);
[PreserveSig()]
int InstallAssembly(uint dwFlags,
[MarshalAs(UnmanagedType.LPWStr)] string pszManifestFilePath,
IntPtr pvReserved);
}
[ComImport(), Guid("9E3AAEB4-D1CD-11D2-BAB9-00C04F8ECEAE"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAssemblyCacheItem
{
void CreateStream([MarshalAs(UnmanagedType.LPWStr)] string pszName,
uint dwFormat,
uint dwFlags,
uint dwMaxSize,
out IStream ppStream);
void IsNameEqual(IAssemblyName pName);
void Commit(uint dwFlags);
void MarkAssemblyVisible(uint dwFlags);
}
[ComImport(), Guid("CD193BC0-B4BC-11D2-9833-00C04FC31D2E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAssemblyName
{
[PreserveSig()]
int SetProperty(uint PropertyId, IntPtr pvProperty, uint cbProperty);
[PreserveSig()]
int GetProperty(uint PropertyId, IntPtr pvProperty, ref uint pcbProperty);
[PreserveSig()]
int Finalize();
[PreserveSig()]
int GetDisplayName([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder szDisplayName,
ref uint pccDisplayName,
uint dwDisplayFlags);
[PreserveSig()]
int BindToObject(object refIID,
object pAsmBindSink,
IApplicationContext pApplicationContext,
[MarshalAs(UnmanagedType.LPWStr)] string szCodeBase,
long llFlags,
int pvReserved,
uint cbReserved,
out int ppv);
[PreserveSig()]
int GetName(ref uint lpcwBuffer,
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwzName);
[PreserveSig()]
int GetVersion(out uint pdwVersionHi, out uint pdwVersionLow);
[PreserveSig()]
int IsEqual(IAssemblyName pName,
uint dwCmpFlags);
[PreserveSig()]
int Clone(out IAssemblyName pName);
}
[ComImport(), Guid("7C23FF90-33AF-11D3-95DA-00A024A85B51"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IApplicationContext
{
void SetContextNameObject(IAssemblyName pName);
void GetContextNameObject(out IAssemblyName ppName);
void Set([MarshalAs(UnmanagedType.LPWStr)] string szName,
int pvValue,
uint cbValue,
uint dwFlags);
void Get([MarshalAs(UnmanagedType.LPWStr)] string szName,
out int pvValue,
ref uint pcbValue,
uint dwFlags);
void GetDynamicDirectory(out int wzDynamicDir,
ref uint pdwSize);
}
[ComImport(), Guid("21B8916C-F28E-11D2-A473-00C04F8EF448"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IAssemblyEnum
{
[PreserveSig()]
int GetNextAssembly(out IApplicationContext ppAppCtx,
out IAssemblyName ppName,
uint dwFlags);
[PreserveSig()]
int Reset();
[PreserveSig()]
int Clone(out IAssemblyEnum ppEnum);
}
[ComImport(), Guid("1D23DF4D-A1E2-4B8B-93D6-6EA3DC285A54"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
internal interface IHistoryReader
{
[PreserveSig()]
int GetFilePath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder wzFilePath,
ref uint pdwSize);
[PreserveSig()]
int GetApplicationName([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder wzAppName,
ref uint pdwSize);
[PreserveSig()]
int GetEXEModulePath([Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder wzExePath,
ref uint pdwSize);
void GetNumActivations(out uint pdwNumActivations);
void GetActivationDate(uint dwIdx, // One-based!
out long /* FILETIME */ pftDate);
[PreserveSig()]
int GetRunTimeVersion(ref long /* FILETIME */ pftActivationDate,
[Out(), MarshalAs(UnmanagedType.LPWStr)] StringBuilder wzRunTimeVersion,
ref uint pdwSize);
void GetNumAssemblies(ref long /* FILETIME */ pftActivationDate,
out uint pdwNumAsms);
void GetHistoryAssembly(ref long /* FILETIME */ pftActivationDate,
uint dwIdx, // One-based!
[MarshalAs(UnmanagedType.IUnknown)] out object ppHistAsm);
}
internal static class Fusion
{
[DllImport("fusion.dll", CharSet=CharSet.Auto)]
internal static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache,
uint dwReserved);
// dwFlags: 1 = Enumerate native image (NGEN) assemblies
// 2 = Enumerate GAC assemblies
// 4 = Enumerate Downloaded assemblies
//
[DllImport("fusion.dll", CharSet=CharSet.Auto)]
internal static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum,
IApplicationContext pAppCtx,
IAssemblyName pName,
uint dwFlags,
int pvReserved);
[DllImport("fusion.dll", CharSet=CharSet.Auto)]
internal static extern int CreateAssemblyNameObject(out IAssemblyName ppName,
string szAssemblyName,
uint dwFlags,
int pvReserved);
// ?????
[DllImport("fusion.dll")]
internal static extern int CreateApplicationContext(out IApplicationContext ppAppContext,
uint dw);
[DllImport("fusion.dll")]
internal static extern int GetCachePath(uint flags,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder wzDir,
ref uint pdwSize);
public static string GetGacPath(bool isCLRv4 = false)
{
const uint ASM_CACHE_ROOT = 0x08; // CLR V2.0
const uint ASM_CACHE_ROOT_EX = 0x80; // CLR V4.0
uint flags = isCLRv4 ? ASM_CACHE_ROOT_EX : ASM_CACHE_ROOT;
const int size = 260; // MAX_PATH
StringBuilder b = new StringBuilder(size);
uint tmp = size;
GetCachePath(flags, b, ref tmp);
return b.ToString();
}
}
}

118
src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyAssemblyResolver.cs

@ -0,0 +1,118 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using System.Linq;
using System.Text;
using Mono.Cecil;
namespace ICSharpCode.ILSpyAddIn.LaunchILSpy
{
class ILSpyAssemblyResolver : DefaultAssemblyResolver
{
readonly DirectoryInfo directoryInfo;
public ILSpyAssemblyResolver(string decompiledAssemblyFolder)
{
if (string.IsNullOrEmpty(decompiledAssemblyFolder))
throw new ArgumentException("Invalid working folder");
this.directoryInfo = new DirectoryInfo(decompiledAssemblyFolder);
}
public override AssemblyDefinition Resolve(AssemblyNameReference name)
{
try {
// search default
var defaultAssembly = base.Resolve(name);
if (defaultAssembly != null)
return defaultAssembly;
} catch (AssemblyResolutionException) {
// serach into assemblyDecompiledFolder
var file = this.directoryInfo.GetFiles()
.Where(f => f != null && f.FullName.Contains(name.Name))
.FirstOrDefault();
if (file != null)
return AssemblyDefinition.ReadAssembly(file.FullName);
// search using ILSpy's GacInterop.FindAssemblyInNetGac()
string fileInGac = FindAssemblyInNetGac(name);
if (!string.IsNullOrEmpty(fileInGac))
return AssemblyDefinition.ReadAssembly(fileInGac);
}
return null;
}
#region FindAssemblyInGac
// This region is based on code from Mono.Cecil:
// Author:
// Jb Evain (jbevain@gmail.com)
//
// Copyright (c) 2008 - 2010 Jb Evain
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
static readonly string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) };
static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
static readonly string[] prefixes = { string.Empty, "v4.0_" };
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// </summary>
public static string FindAssemblyInNetGac (AssemblyNameReference reference)
{
// without public key, it can't be in the GAC
if (reference.PublicKeyToken == null)
return null;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < gacs.Length; j++) {
var gac = Path.Combine (gac_paths [i], gacs [j]);
var file = GetAssemblyFile (reference, prefixes [i], gac);
if (File.Exists (file))
return file;
}
}
return null;
}
static string GetAssemblyFile (AssemblyNameReference reference, string prefix, string gac)
{
var gac_folder = new StringBuilder ()
.Append (prefix)
.Append (reference.Version)
.Append ("__");
for (int i = 0; i < reference.PublicKeyToken.Length; i++)
gac_folder.Append (reference.PublicKeyToken [i].ToString ("x2"));
return Path.Combine (
Path.Combine (
Path.Combine (gac, reference.Name), gac_folder.ToString ()),
reference.Name + ".dll");
}
#endregion
}
}

3
src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs

@ -9,6 +9,7 @@ using System.Threading;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast; using ICSharpCode.Decompiler.Ast;
using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.ILSpyAddIn.ViewContent; using ICSharpCode.ILSpyAddIn.ViewContent;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Utils; using ICSharpCode.NRefactory.Utils;
@ -151,7 +152,7 @@ namespace ICSharpCode.ILSpyAddIn
ReaderParameters readerParameters = new ReaderParameters(); ReaderParameters readerParameters = new ReaderParameters();
// Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected // Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected
// once the code is decompiled. // once the code is decompiled.
readerParameters.AssemblyResolver = new DefaultAssemblyResolver(); readerParameters.AssemblyResolver = new ILSpyAssemblyResolver(Path.GetDirectoryName(assemblyFile));
ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters); ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters);
TypeDefinition typeDefinition = module.GetType(fullTypeName); TypeDefinition typeDefinition = module.GetType(fullTypeName);

Loading…
Cancel
Save