📄 filedisassemblerhelper.cs
字号:
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Resources;
using System.Xml;
using Reflector.CodeModel;
using Reflector.CodeModel.Memory;
namespace Reflector.FileDisassembler
{
/// <summary>
/// Summary description for FileDisassemblerHelper.
/// </summary>
public class FileDisassemblerHelper
{
public delegate void WriteLineDelegate(string line);
public delegate void SetProgressBarDelegate(int pos);
private IAssemblyManager _assemblyManager;
private ILanguageManager _languageManager;
private ITranslatorManager _TranslatorManager;
private int _projectType = -1;
private string _outputDirectory = string.Empty;
private event WriteLineDelegate WriteLine;
private event SetProgressBarDelegate SetProgressBar;
private StringCollection _projectFiles = new StringCollection();
public FileDisassemblerHelper(
IAssemblyManager assemblyManager,
ITranslatorManager TranslatorManager,
ILanguageManager languageManager,
int projectType,
string outputDirectory,
WriteLineDelegate writeLineDelegate,
SetProgressBarDelegate setProgressBarDelegate)
{
_assemblyManager = assemblyManager;
_TranslatorManager = TranslatorManager;
_languageManager = languageManager;
_projectType = projectType;
_outputDirectory = outputDirectory;
WriteLine += writeLineDelegate;
SetProgressBar += setProgressBarDelegate;
}
public ILanguageManager LanguageManager
{
get { return _languageManager; }
}
public ITranslatorManager TranslatorManager
{
get { return _TranslatorManager; }
}
public IAssemblyManager AssemblyManager
{
get { return _assemblyManager; }
}
public int GenerateCode(object activeItem)
{
int exceptions = 0;
ILanguageWriterConfiguration configuration = new LanguageWriterConfiguration();
IAssemblyResolver resolver = AssemblyManager.Resolver;
AssemblyManager.Resolver = new AssemblyResolver(resolver);
try
{
// write assembly
IAssembly assembly = activeItem as IAssembly;
if (assembly != null)
{
// calc progress bar count
int pos = 0;
int count = 2; // 1 for the assembly info, 1 for the project
foreach (IModule module in assembly.Modules)
{
count += module.Types.Count;
}
count += assembly.Resources.Count;
// write assembly info
exceptions += WriteAssemblyInfo(assembly, configuration);
SetProgressBar((++pos * 100) / count);
// write modules
string location = string.Empty;
foreach (IModule module in assembly.Modules)
{
if (module.Location != location)
location = module.Location;
foreach (ITypeDeclaration typeDeclaration in module.Types)
{
if ((typeDeclaration.Namespace.Length != 0) || (
(typeDeclaration.Name != "<Module>") &&
(typeDeclaration.Name != "<PrivateImplementationDetails>")))
{
exceptions += WriteTypeDeclaration(typeDeclaration, configuration);
}
SetProgressBar((++pos * 100) / count);
}
}
// write resources
foreach (IResource resource in assembly.Resources)
{
exceptions += WriteResource(resource);
SetProgressBar((++pos * 100) / count);
}
GenerateVisualStudioProject(assembly.Name, _outputDirectory, assembly.Modules[0].AssemblyReferences);
SetProgressBar((++pos * 100) / count);
}
// write single item
else if (activeItem is ITypeDeclaration)
{
ITypeDeclaration typeDeclaration = activeItem as ITypeDeclaration;
if ((typeDeclaration.Namespace.Length != 0) || (
(typeDeclaration.Name != "<Module>") &&
(typeDeclaration.Name != "<PrivateImplementationDetails>")))
{
exceptions += WriteTypeDeclaration(typeDeclaration, configuration);
}
}
}
catch (Exception ex)
{
WriteLine("Error: " + ex.Message + Environment.NewLine + ex.StackTrace);
exceptions++;
}
finally
{
AssemblyManager.Resolver = resolver;
}
return exceptions;
}
private int WriteAssemblyInfo(IAssembly assembly, ILanguageWriterConfiguration configuration)
{
ILanguage language = LanguageManager.ActiveLanguage;
ITranslator translator = TranslatorManager.CreateDisassembler("Xml", null);
int exceptions = 0;
using (StreamWriter streamWriter = CreateFile(string.Empty, "AssemblyInfo"))
{
TextFormatter formatter = new TextFormatter();
try
{
ILanguageWriter writer = language.GetWriter(formatter, configuration);
assembly = translator.TranslateAssembly(assembly, false);
writer.WriteAssembly(assembly);
foreach (IModule module in assembly.Modules)
{
IModule visitedModule = translator.TranslateModule(module, false);
writer.WriteModule(visitedModule);
foreach (IAssemblyReference assemblyReference in module.AssemblyReferences)
{
IAssemblyReference visitedAssemblyReference = translator.TranslateAssemblyReference(assemblyReference);
writer.WriteAssemblyReference(visitedAssemblyReference);
}
foreach (IModuleReference moduleReference in module.ModuleReferences)
{
IModuleReference visitedModuleReference = translator.TranslateModuleReference(moduleReference);
writer.WriteModuleReference(visitedModuleReference);
}
}
foreach (IResource resource in assembly.Resources)
{
writer.WriteResource(resource);
}
}
catch (Exception exception)
{
streamWriter.WriteLine(exception.ToString());
WriteLine(exception.ToString());
exceptions++;
}
string output = formatter.ToString().Replace("\r\n", "\n").Replace("\n", "\r\n");
streamWriter.WriteLine(output);
}
return exceptions;
}
private int WriteTypeDeclaration(ITypeDeclaration typeDeclaration, ILanguageWriterConfiguration configuration)
{
ILanguage language = LanguageManager.ActiveLanguage;
ITranslator translator = TranslatorManager.CreateDisassembler("Xml", null);
int exceptions = 0;
using (StreamWriter streamWriter = CreateTypeDeclarationFile(typeDeclaration))
{
INamespace namespaceItem = new Namespace();
namespaceItem.Name = typeDeclaration.Namespace;
try
{
if (language.Translate)
{
typeDeclaration = translator.TranslateTypeDeclaration(typeDeclaration, true, true);
}
namespaceItem.Types.Add(typeDeclaration);
}
catch (Exception ex)
{
streamWriter.WriteLine(ex.ToString());
WriteLine(ex.ToString());
exceptions++;
}
TextFormatter formatter = new TextFormatter();
ILanguageWriter writer = language.GetWriter(formatter, configuration);
try
{
writer.WriteNamespace(namespaceItem);
}
catch (Exception exception)
{
streamWriter.WriteLine(exception.ToString());
WriteLine(exception.ToString());
}
string output = formatter.ToString().Replace("\r\n", "\n").Replace("\n", "\r\n");
streamWriter.WriteLine(output);
}
return exceptions;
}
private StreamWriter CreateTypeDeclarationFile(ITypeDeclaration typeDeclaration)
{
string directory = typeDeclaration.Namespace;
string fileName = typeDeclaration.Name;
if (typeDeclaration.GenericArguments.Count > 0)
{
fileName = fileName + "!" + typeDeclaration.GenericArguments.Count.ToString();
}
return CreateFile(directory, fileName);
}
private StreamWriter CreateFile(string directory, string fileName)
{
//somehow Path.InvalidPathChars does not include all invalid chars
ArrayList invalidPathChars = new ArrayList();
invalidPathChars.AddRange(Path.InvalidPathChars);
invalidPathChars.Add('^');
invalidPathChars.Add('<');
invalidPathChars.Add('>');
invalidPathChars.Add(':');
invalidPathChars.Add('|');
invalidPathChars.Add('?');
invalidPathChars.Add('*');
foreach(char invalidChar in invalidPathChars)
directory = directory.Replace(invalidChar, '_');
directory = Path.Combine(_outputDirectory, directory);
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
ILanguage language = LanguageManager.ActiveLanguage;
string fileExtension = language.FileExtension;
foreach(char invalidChar in invalidPathChars)
fileName = fileName.Replace(invalidChar, '_');
fileName = Path.Combine(directory, fileName);
fileName = Path.ChangeExtension(fileName, fileExtension);
AddToProjectFiles(fileName);
StreamWriter writer = null;
try
{
writer = new StreamWriter(fileName);
}
catch(NotSupportedException ex)
{
throw new ApplicationException(string.Format("Could not create file '{0}'", fileName), ex);
}
return writer;
}
private int WriteResource(IResource resource)
{
IEmbeddedResource embeddedResource = resource as IEmbeddedResource;
if (embeddedResource != null)
{
try
{
byte[] buffer = embeddedResource.Value;
string fileName = Path.Combine(_outputDirectory, resource.Name);
if (resource.Name.EndsWith(".resources"))
{
fileName = Path.ChangeExtension(fileName, ".resx");
using (MemoryStream ms = new MemoryStream(embeddedResource.Value))
{
ResXResourceWriter resxw = new ResXResourceWriter(fileName);
IResourceReader reader = new ResourceReader(ms);
IDictionaryEnumerator en = reader.GetEnumerator();
while (en.MoveNext())
{
resxw.AddResource(en.Key.ToString(), en.Value);
}
reader.Close();
resxw.Close();
}
}
else // other embedded resource
{
if (buffer != null)
{
using (Stream stream = File.Create(fileName))
{
stream.Write(buffer, 0, buffer.Length);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -