Would be a great addition at least for me.
And I successfully extended it as an experiment to diff dotnet assemblies with adding ilspy functions to it.
(just as an alternative to JustAssembly)
Doubleclicking an assembly triggers the comparison.
/// <summary>
/// Diff files as binary files.
/// </summary>
Binary,
/// <summary>
/// Diff files as assembly files.
/// </summary>
Assembly
}
...
public enum FileType
{
Unknown,
NotExisting,
Binary,
Assembly,
Text,
Xml
}
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using System.Threading;
private DiffBinaryTextResults GetFileLines(FileCompInfo fileA
,FileCompInfo fileB
,TextBinaryDiffArgs args
,IDiffProgress progress)
{
// Nothing to compare if both files do not exist
if (fileA.FileExists == false && fileB.FileExists == false)
return new DiffBinaryTextResults(CompareType.Text, new FileContentInfo(), new FileContentInfo());
if (args.CompareType == CompareType.Assembly ||
(args.IsAuto && fileA.Is == FileType.Assembly || fileB.Is == FileType.Assembly))
return GetAssemblyFileLines(fileA, fileB, args, progress);
if (args.CompareType == CompareType.Binary ||
(args.IsAuto && fileA.Is == FileType.Binary || fileB.Is == FileType.Binary))
return GetBinaryFileLines(fileA, fileB, args, progress);
...
private string DecompileAssembly(string assemblyFilePath)
{
if (String.IsNullOrEmpty(assemblyFilePath) || !File.Exists(assemblyFilePath)) return String.Empty;
try
{
var settings = new DecompilerSettings();
//settings = new DecompilerSettings { UsingDeclarations = false, ShowXmlDocumentation = false };
var decompiler = new CSharpDecompiler(assemblyFilePath, settings);
return decompiler.DecompileWholeModuleAsString();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
//Try to decompile as IL
try
{
using (var peFileStream = new FileStream(assemblyFilePath, FileMode.Open, FileAccess.Read))
using (var peFile = new PEFile(assemblyFilePath, peFileStream))
using (var writer = new StringWriter())
{
var output = new PlainTextOutput(writer);
ReflectionDisassembler rd = new ReflectionDisassembler(output, CancellationToken.None);
rd.DetectControlStructure = false;
//rd.ShowMetadataTokens = false;
//rd.ShowSequencePoints = false;
rd.WriteAssemblyReferences(peFile.Metadata);
var metadata = peFile.Metadata;
if (metadata.IsAssembly)
rd.WriteAssemblyHeader(peFile);
output.WriteLine();
rd.WriteModuleHeader(peFile);
output.WriteLine();
bool filterRvaAndCodeSize = true;
if (filterRvaAndCodeSize)
{
/*
StringBuilder result = new StringBuilder();
var sb = writer.GetStringBuilder(); //get the underlying StringBuilder
foreach (string line in sb.ToString().ReadLines())
{
if (!line.TrimStart().StartsWith("// Method begins at RVA") && !line.TrimStart().StartsWith("// Code size")) result.Append(line + Environment.NewLine);
}
return result.ToString();
*/
rd.WriteModuleContents(peFile, false);
}
else
{
rd.WriteModuleContents(peFile);
}
return writer.ToString();
}
}
catch (Exception ex2)
{
Console.WriteLine(ex2.ToString());
}
}
return string.Empty;
}
/// <summary>
/// Get Assembly file contents disassembled and rendered as text lines with line number marker at beginning of each line.
/// </summary>
/// <param name="fileA"></param>
/// <param name="fileB"></param>
/// <param name="args"></param>
/// <param name="progress"></param>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="leadingCharactersToIgnore">Leading number of characters to ignore for diff in each line.
/// This space is used in binary diff to display 8 digit line number and 4 digit space.</param>
private DiffBinaryTextResults GetAssemblyFileLines(FileCompInfo fileA, FileCompInfo fileB
, TextBinaryDiffArgs args
, IDiffProgress progress)
{
// Neither left nor right file exist or cannot be accessed
if (fileA.FileExists == false && fileB.FileExists == false)
return new DiffBinaryTextResults(CompareType.Assembly, new FileContentInfo(), new FileContentInfo());
string textA = DecompileAssembly(fileA.FileNamePath);
string textB = DecompileAssembly(fileB.FileNamePath);
FileContentInfo af = null, bf = null;
if (af == null || bf == null)
{
af = new FileContentInfo();
bf = new FileContentInfo();
af.Lines = DiffUtility.GetStringTextLines(textA, progress);
bf.Lines = DiffUtility.GetStringTextLines(textB, progress);
}
af.TextContent = textA;
bf.TextContent = textB;
DiffBinaryTextResults result = new DiffBinaryTextResults(CompareType.Text, af, bf);
return result;
}