Browse Source

Added "Open From GAC" dialog.

pull/1/head
Daniel Grunwald 14 years ago
parent
commit
0c972544af
  1. 2
      ILSpy/AboutDialog.xaml
  2. 5
      ILSpy/App.xaml
  3. 129
      ILSpy/AssemblyListTreeNode.cs
  4. 39
      ILSpy/AssemblyTreeNode.cs
  5. 65
      ILSpy/ExtensionMethods.cs
  6. 216
      ILSpy/Fusion.cs
  7. 10
      ILSpy/ILSpy.csproj
  8. 3
      ILSpy/MainWindow.xaml
  9. 38
      ILSpy/MainWindow.xaml.cs
  10. 39
      ILSpy/OpenFromGacDialog.xaml
  11. 180
      ILSpy/OpenFromGacDialog.xaml.cs
  12. 210
      ILSpy/SortableGridViewColumn.cs
  13. 25
      ILSpy/themes/generic.xaml

2
ILSpy/AboutDialog.xaml

@ -18,6 +18,6 @@ @@ -18,6 +18,6 @@
<Hyperlink NavigateUri="http://www.avalonedit.net/">ICSharpCode.AvalonEdit</Hyperlink><LineBreak/>
<Hyperlink NavigateUri="http://www.sharpdevelop.net/">SharpDevelop</Hyperlink> components (SharpTreeView, NRefactory)<LineBreak/>
</TextBlock>
<Button IsCancel="True" MinWidth="73" HorizontalAlignment="Center">Close</Button>
<Button IsCancel="True" HorizontalAlignment="Center">Close</Button>
</StackPanel>
</Window>

5
ILSpy/App.xaml

@ -8,5 +8,10 @@ @@ -8,5 +8,10 @@
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
</Style>
<Style TargetType="{x:Type Button}">
<Setter Property="MinWidth" Value="73" />
<Setter Property="Padding" Value="9,1,9,1" />
</Style>
</Application.Resources>
</Application>

129
ILSpy/AssemblyListTreeNode.cs

@ -3,16 +3,19 @@ @@ -3,16 +3,19 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents a list of assemblies.
/// </summary>
public sealed class AssemblyListTreeNode : SharpTreeNode
sealed class AssemblyListTreeNode : SharpTreeNode, IAssemblyResolver
{
public override bool CanDelete(SharpTreeNode[] nodes)
{
@ -34,5 +37,127 @@ namespace ICSharpCode.ILSpy @@ -34,5 +37,127 @@ namespace ICSharpCode.ILSpy
{
return requestedEffect;
}
public AssemblyTreeNode OpenAssembly(string file)
{
App.Current.Dispatcher.VerifyAccess();
file = Path.GetFullPath(file);
foreach (AssemblyTreeNode node in this.Children) {
if (file.Equals(node.FileName, StringComparison.OrdinalIgnoreCase))
return node;
}
var newNode = new AssemblyTreeNode(file, null, this);
this.Children.Add(newNode);
return newNode;
}
public AssemblyTreeNode OpenGacAssembly(string fullName)
{
App.Current.Dispatcher.VerifyAccess();
foreach (AssemblyTreeNode node in this.Children) {
if (fullName.Equals(node.FullName, StringComparison.OrdinalIgnoreCase))
return node;
}
string file = FindAssemblyInNetGac(AssemblyNameReference.Parse(fullName));
if (file != null) {
var newNode = new AssemblyTreeNode(file, fullName, this);
this.Children.Add(newNode);
return newNode;
} else {
return null;
}
}
AssemblyDefinition IAssemblyResolver.Resolve(AssemblyNameReference name)
{
var node = OpenGacAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters)
{
var node = OpenGacAssembly(name.FullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(string fullName)
{
var node = OpenGacAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
AssemblyDefinition IAssemblyResolver.Resolve(string fullName, ReaderParameters parameters)
{
var node = OpenGacAssembly(fullName);
return node != null ? node.AssemblyDefinition : null;
}
#region FindAssemblyInGac
// This region is taken 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 string FindAssemblyInNetGac (AssemblyNameReference reference)
{
string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) };
string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
string[] prefixes = { string.Empty, "v4.0_" };
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
}
}

39
ILSpy/AssemblyTreeNode.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using ICSharpCode.TreeView;
@ -15,20 +16,26 @@ namespace ICSharpCode.ILSpy @@ -15,20 +16,26 @@ namespace ICSharpCode.ILSpy
{
sealed class AssemblyTreeNode : SharpTreeNode
{
readonly IAssemblyResolver assemblyResolver;
readonly string fileName;
readonly string name;
string fullName;
string shortName;
readonly Task<AssemblyDefinition> assemblyTask;
readonly List<TypeTreeNode> classes = new List<TypeTreeNode>();
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
readonly SynchronizationContext syncContext;
public AssemblyTreeNode(string fileName)
public AssemblyTreeNode(string fileName, string fullName, IAssemblyResolver assemblyResolver)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
this.fileName = fileName;
this.fullName = fullName;
this.assemblyResolver = assemblyResolver;
this.assemblyTask = Task.Factory.StartNew<AssemblyDefinition>(LoadAssembly); // requires that this.fileName is set
this.name = Path.GetFileNameWithoutExtension(fileName);
this.shortName = Path.GetFileNameWithoutExtension(fileName);
this.syncContext = SynchronizationContext.Current;
this.LazyLoading = true;
}
@ -37,8 +44,16 @@ namespace ICSharpCode.ILSpy @@ -37,8 +44,16 @@ namespace ICSharpCode.ILSpy
get { return fileName; }
}
public string FullName {
get { return fullName ?? assemblyTask.Result.FullName; }
}
public AssemblyDefinition AssemblyDefinition {
get { return assemblyTask.Result; }
}
public override object Text {
get { return name; }
get { return shortName; }
}
public override object Icon {
@ -48,10 +63,24 @@ namespace ICSharpCode.ILSpy @@ -48,10 +63,24 @@ namespace ICSharpCode.ILSpy
AssemblyDefinition LoadAssembly()
{
// runs on background thread
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName);
ReaderParameters p = new ReaderParameters();
p.AssemblyResolver = assemblyResolver;
AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName, p);
foreach (TypeDefinition type in assembly.MainModule.Types.OrderBy(t => t.FullName)) {
classes.Add(new TypeTreeNode(type));
}
syncContext.Post(
delegate {
if (shortName != assembly.Name.Name) {
shortName = assembly.Name.Name;
RaisePropertyChanged("Text");
}
if (fullName != assembly.FullName) {
fullName = assembly.FullName;
RaisePropertyChanged("FullName");
}
}, null);
return assembly;
}

65
ILSpy/ExtensionMethods.cs

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
// 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.Windows;
using System.Windows.Markup;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// ExtensionMethods that help with WPF.
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Sets the value of a dependency property on <paramref name="targetObject"/> using a markup extension.
/// </summary>
/// <remarks>This method does not support markup extensions like x:Static that depend on
/// having a XAML file as context.</remarks>
public static void SetValueToExtension(this DependencyObject targetObject, DependencyProperty property, MarkupExtension markupExtension)
{
// This method was copied from ICSharpCode.Core.Presentation
if (targetObject == null)
throw new ArgumentNullException("targetObject");
if (property == null)
throw new ArgumentNullException("property");
if (markupExtension == null)
throw new ArgumentNullException("markupExtension");
var serviceProvider = new SetValueToExtensionServiceProvider(targetObject, property);
targetObject.SetValue(property, markupExtension.ProvideValue(serviceProvider));
}
sealed class SetValueToExtensionServiceProvider : IServiceProvider, IProvideValueTarget
{
// This class was copied from ICSharpCode.Core.Presentation
readonly DependencyObject targetObject;
readonly DependencyProperty targetProperty;
public SetValueToExtensionServiceProvider(DependencyObject targetObject, DependencyProperty property)
{
this.targetObject = targetObject;
this.targetProperty = property;
}
public object GetService(Type serviceType)
{
if (serviceType == typeof(IProvideValueTarget))
return this;
else
return null;
}
public object TargetObject {
get { return targetObject; }
}
public object TargetProperty {
get { return targetProperty; }
}
}
}
}

