using System; using System.IO; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Ast; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using Mono.Cecil; using System.Text; using ICSharpCode.ILSpy; using System.Collections.Generic; using ICSharpCode.NRefactory.TypeSystem; namespace Decomplier { class MainClass { private const string LAN_TYPE_CSHARP = "csharp"; private const string LAN_TYPE_IL = "il"; private static void showUsage() { Console.WriteLine(" Usage: ILSpyMac [options] directory/to/all/your/dll "); Console.WriteLine(" made it run at all platform support mono."); Console.WriteLine(" by aerror 2015/11/27"); Console.WriteLine(" options:"); Console.WriteLine(" -a Decompile yield. OFF if exists this option, default ON."); Console.WriteLine(" -b Decompile anonymous methods/lambdas. OFF if exists this option, default ON. "); Console.WriteLine(" -c Decompile asyncwait. OFF if exists this option, default ON. "); Console.WriteLine(" -d Decompile automatic events. OFF if exists this option, default ON. "); Console.WriteLine(" -e Decompile expression trees. OFF if exists this option, default ON. "); Console.WriteLine(" -f Decompile automatic properties. OFF if exists this option, default ON. "); Console.WriteLine(" -g Decompile using statements if. OFF exists this option, default ON. "); Console.WriteLine(" -h Decompile foreach statements. OFF if exists this option, default ON. "); Console.WriteLine(" -i Decompile lock statements if. OFF exists this option, default ON. "); Console.WriteLine(" -j Decompile SwitchStatement On String. OFF if exists this option, default ON. "); Console.WriteLine(" -k Decompile Using Declarations. OFF if exists this option, default ON. "); Console.WriteLine(" -l References dll path which dll will be loaded but not decompile , they use as References."); Console.WriteLine(" -n Solution Name"); Console.WriteLine(" -r Decompile query Expressions. OFF if exists this option, default ON. "); Console.WriteLine(" -s Decompile fully Qualify Ambiguous Type Names. OFF if exists this option, default ON. "); Console.WriteLine(" -t Output language type, accept il or csharp, default is csharp."); Console.WriteLine(" -p Use variable names from debug symbols, if available. OFF if exists this option, default ON. "); Console.WriteLine(" -x Use C# 3.0 object/collection initializers. OFF if exists this option, default ON. "); Console.WriteLine(" -y Include XML documentation comments in the decompiled code. OFF if exists this option, default ON."); Console.WriteLine(" -z Fold braces. ON if exists this option, default OFF "); Console.WriteLine(" -C class Name "); Console.WriteLine(" -D Ony specitfied files to do decompiling in the Directory"); Console.WriteLine(" Example:"); Console.WriteLine(" ILSpyMac -n Example -l /directory/to/Rerences/dll /directory/to/all/your/dll"); } public static bool isDecompilingFile(string fullName, List includedList) { if (includedList.Count == 0) return true; foreach (string x in includedList) { if (fullName.EndsWith(x)) { return true; } } return false; } public static bool praseDecompileSetting(char c, DecompilerSettings ds) { switch (c) { case 'a': ds.YieldReturn = false; break; case 'b': ds.AnonymousMethods = false; break; case 'c': ds.AsyncAwait = false; break; case 'd': ds.AutomaticEvents = false; break; case 'e': ds.ExpressionTrees = false; break; case 'f': ds.AutomaticProperties = false; break; case 'g': ds.UsingStatement = false; break; case 'h': ds.ForEachStatement = false; break; case 'i': ds.LockStatement = false; break; case 'j': ds.SwitchStatementOnString = false; break; case 'k': ds.UsingDeclarations = false; break; case 'r': ds.QueryExpressions = false; break; case 's': ds.FullyQualifyAmbiguousTypeNames = false; break; case 'p': ds.UseDebugSymbols = false; break; case 'x': ds.ObjectOrCollectionInitializers = false; break; case 'y': ds.ShowXmlDocumentation = false; break; case 'z': ds.FoldBraces = true; break; default: return false; } return true; } public static void Main(string[] args) { string appPath = null; string slnName = null; string libPath = null; string expOpt = null; string outLanguageType = LAN_TYPE_CSHARP; DecompilerSettings ds = new DecompilerSettings(); ds.AnonymousMethods = true; ds.AsyncAwait = true; ds.YieldReturn = true; ds.FullyQualifyAmbiguousTypeNames = true; string onlyDecomileClassName = null; List onlyDecompilingFileNameList = new List(); //parsing args foreach (string x in args) { if (x.StartsWith("-")) { switch (x) { case "-n": case "-l": case "-t": case "-C": case "-D": expOpt = x; continue; default: if (x.StartsWith("-")) { if (x.Length < 2) { Console.WriteLine(" Unexpected options " + x); showUsage(); return; } for (int i = 0; i < x.Length; i++) { if (!praseDecompileSetting(x[i], ds)) { Console.WriteLine(" Unexpected options " + x); showUsage(); return; } } continue; } break; } } else if (expOpt != null) { switch (expOpt) { case "-n": slnName = x; expOpt = null; break; case "-l": libPath = x; expOpt = null; break; case "-t": if (x != LAN_TYPE_CSHARP && x != LAN_TYPE_IL) { Console.WriteLine(" Unexpected Output language type: " + x); showUsage(); return; } outLanguageType = x; expOpt = null; break; case "-C": onlyDecomileClassName = x; expOpt = null; break; case "-D": onlyDecompilingFileNameList.Add(x); break; default: showUsage(); expOpt = null; return; } } else { if (appPath == null) { appPath = x; continue; } else { Console.WriteLine(" Unexpected options " + x); showUsage(); return; } } } if (appPath == null) { Console.WriteLine("directory/to/all/your/dll missing"); showUsage(); return; } if (slnName == null && outLanguageType == LAN_TYPE_CSHARP) { Console.WriteLine("Solution Name missing"); showUsage(); return; } Console.WriteLine("Decompiling all dll in " + appPath); Console.WriteLine("Please wait..."); DirectoryInfo di = null; FileInfo[] dllFileInfoList = null; FileInfo[] exeFileInfoList = null; if (File.Exists(appPath)) { var file = new FileInfo(appPath); di = file.Directory; if (file.Extension.ToLower().EndsWith("dll")) { dllFileInfoList = new FileInfo[] { file }; exeFileInfoList = new FileInfo[] { }; } else if (file.Extension.ToLower().EndsWith("exe")) { dllFileInfoList = new FileInfo[] { }; exeFileInfoList = new FileInfo[] { file }; } else { Console.WriteLine("directory/to/all/your/dll missing"); showUsage(); return; } } else if (Directory.Exists(appPath)) { di = new DirectoryInfo(appPath); dllFileInfoList = di.GetFiles("*.dll"); exeFileInfoList = di.GetFiles("*.exe"); } else { Console.WriteLine("directory/to/all/your/dll missing"); showUsage(); return; } appPath = di.FullName; AssemblyList asmlist = new AssemblyList("mylistname"); foreach (var dllfile in dllFileInfoList) { bool bDecompile = isDecompilingFile(dllfile.FullName, onlyDecompilingFileNameList); asmlist.OpenAssembly(dllfile.FullName, !bDecompile); } foreach (var dllfile in exeFileInfoList) { bool bDecompile = isDecompilingFile(dllfile.FullName, onlyDecompilingFileNameList); asmlist.OpenAssembly(dllfile.FullName, !bDecompile); } if (libPath != null) { di = new DirectoryInfo(libPath); libPath = di.FullName; dllFileInfoList = di.GetFiles("*.dll"); foreach (var dllfile in dllFileInfoList) { asmlist.OpenAssembly(dllfile.FullName, true); } } StringBuilder projSln = new StringBuilder(); projSln.Append("Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n"); StringBuilder globSec = new StringBuilder(); Guid slnProjGuid = Guid.NewGuid(); int num = 0; LoadedAssembly[] ls = asmlist.GetAssemblies(); var decompilationOptions = new DecompilationOptions(); decompilationOptions.FullDecompilation = true; decompilationOptions.DecompilerSettings = ds; #if MAC decompilationOptions.assenmlyList = asmlist; decompilationOptions.IncludedClassName = onlyDecomileClassName; #endif if (outLanguageType == LAN_TYPE_CSHARP) { foreach (LoadedAssembly asm in ls) { if (asm.IsAutoLoaded) continue; string projectPath = appPath + "/" + asm.ShortName; if (!Directory.Exists(projectPath)) { Directory.CreateDirectory(projectPath); } string projectFileName = projectPath + "/" + asm.ShortName + ".csproj"; #if MAC asm.ProjectGuid = Guid.NewGuid(); asm.ProjectFileName = projectFileName; #endif } } foreach (LoadedAssembly asm in ls) { num++; Console.WriteLine(asm.FileName + " " + num + "/" + ls.Length); if (asm.IsAutoLoaded) continue; if (outLanguageType == LAN_TYPE_CSHARP) { var csharpLanguage = new CSharpLanguage(); var textOutput = new PlainTextOutput(); decompilationOptions.SaveAsProjectDirectory = appPath + "/" + asm.ShortName; csharpLanguage.DecompileAssembly(asm, textOutput, decompilationOptions); #if MAC File.WriteAllText(asm.ProjectFileName, textOutput.ToString()); Guid createdProjGuid = asm.ProjectGuid; #else string projectPath = appPath + "/" + asm.ShortName; if (!Directory.Exists(projectPath)) { Directory.CreateDirectory(projectPath); } string projectFileName = projectPath + "/" + asm.ShortName + ".csproj"; File.WriteAllText(projectFileName, textOutput.ToString()); Guid createdProjGuid = Guid.NewGuid(); #endif projSln.Append(" Project(\"{"); projSln.Append(slnProjGuid.ToString()); projSln.Append("}\") = \""); projSln.Append(asm.ShortName); projSln.Append("\", \""); projSln.Append(asm.ShortName + "/" + asm.ShortName + ".csproj"); projSln.Append("\", \"{"); projSln.Append(createdProjGuid.ToString()); projSln.Append("}\"\n"); projSln.Append("EndProject\n"); globSec.Append(" {" + createdProjGuid.ToString() + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n"); globSec.Append(" {" + createdProjGuid.ToString() + "}.Debug|Any CPU.Build.0 = Debug|Any CPU\n"); globSec.Append(" {" + createdProjGuid.ToString() + "}.Release|Any CPU.ActiveCfg = Release|Any CPU\n"); globSec.Append(" {" + createdProjGuid.ToString() + "}.Release|Any CPU.Build.0 = Release|Any CPU\n"); } else { var ilLanguage = new ILLanguage(true); var textOutput = new PlainTextOutput(); ilLanguage.DecompileAssembly(asm, textOutput, decompilationOptions); string ilFileName = appPath + "/" + asm.ShortName + ".il"; File.WriteAllText(ilFileName, textOutput.ToString()); } } if (outLanguageType == LAN_TYPE_CSHARP) { projSln.Append("Global\n"); projSln.Append("GlobalSection(SolutionConfigurationPlatforms) = preSolution\n"); projSln.Append("\t\t\t\tDebug|Any CPU = Debug|Any CPU\n"); projSln.Append("\t\t\t\tRelease|Any CPU = Release|Any CPU\n"); projSln.Append("EndGlobalSection\n"); projSln.Append("GlobalSection(ProjectConfigurationPlatforms) = postSolution\n"); projSln.Append(globSec.ToString()); projSln.Append("EndGlobalSection\n"); projSln.Append("GlobalSection(MonoDevelopProperties) = preSolution\n"); projSln.Append("\nEndGlobalSection\n"); projSln.Append("EndGlobal\n\t\t"); string slnFileName = appPath + "/" + slnName + ".sln"; if (!File.Exists(slnFileName)) { File.WriteAllText(slnFileName, projSln.ToString()); } } } } }