public static void WritePdb(PEFile file, CSharpDecompiler decompiler, DecompilerSettings settings, Stream targetStream) { MetadataBuilder metadata = new MetadataBuilder(); MetadataReader reader = file.Metadata; var entrypointHandle = MetadataTokens.MethodDefinitionHandle(file.Reader.PEHeaders.CorHeader.EntryPointTokenOrRelativeVirtualAddress); var hasher = SHA256.Create(); var sequencePointBlobs = new Dictionary <MethodDefinitionHandle, (DocumentHandle Document, BlobHandle SequencePoints)>(); var importScopeBlobs = new Dictionary <MethodDefinitionHandle, (DocumentHandle Document, BlobHandle ImportScope)>(); var emptyList = new List <SequencePoint>(); foreach (var handle in reader.GetTopLevelTypeDefinitions()) { var type = reader.GetTypeDefinition(handle); var name = metadata.GetOrAddDocumentName("ILSpy_Generated_" + type.GetFullTypeName(reader) + "_" + Guid.NewGuid() + ".cs"); var ast = decompiler.DecompileTypes(new[] { handle }); ast.InsertChildAfter(null, new Comment(" PDB and source generated by ICSharpCode.Decompiler " + decompilerVersion.FileVersion), Roles.Comment); var sourceText = SyntaxTreeToString(ast, settings); var sequencePoints = decompiler.CreateSequencePoints(ast).ToDictionary(sp => (MethodDefinitionHandle)sp.Key.Method.MetadataToken, sp => sp.Value); var sourceCheckSum = hasher.ComputeHash(Encoding.UTF8.GetBytes(sourceText)); var sourceBlob = WriteSourceToBlob(metadata, sourceText); var document = metadata.AddDocument(name, hashAlgorithm: metadata.GetOrAddGuid(HashAlgorithmSHA256), hash: metadata.GetOrAddBlob(sourceCheckSum), language: metadata.GetOrAddGuid(CSharpLanguageGuid)); metadata.AddCustomDebugInformation(document, metadata.GetOrAddGuid(DebugInfoEmbeddedSource), sourceBlob); foreach (var method in type.GetMethods()) { var methodDef = reader.GetMethodDefinition(method); if (!sequencePoints.TryGetValue(method, out var points)) { points = emptyList; } int localSignatureRowId; MethodBodyBlock methodBody; if (methodDef.RelativeVirtualAddress != 0) { methodBody = file.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); localSignatureRowId = methodBody.LocalSignature.IsNil ? 0 : MetadataTokens.GetRowNumber(methodBody.LocalSignature); } else { methodBody = null; localSignatureRowId = 0; } if (points.Count == 0) { sequencePointBlobs.Add(method, (default, default));
IEnumerable <Tuple <string, string> > WriteCodeFilesInProject(Metadata.PEFile module, CancellationToken cancellationToken) { var metadata = module.Metadata; var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy( delegate(TypeDefinitionHandle h) { var type = metadata.GetTypeDefinition(h); string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs"; if (string.IsNullOrEmpty(metadata.GetString(type.Namespace))) { return(file); } else { string dir = CleanUpFileName(metadata.GetString(type.Namespace)); if (directories.Add(dir)) { Directory.CreateDirectory(Path.Combine(targetDirectory, dir)); } return(Path.Combine(dir, file)); } }, StringComparer.OrdinalIgnoreCase).ToList(); int total = files.Count; var progress = this.ProgressIndicator; DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, settings); Parallel.ForEach( files, new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, CancellationToken = cancellationToken }, delegate(IGrouping <string, TypeDefinitionHandle> file) { using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) { try { CSharpDecompiler decompiler = CreateDecompiler(ts); decompiler.CancellationToken = cancellationToken; var syntaxTree = decompiler.DecompileTypes(file.ToArray()); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions)); } catch (Exception innerException) when(!(innerException is OperationCanceledException || innerException is DecompilerException)) { throw new DecompilerException(module, $"Error decompiling for '{file.Key}'", innerException); } } progress?.Report(new DecompilationProgress(total, file.Key)); }); return(files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken))); }
static void Decompile(string assemblyFileName, TextWriter output, string typeName = null) { ModuleDefinition module = LoadModule(assemblyFileName); var typeSystem = new DecompilerTypeSystem(module); CSharpDecompiler decompiler = new CSharpDecompiler(typeSystem, new DecompilerSettings()); decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); SyntaxTree syntaxTree; if (typeName == null) { syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(); } else { syntaxTree = decompiler.DecompileTypes(module.GetTypes().Where(td => string.Equals(td.FullName, typeName, StringComparison.OrdinalIgnoreCase))); } var visitor = new CSharpOutputVisitor(output, FormattingOptionsFactory.CreateSharpDevelop()); syntaxTree.AcceptVisitor(visitor); }
IEnumerable <Tuple <string, string> > WriteCodeFilesInProject(ModuleDefinition module, CancellationToken cancellationToken) { var files = module.Types.Where(IncludeTypeWhenDecompilingProject).GroupBy( delegate(TypeDefinition type) { string file = CleanUpFileName(type.Name) + ".cs"; if (string.IsNullOrEmpty(type.Namespace)) { return(file); } else { string dir = CleanUpFileName(type.Namespace); if (directories.Add(dir)) { Directory.CreateDirectory(Path.Combine(targetDirectory, dir)); } return(Path.Combine(dir, file)); } }, StringComparer.OrdinalIgnoreCase).ToList(); DecompilerTypeSystem ts = new DecompilerTypeSystem(module); Parallel.ForEach( files, new ParallelOptions { MaxDegreeOfParallelism = this.MaxDegreeOfParallelism, CancellationToken = cancellationToken }, delegate(IGrouping <string, TypeDefinition> file) { using (StreamWriter w = new StreamWriter(Path.Combine(targetDirectory, file.Key))) { CSharpDecompiler decompiler = CreateDecompiler(ts); decompiler.CancellationToken = cancellationToken; var syntaxTree = decompiler.DecompileTypes(file.ToArray()); syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, settings.CSharpFormattingOptions)); } }); return(files.Select(f => Tuple.Create("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken))); }