216
ILSpy/Fusion.cs

@ -0,0 +1,216 @@ @@ -0,0 +1,216 @@
// 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.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
namespace ICSharpCode.ILSpy
{
// .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();
}
}
}

10
ILSpy/ILSpy.csproj

@ -71,12 +71,18 @@ @@ -71,12 +71,18 @@
<Compile Include="AssemblyListTreeNode.cs" />
<Compile Include="AssemblyReferenceTreeNode.cs" />
<Compile Include="AssemblyTreeNode.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="FieldTreeNode.cs" />
<Compile Include="Fusion.cs" />
<Compile Include="Images\Images.cs" />
<Compile Include="MethodTreeNode.cs" />
<Compile Include="ModuleReferenceTreeNode.cs" />
<Compile Include="Mono.Cecil.Rocks\MethodBodyRocks.cs" />
<Compile Include="NamespaceTreeNode.cs" />
<Compile Include="OpenFromGacDialog.xaml.cs">
<DependentUpon>OpenFromGacDialog.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\WPFAssemblyInfo.cs" />
<Compile Include="MainWindow.xaml.cs">
@ -84,12 +90,15 @@ @@ -84,12 +90,15 @@
<DependentUpon>MainWindow.xaml</DependentUpon>
</Compile>
<Compile Include="ReferenceFolderTreeNode.cs" />
<Compile Include="SortableGridViewColumn.cs" />
<Compile Include="TreeTraversal.cs" />
<Compile Include="TypeTreeNode.cs" />
</ItemGroup>
<ItemGroup>
<Page Include="AboutDialog.xaml" />
<Page Include="MainWindow.xaml" />
<Page Include="OpenFromGacDialog.xaml" />
<Page Include="themes\generic.xaml" />
</ItemGroup>
<ItemGroup>
<Resource Include="Images\Class.png" />
@ -128,6 +137,7 @@ @@ -128,6 +137,7 @@
<ItemGroup>
<Folder Include="Images" />
<Folder Include="Mono.Cecil.Rocks" />
<Folder Include="themes" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Mono.Cecil\Mono.Cecil.csproj">

3
ILSpy/MainWindow.xaml

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
MinHeight="200"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
FocusManager.FocusedElement="{Binding ElementName=treeView}"
>
<Window.CommandBindings>
<CommandBinding
@ -28,6 +29,7 @@ @@ -28,6 +29,7 @@
Source="Images/Open.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Open from _GAC" Click="OpenFromGac_Click" />
<Separator />
<MenuItem
Header="E_xit"
@ -98,6 +100,7 @@ @@ -98,6 +100,7 @@
<DockPanel
Grid.Column="2">
<ae:TextEditor
Name="textEditor"
SyntaxHighlighting="C#"
FontFamily="Consolas"
FontSize="10pt"

38
ILSpy/MainWindow.xaml.cs

