Main.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. using System;
  2. using System.IO;
  3. using ICSharpCode.Decompiler;
  4. using ICSharpCode.Decompiler.Ast;
  5. using ICSharpCode.NRefactory;
  6. using ICSharpCode.NRefactory.CSharp;
  7. using Mono.Cecil;
  8. using System.Text;
  9. using ICSharpCode.ILSpy;
  10. using System.Collections.Generic;
  11. using ICSharpCode.NRefactory.TypeSystem;
  12. namespace Decomplier
  13. {
  14. class MainClass
  15. {
  16. private const string LAN_TYPE_CSHARP = "csharp";
  17. private const string LAN_TYPE_IL = "il";
  18. private static void showUsage()
  19. {
  20. Console.WriteLine(" Usage: ILSpyMac [options] directory/to/all/your/dll ");
  21. Console.WriteLine(" made it run at all platform support mono.");
  22. Console.WriteLine(" by aerror 2015/11/27");
  23. Console.WriteLine(" options:");
  24. Console.WriteLine(" -a Decompile yield. OFF if exists this option, default ON.");
  25. Console.WriteLine(" -b Decompile anonymous methods/lambdas. OFF if exists this option, default ON. ");
  26. Console.WriteLine(" -c Decompile asyncwait. OFF if exists this option, default ON. ");
  27. Console.WriteLine(" -d Decompile automatic events. OFF if exists this option, default ON. ");
  28. Console.WriteLine(" -e Decompile expression trees. OFF if exists this option, default ON. ");
  29. Console.WriteLine(" -f Decompile automatic properties. OFF if exists this option, default ON. ");
  30. Console.WriteLine(" -g Decompile using statements if. OFF exists this option, default ON. ");
  31. Console.WriteLine(" -h Decompile foreach statements. OFF if exists this option, default ON. ");
  32. Console.WriteLine(" -i Decompile lock statements if. OFF exists this option, default ON. ");
  33. Console.WriteLine(" -j Decompile SwitchStatement On String. OFF if exists this option, default ON. ");
  34. Console.WriteLine(" -k Decompile Using Declarations. OFF if exists this option, default ON. ");
  35. Console.WriteLine(" -l References dll path which dll will be loaded but not decompile , they use as References.");
  36. Console.WriteLine(" -n Solution Name");
  37. Console.WriteLine(" -r Decompile query Expressions. OFF if exists this option, default ON. ");
  38. Console.WriteLine(" -s Decompile fully Qualify Ambiguous Type Names. OFF if exists this option, default ON. ");
  39. Console.WriteLine(" -t Output language type, accept il or csharp, default is csharp.");
  40. Console.WriteLine(" -p Use variable names from debug symbols, if available. OFF if exists this option, default ON. ");
  41. Console.WriteLine(" -x Use C# 3.0 object/collection initializers. OFF if exists this option, default ON. ");
  42. Console.WriteLine(" -y Include XML documentation comments in the decompiled code. OFF if exists this option, default ON.");
  43. Console.WriteLine(" -z Fold braces. ON if exists this option, default OFF ");
  44. Console.WriteLine(" -C class Name ");
  45. Console.WriteLine(" -D Ony specitfied files to do decompiling in the Directory");
  46. Console.WriteLine(" Example:");
  47. Console.WriteLine(" ILSpyMac -n Example -l /directory/to/Rerences/dll /directory/to/all/your/dll");
  48. }
  49. public static bool isDecompilingFile(string fullName, List<string> includedList)
  50. {
  51. if (includedList.Count == 0)
  52. return true;
  53. foreach (string x in includedList)
  54. {
  55. if (fullName.EndsWith(x))
  56. {
  57. return true;
  58. }
  59. }
  60. return false;
  61. }
  62. public static bool praseDecompileSetting(char c, DecompilerSettings ds)
  63. {
  64. switch (c)
  65. {
  66. case 'a':
  67. ds.YieldReturn = false;
  68. break;
  69. case 'b':
  70. ds.AnonymousMethods = false;
  71. break;
  72. case 'c':
  73. ds.AsyncAwait = false;
  74. break;
  75. case 'd':
  76. ds.AutomaticEvents = false;
  77. break;
  78. case 'e':
  79. ds.ExpressionTrees = false;
  80. break;
  81. case 'f':
  82. ds.AutomaticProperties = false;
  83. break;
  84. case 'g':
  85. ds.UsingStatement = false;
  86. break;
  87. case 'h':
  88. ds.ForEachStatement = false;
  89. break;
  90. case 'i':
  91. ds.LockStatement = false;
  92. break;
  93. case 'j':
  94. ds.SwitchStatementOnString = false;
  95. break;
  96. case 'k':
  97. ds.UsingDeclarations = false;
  98. break;
  99. case 'r':
  100. ds.QueryExpressions = false;
  101. break;
  102. case 's':
  103. ds.FullyQualifyAmbiguousTypeNames = false;
  104. break;
  105. case 'p':
  106. ds.UseDebugSymbols = false;
  107. break;
  108. case 'x':
  109. ds.ObjectOrCollectionInitializers = false;
  110. break;
  111. case 'y':
  112. ds.ShowXmlDocumentation = false;
  113. break;
  114. case 'z':
  115. ds.FoldBraces = true;
  116. break;
  117. default:
  118. return false;
  119. }
  120. return true;
  121. }
  122. public static void Main(string[] args)
  123. {
  124. string appPath = null;
  125. string slnName = null;
  126. string libPath = null;
  127. string expOpt = null;
  128. string outLanguageType = LAN_TYPE_CSHARP;
  129. DecompilerSettings ds = new DecompilerSettings();
  130. ds.AnonymousMethods = true;
  131. ds.AsyncAwait = true;
  132. ds.YieldReturn = true;
  133. ds.FullyQualifyAmbiguousTypeNames = true;
  134. string onlyDecomileClassName = null;
  135. List<string> onlyDecompilingFileNameList = new List<string>();
  136. //parsing args
  137. foreach (string x in args)
  138. {
  139. if (x.StartsWith("-"))
  140. {
  141. switch (x)
  142. {
  143. case "-n":
  144. case "-l":
  145. case "-t":
  146. case "-C":
  147. case "-D":
  148. expOpt = x;
  149. continue;
  150. default:
  151. if (x.StartsWith("-"))
  152. {
  153. if (x.Length < 2)
  154. {
  155. Console.WriteLine(" Unexpected options " + x);
  156. showUsage();
  157. return;
  158. }
  159. for (int i = 0; i < x.Length; i++)
  160. {
  161. if (!praseDecompileSetting(x[i], ds))
  162. {
  163. Console.WriteLine(" Unexpected options " + x);
  164. showUsage();
  165. return;
  166. }
  167. }
  168. continue;
  169. }
  170. break;
  171. }
  172. }
  173. else if (expOpt != null)
  174. {
  175. switch (expOpt)
  176. {
  177. case "-n":
  178. slnName = x;
  179. expOpt = null;
  180. break;
  181. case "-l":
  182. libPath = x;
  183. expOpt = null;
  184. break;
  185. case "-t":
  186. if (x != LAN_TYPE_CSHARP && x != LAN_TYPE_IL)
  187. {
  188. Console.WriteLine(" Unexpected Output language type: " + x);
  189. showUsage();
  190. return;
  191. }
  192. outLanguageType = x;
  193. expOpt = null;
  194. break;
  195. case "-C":
  196. onlyDecomileClassName = x;
  197. expOpt = null;
  198. break;
  199. case "-D":
  200. onlyDecompilingFileNameList.Add(x);
  201. break;
  202. default:
  203. showUsage();
  204. expOpt = null;
  205. return;
  206. }
  207. }
  208. else
  209. {
  210. if (appPath == null)
  211. {
  212. appPath = x;
  213. continue;
  214. }
  215. else
  216. {
  217. Console.WriteLine(" Unexpected options " + x);
  218. showUsage();
  219. return;
  220. }
  221. }
  222. }
  223. if (appPath == null)
  224. {
  225. Console.WriteLine("directory/to/all/your/dll missing");
  226. showUsage();
  227. return;
  228. }
  229. if (slnName == null && outLanguageType == LAN_TYPE_CSHARP)
  230. {
  231. Console.WriteLine("Solution Name missing");
  232. showUsage();
  233. return;
  234. }
  235. Console.WriteLine("Decompiling all dll in " + appPath);
  236. Console.WriteLine("Please wait...");
  237. DirectoryInfo di = null;
  238. FileInfo[] dllFileInfoList = null;
  239. FileInfo[] exeFileInfoList = null;
  240. if (File.Exists(appPath))
  241. {
  242. var file = new FileInfo(appPath);
  243. di = file.Directory;
  244. if (file.Extension.ToLower().EndsWith("dll"))
  245. {
  246. dllFileInfoList = new FileInfo[] { file };
  247. exeFileInfoList = new FileInfo[] { };
  248. }
  249. else if (file.Extension.ToLower().EndsWith("exe"))
  250. {
  251. dllFileInfoList = new FileInfo[] { };
  252. exeFileInfoList = new FileInfo[] { file };
  253. }
  254. else
  255. {
  256. Console.WriteLine("directory/to/all/your/dll missing");
  257. showUsage();
  258. return;
  259. }
  260. }
  261. else if (Directory.Exists(appPath))
  262. {
  263. di = new DirectoryInfo(appPath);
  264. dllFileInfoList = di.GetFiles("*.dll");
  265. exeFileInfoList = di.GetFiles("*.exe");
  266. }
  267. else
  268. {
  269. Console.WriteLine("directory/to/all/your/dll missing");
  270. showUsage();
  271. return;
  272. }
  273. appPath = di.FullName;
  274. AssemblyList asmlist = new AssemblyList("mylistname");
  275. foreach (var dllfile in dllFileInfoList)
  276. {
  277. bool bDecompile = isDecompilingFile(dllfile.FullName, onlyDecompilingFileNameList);
  278. asmlist.OpenAssembly(dllfile.FullName, !bDecompile);
  279. }
  280. foreach (var dllfile in exeFileInfoList)
  281. {
  282. bool bDecompile = isDecompilingFile(dllfile.FullName, onlyDecompilingFileNameList);
  283. asmlist.OpenAssembly(dllfile.FullName, !bDecompile);
  284. }
  285. if (libPath != null)
  286. {
  287. di = new DirectoryInfo(libPath);
  288. libPath = di.FullName;
  289. dllFileInfoList = di.GetFiles("*.dll");
  290. foreach (var dllfile in dllFileInfoList)
  291. {
  292. asmlist.OpenAssembly(dllfile.FullName, true);
  293. }
  294. }
  295. StringBuilder projSln = new StringBuilder();
  296. projSln.Append("Microsoft Visual Studio Solution File, Format Version 11.00\n# Visual Studio 2010\n");
  297. StringBuilder globSec = new StringBuilder();
  298. Guid slnProjGuid = Guid.NewGuid();
  299. int num = 0;
  300. LoadedAssembly[] ls = asmlist.GetAssemblies();
  301. var decompilationOptions = new DecompilationOptions();
  302. decompilationOptions.FullDecompilation = true;
  303. decompilationOptions.DecompilerSettings = ds;
  304. #if MAC
  305. decompilationOptions.assenmlyList = asmlist;
  306. decompilationOptions.IncludedClassName = onlyDecomileClassName;
  307. #endif
  308. if (outLanguageType == LAN_TYPE_CSHARP)
  309. {
  310. foreach (LoadedAssembly asm in ls)
  311. {
  312. if (asm.IsAutoLoaded)
  313. continue;
  314. string projectPath = appPath + "/" + asm.ShortName;
  315. if (!Directory.Exists(projectPath))
  316. {
  317. Directory.CreateDirectory(projectPath);
  318. }
  319. string projectFileName = projectPath + "/" + asm.ShortName + ".csproj";
  320. #if MAC
  321. asm.ProjectGuid = Guid.NewGuid();
  322. asm.ProjectFileName = projectFileName;
  323. #endif
  324. }
  325. }
  326. foreach (LoadedAssembly asm in ls)
  327. {
  328. num++;
  329. Console.WriteLine(asm.FileName + " " + num + "/" + ls.Length);
  330. if (asm.IsAutoLoaded)
  331. continue;
  332. if (outLanguageType == LAN_TYPE_CSHARP)
  333. {
  334. var csharpLanguage = new CSharpLanguage();
  335. var textOutput = new PlainTextOutput();
  336. decompilationOptions.SaveAsProjectDirectory = appPath + "/" + asm.ShortName;
  337. csharpLanguage.DecompileAssembly(asm, textOutput, decompilationOptions);
  338. #if MAC
  339. File.WriteAllText(asm.ProjectFileName, textOutput.ToString());
  340. Guid createdProjGuid = asm.ProjectGuid;
  341. #else
  342. string projectPath = appPath + "/" + asm.ShortName;
  343. if (!Directory.Exists(projectPath))
  344. {
  345. Directory.CreateDirectory(projectPath);
  346. }
  347. string projectFileName = projectPath + "/" + asm.ShortName + ".csproj";
  348. File.WriteAllText(projectFileName, textOutput.ToString());
  349. Guid createdProjGuid = Guid.NewGuid();
  350. #endif
  351. projSln.Append(" Project(\"{");
  352. projSln.Append(slnProjGuid.ToString());
  353. projSln.Append("}\") = \"");
  354. projSln.Append(asm.ShortName);
  355. projSln.Append("\", \"");
  356. projSln.Append(asm.ShortName + "/" + asm.ShortName + ".csproj");
  357. projSln.Append("\", \"{");
  358. projSln.Append(createdProjGuid.ToString());
  359. projSln.Append("}\"\n");
  360. projSln.Append("EndProject\n");
  361. globSec.Append(" {" + createdProjGuid.ToString() + "}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n");
  362. globSec.Append(" {" + createdProjGuid.ToString() + "}.Debug|Any CPU.Build.0 = Debug|Any CPU\n");
  363. globSec.Append(" {" + createdProjGuid.ToString() + "}.Release|Any CPU.ActiveCfg = Release|Any CPU\n");
  364. globSec.Append(" {" + createdProjGuid.ToString() + "}.Release|Any CPU.Build.0 = Release|Any CPU\n");
  365. }
  366. else
  367. {
  368. var ilLanguage = new ILLanguage(true);
  369. var textOutput = new PlainTextOutput();
  370. ilLanguage.DecompileAssembly(asm, textOutput, decompilationOptions);
  371. string ilFileName = appPath + "/" + asm.ShortName + ".il";
  372. File.WriteAllText(ilFileName, textOutput.ToString());
  373. }
  374. }
  375. if (outLanguageType == LAN_TYPE_CSHARP)
  376. {
  377. projSln.Append("Global\n");
  378. projSln.Append("GlobalSection(SolutionConfigurationPlatforms) = preSolution\n");
  379. projSln.Append("\t\t\t\tDebug|Any CPU = Debug|Any CPU\n");
  380. projSln.Append("\t\t\t\tRelease|Any CPU = Release|Any CPU\n");
  381. projSln.Append("EndGlobalSection\n");
  382. projSln.Append("GlobalSection(ProjectConfigurationPlatforms) = postSolution\n");
  383. projSln.Append(globSec.ToString());
  384. projSln.Append("EndGlobalSection\n");
  385. projSln.Append("GlobalSection(MonoDevelopProperties) = preSolution\n");
  386. projSln.Append("\nEndGlobalSection\n");
  387. projSln.Append("EndGlobal\n\t\t");
  388. string slnFileName = appPath + "/" + slnName + ".sln";
  389. if (!File.Exists(slnFileName))
  390. {
  391. File.WriteAllText(slnFileName, projSln.ToString());
  392. }
  393. }
  394. }
  395. }
  396. }