@ -18,7 +18,7 @@ namespace ICSharpCode.ILSpy @@ -18,7 +18,7 @@ namespace ICSharpCode.ILSpy
/// </summary>
public partial class MainWindow : Window
{
SharpTreeNodeCollection assemblies;
AssemblyListTreeNode assemblyList = new AssemblyListTreeNode();
static readonly Assembly[] initialAssemblies = {
typeof(object).Assembly,
@ -38,11 +38,11 @@ namespace ICSharpCode.ILSpy @@ -38,11 +38,11 @@ namespace ICSharpCode.ILSpy
{
InitializeComponent();
treeView.Root = new AssemblyListTreeNode();
assemblies = treeView.Root.Children;
textEditor.Text = "// Welcome to ILSpy!";
treeView.Root = assemblyList;
foreach (Assembly asm in initialAssemblies)
OpenAssembly(asm.Location);
assemblyList.OpenAssembly(asm.Location);
}
void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e)
@ -55,23 +55,13 @@ namespace ICSharpCode.ILSpy @@ -55,23 +55,13 @@ namespace ICSharpCode.ILSpy
if (dlg.ShowDialog() == true) {
treeView.UnselectAll();
foreach (string file in dlg.FileNames) {
treeView.SelectedItems.Add(OpenAssembly(file));
var asm = assemblyList.OpenAssembly(file);
if (asm != null)
treeView.SelectedItems.Add(asm);
}
}
}
AssemblyTreeNode OpenAssembly(string file)
{
file = Path.GetFullPath(file);
var node = assemblies.OfType<AssemblyTreeNode>().FirstOrDefault(a => file.Equals(a.FileName, StringComparison.OrdinalIgnoreCase));
if (node == null) {
node = new AssemblyTreeNode(file);
assemblies.Add(node);
}
return node;
}
void ExitClick(object sender, RoutedEventArgs e)
{
Close();
@ -83,5 +73,19 @@ namespace ICSharpCode.ILSpy @@ -83,5 +73,19 @@ namespace ICSharpCode.ILSpy
dlg.Owner = this;
dlg.ShowDialog();
}
void OpenFromGac_Click(object sender, RoutedEventArgs e)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = this;
if (dlg.ShowDialog() == true) {
treeView.UnselectAll();
foreach (string fullName in dlg.SelectedFullNames) {
var asm = assemblyList.OpenGacAssembly(fullName);
if (asm != null)
treeView.SelectedItems.Add(asm);
}
}
}
}
}

39
ILSpy/OpenFromGacDialog.xaml

@ -0,0 +1,39 @@ @@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="ICSharpCode.ILSpy.OpenFromGacDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:ICSharpCode.ILSpy"
Title="Open From GAC"
Style="{DynamicResource DialogWindow}"
WindowStartupLocation="CenterOwner"
ResizeMode="CanResizeWithGrip"
MinWidth="200"
MinHeight="150"
Height="350"
Width="650"
FocusManager.FocusedElement="{Binding ElementName=filterTextBox}">
<Grid
Margin="12,8">
<Grid.RowDefinitions>
<RowDefinition
Height="Auto" />
<RowDefinition
Height="1*" />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<TextBox Name="filterTextBox" TextChanged="FilterTextBox_TextChanged" />
<ListView Name="listView" Grid.Row="1" Margin="0, 8" local:SortableGridViewColumn.SortMode="Automatic" SelectionChanged="ListView_SelectionChanged">
<ListView.View>
<GridView>
<local:SortableGridViewColumn x:Name="nameColumn" Width="300" Header="Reference Name" DisplayMemberBinding="{Binding ShortName}" />
<local:SortableGridViewColumn Width="75" Header="Version" DisplayMemberBinding="{Binding Version}" />
<local:SortableGridViewColumn Width="80" Header="Culture" DisplayMemberBinding="{Binding Culture}" />
<local:SortableGridViewColumn Width="120" Header="Public Key Token" DisplayMemberBinding="{Binding PublicKeyToken}" />
</GridView>
</ListView.View>
</ListView>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button IsDefault="True" Margin="2,0" IsEnabled="False" Name="okButton" Click="OKButton_Click">Open</Button>
<Button IsCancel="True" Margin="2,0">Cancel</Button>
</StackPanel>
</Grid>
</Window>

180
ILSpy/OpenFromGacDialog.xaml.cs

@ -0,0 +1,180 @@ @@ -0,0 +1,180 @@
// 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.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Interaction logic for OpenFromGacDialog.xaml
/// </summary>
public partial class OpenFromGacDialog : Window
{
ObservableCollection<GacEntry> gacEntries = new ObservableCollection<GacEntry>();
ObservableCollection<GacEntry> filteredEntries = new ObservableCollection<GacEntry>();
volatile bool cancelFetchThread;
public OpenFromGacDialog()
{
InitializeComponent();
listView.ItemsSource = filteredEntries;
SortableGridViewColumn.SetCurrentSortColumn(listView, nameColumn);
SortableGridViewColumn.SetSortDirection(listView, ColumnSortDirection.Ascending);
new Thread(new ThreadStart(FetchGacContents)).Start();
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
cancelFetchThread = true;
}
#region Fetch Gac Contents
sealed class GacEntry : IEquatable<GacEntry>
{
readonly string fullAssemblyName;
readonly string shortName, culture, publicKeyToken;
readonly Version version;
public GacEntry(string fullAssemblyName)
{
this.fullAssemblyName = fullAssemblyName;
string[] components = fullAssemblyName.Split(',');
shortName = components[0];
for (int i = 1; i < components.Length; i++) {
string val = components[i].Trim();
int pos = val.IndexOf('=');
if (pos > 0) {
switch (val.Substring(0, pos)) {
case "Version":
string versionText = val.Substring(pos + 1);
Version.TryParse(versionText, out version);
break;
case "Culture":
culture = val.Substring(pos + 1);
break;
case "PublicKeyToken":
publicKeyToken = val.Substring(pos + 1);
break;
}
}
}
}
public string FullName {
get { return fullAssemblyName; }
}
public string ShortName {
get { return shortName; }
}
public Version Version {
get { return version; }
}
public string Culture {
get { return culture; }
}
public string PublicKeyToken {
get { return publicKeyToken; }
}
public override string ToString()
{
return fullAssemblyName;
}
public override int GetHashCode()
{
return fullAssemblyName.GetHashCode();
}
public override bool Equals(object obj)
{
return Equals(obj as GacEntry);
}
public bool Equals(GacEntry o)
{
return o != null && fullAssemblyName == o.fullAssemblyName;
}
}
IEnumerable<GacEntry> GetGacAssemblyFullNames()
{
IApplicationContext applicationContext = null;
IAssemblyEnum assemblyEnum = null;
IAssemblyName assemblyName = null;
Fusion.CreateAssemblyEnum(out assemblyEnum, null, null, 2, 0);
while (!cancelFetchThread && assemblyEnum.GetNextAssembly(out applicationContext, out assemblyName, 0) == 0) {
uint nChars = 0;
assemblyName.GetDisplayName(null, ref nChars, 0);
StringBuilder name = new StringBuilder((int)nChars);
assemblyName.GetDisplayName(name, ref nChars, 0);
yield return new GacEntry(name.ToString());
}
}
void FetchGacContents()
{
foreach (var entry in GetGacAssemblyFullNames().Distinct()) {
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action<GacEntry>(AddNewEntry), entry);
}
}
void AddNewEntry(GacEntry entry)
{
gacEntries.Add(entry);
string filter = filterTextBox.Text;
if (string.IsNullOrEmpty(filter) || entry.ShortName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)
filteredEntries.Add(entry);
}
#endregion
void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string filter = filterTextBox.Text;
filteredEntries.Clear();
foreach (GacEntry entry in gacEntries) {
if (string.IsNullOrEmpty(filter) || entry.ShortName.IndexOf(filter, StringComparison.OrdinalIgnoreCase) >= 0)
filteredEntries.Add(entry);
}
}
void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
okButton.IsEnabled = listView.SelectedItems.Count > 0;
}
void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
Close();
}
public string[] SelectedFullNames {
get {
return listView.SelectedItems.OfType<GacEntry>().Select(e => e.FullName).ToArray();
}
}
}
}

210
ILSpy/SortableGridViewColumn.cs

@ -0,0 +1,210 @@ @@ -0,0 +1,210 @@
// 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.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Allows to automatically sort a grid view.
/// </summary>
public class SortableGridViewColumn : GridViewColumn
{
// This class was copied from ICSharpCode.Core.Presentation.
static readonly ComponentResourceKey headerTemplateKey = new ComponentResourceKey(typeof(SortableGridViewColumn), "ColumnHeaderTemplate");
public SortableGridViewColumn()
{
this.SetValueToExtension(HeaderTemplateProperty, new DynamicResourceExtension(headerTemplateKey));
}
string sortBy;
public string SortBy {
get { return sortBy; }
set {
if (sortBy != value) {
sortBy = value;
OnPropertyChanged(new System.ComponentModel.PropertyChangedEventArgs("SortBy"));
}
}
}
#region SortDirection property
public static readonly DependencyProperty SortDirectionProperty =
DependencyProperty.RegisterAttached("SortDirection", typeof(ColumnSortDirection), typeof(SortableGridViewColumn),
new FrameworkPropertyMetadata(ColumnSortDirection.None, OnSortDirectionChanged));
public ColumnSortDirection SortDirection {
get { return (ColumnSortDirection)GetValue(SortDirectionProperty); }
set { SetValue(SortDirectionProperty, value); }
}
public static ColumnSortDirection GetSortDirection(ListView listView)
{
return (ColumnSortDirection)listView.GetValue(SortDirectionProperty);
}
public static void SetSortDirection(ListView listView, ColumnSortDirection value)
{
listView.SetValue(SortDirectionProperty, value);
}
static void OnSortDirectionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
ListView grid = sender as ListView;
if (grid != null) {
SortableGridViewColumn col = GetCurrentSortColumn(grid);
if (col != null)
col.SortDirection = (ColumnSortDirection)args.NewValue;
Sort(grid);
}
}
#endregion
#region CurrentSortColumn property
public static readonly DependencyProperty CurrentSortColumnProperty =
DependencyProperty.RegisterAttached("CurrentSortColumn", typeof(SortableGridViewColumn), typeof(SortableGridViewColumn),
new FrameworkPropertyMetadata(OnCurrentSortColumnChanged));
public static SortableGridViewColumn GetCurrentSortColumn(ListView listView)
{
return (SortableGridViewColumn)listView.GetValue(CurrentSortColumnProperty);
}
public static void SetCurrentSortColumn(ListView listView, SortableGridViewColumn value)
{
listView.SetValue(CurrentSortColumnProperty, value);
}
static void OnCurrentSortColumnChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
ListView grid = sender as ListView;
if (grid != null) {
SortableGridViewColumn oldColumn = (SortableGridViewColumn)args.OldValue;
if (oldColumn != null)
oldColumn.SortDirection = ColumnSortDirection.None;
SortableGridViewColumn newColumn = (SortableGridViewColumn)args.NewValue;
if (newColumn != null) {
newColumn.SortDirection = GetSortDirection(grid);
}
Sort(grid);
}
}
#endregion
#region SortMode property
public static readonly DependencyProperty SortModeProperty =
DependencyProperty.RegisterAttached("SortMode", typeof(ListViewSortMode), typeof(SortableGridViewColumn),
new FrameworkPropertyMetadata(ListViewSortMode.None, OnSortModeChanged));
public static ListViewSortMode GetSortMode(ListView listView)
{
return (ListViewSortMode)listView.GetValue(SortModeProperty);
}
public static void SetSortMode(ListView listView, ListViewSortMode value)
{
listView.SetValue(SortModeProperty, value);
}
static void OnSortModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
ListView grid = sender as ListView;
if (grid != null) {
if ((ListViewSortMode)args.NewValue != ListViewSortMode.None)
grid.AddHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler));
else
grid.RemoveHandler(GridViewColumnHeader.ClickEvent, new RoutedEventHandler(GridViewColumnHeaderClickHandler));
}
}
static void GridViewColumnHeaderClickHandler(object sender, RoutedEventArgs e)
{
ListView grid = sender as ListView;
GridViewColumnHeader headerClicked = e.OriginalSource as GridViewColumnHeader;
if (grid != null && headerClicked != null && headerClicked.Role != GridViewColumnHeaderRole.Padding) {
if (headerClicked.Column == GetCurrentSortColumn(grid)) {
if (GetSortDirection(grid) == ColumnSortDirection.Ascending)
SetSortDirection(grid, ColumnSortDirection.Descending);
else
SetSortDirection(grid, ColumnSortDirection.Ascending);
} else {
SetSortDirection(grid, ColumnSortDirection.Ascending);
SetCurrentSortColumn(grid, headerClicked.Column as SortableGridViewColumn);
}
}
}
#endregion
static void Sort(ListView grid)
{
ColumnSortDirection currentDirection = GetSortDirection(grid);
SortableGridViewColumn column = GetCurrentSortColumn(grid);
if (column != null && GetSortMode(grid) == ListViewSortMode.Automatic && currentDirection != ColumnSortDirection.None) {
ICollectionView dataView = CollectionViewSource.GetDefaultView(grid.ItemsSource);
string sortBy = column.SortBy;
if (sortBy == null) {
Binding binding = column.DisplayMemberBinding as Binding;
if (binding != null && binding.Path != null) {
sortBy = binding.Path.Path;
}
}
dataView.SortDescriptions.Clear();
if (sortBy != null) {
ListSortDirection direction;
if (currentDirection == ColumnSortDirection.Descending)
direction = ListSortDirection.Descending;
else
direction = ListSortDirection.Ascending;
dataView.SortDescriptions.Add(new SortDescription(sortBy, direction));
}
dataView.Refresh();
}
}
}
public enum ColumnSortDirection
{
None,
Ascending,
Descending
}
public enum ListViewSortMode
{
/// <summary>
/// Disable automatic sorting when sortable columns are clicked.
/// </summary>
None,
/// <summary>
/// Fully automatic sorting.
/// </summary>
Automatic,
/// <summary>
/// Automatically update SortDirection and CurrentSortColumn properties,
/// but do not actually sort the data.
/// </summary>
HalfAutomatic
}
sealed class ColumnSortDirectionToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Equals(value, parameter) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
}

25
ILSpy/themes/generic.xaml

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.ILSpy"
>
<!-- SortableGridViewColumn.
Displays an up arrow or down arrow in the column header when the grid is sorted using that column.
-->
<local:ColumnSortDirectionToVisibilityConverter x:Key="ColumnSortDirectionToVisibilityConverter"/>
<DataTemplate x:Key="{ComponentResourceKey {x:Type local:SortableGridViewColumn}, ColumnHeaderTemplate}">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Center" Text="{Binding}"/>
<Path x:Name="upArrow"
Visibility="{Binding Path=Column.SortDirection, ConverterParameter={x:Static local:ColumnSortDirection.Ascending}, RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}, Converter={StaticResource ColumnSortDirectionToVisibilityConverter}}"
StrokeThickness = "1"
Fill = "Gray"
Data = "M 5,10 L 15,10 L 10,5 L 5,10"/>
<Path x:Name="downArrow"
Visibility="{Binding Path=Column.SortDirection, ConverterParameter={x:Static local:ColumnSortDirection.Descending}, RelativeSource={RelativeSource AncestorType={x:Type GridViewColumnHeader}}, Converter={StaticResource ColumnSortDirectionToVisibilityConverter}}"
StrokeThickness = "1"
Fill = "Gray"
Data = "M 5,5 L 10,10 L 15,5 L 5,5"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
Loading…
Cancel
Save