public IDecompileResult Decompile(string path, Action <string> msgSetter, CancellationToken?token = null, params string[] referlib) { PreDecompileCallback?.Invoke(); IDecompileResult result = RunDecompiler(path, msgSetter, token, referlib); AfterDecompileCallback?.Invoke(); return(result); }
protected override IDecompileResult RunDecompiler(string path, Action <string> msgSetter, CancellationToken?token, params string[] referlib) { string output = null; IDecompileResult result = Container.Resolve <IDecompileResult>(); //check if path is a directory if (Directory.Exists(path)) { output = Path.Combine(path, "decompiled"); path += "\\\\";//add backslash for fernflower Directory.CreateDirectory(output); } else if (File.Exists(path)) { output = Path.Combine(Path.GetDirectoryName(path), "decompiled"); Directory.CreateDirectory(output); } else { throw new ArgumentException($"Error:\"{path}\" is not a valid path!"); } string executePath = GlobalUtils.GlobalConfig.JavaPath; using (Process process = new Process()) { bool IsCancelled() => token.HasValue && token.Value.IsCancellationRequested == true; process.StartInfo.FileName = executePath; process.StartInfo.ErrorDialog = true; process.StartInfo.UseShellExecute = false; System.Windows.Application.Current.Dispatcher.Invoke(() => { var interop = new System.Windows.Interop.WindowInteropHelper(System.Windows.Application.Current.MainWindow); process.StartInfo.ErrorDialogParentHandle = interop.Handle; }); process.StartInfo.RedirectStandardOutput = true; process.StartInfo.RedirectStandardError = true; process.StartInfo.Arguments = "-jar " + Options.GetDecompilerPath() + Options.GetArgumentsString(path, output, referlib); process.StartInfo.CreateNoWindow = true; process.OutputDataReceived += (s, e) => { if (!IsCancelled()) { msgSetter.Invoke(e.Data); } else { process.Kill(); } }; process.ErrorDataReceived += (s, e) => { if (!string.IsNullOrWhiteSpace(e.Data)) { result.HasError = true; } if (!IsCancelled()) { if (!string.IsNullOrWhiteSpace(e.Data)) { msgSetter.Invoke(e.Data); } } else { process.Kill(); } }; process.Start(); try { if (!IsCancelled()) { try { process.ProcessorAffinity = (IntPtr)1; } catch (Exception) { } process.BeginOutputReadLine(); process.BeginErrorReadLine(); process.WaitForExit(); } else { process.Kill(); } } catch (Exception e) { if (!process.HasExited) { throw e; } } if (IsCancelled()) { throw new OperationCanceledException(); } else { result.OutputDir = output; result.ResultCode = result.HasError ? DecompileResultEnum.WithJavaException : DecompileResultEnum.Success; result.ReturnCode = process.ExitCode; return(result); } } }
protected override IDocumentViewModel _InnerOpenDocument(IJPath path) { DecompileDocumentViewModel viewModel; viewModel = Container.Resolve <DecompileDocumentViewModel>(); viewModel.Parent = this; viewModel.Title = Path.GetFileName(path.Path); Documents.Add(viewModel); /*viewModel.TokenSource = new CancellationTokenSource(); * viewModel.DecompileTask = new Task(() => * { * if (MapSourceToMd5.ContainsKey(path.Path)) * { * if (APIHelper.GetMd5Of(path.Path) == MapSourceToMd5[path.Path]) * { * //TODO * } * } * var basedir = Path.GetDirectoryName(path.Path); * var tempPath = Path.GetTempFileName(); * File.Delete(tempPath); * Directory.CreateDirectory(tempPath); * File.Copy(path.Path, Path.Combine(tempPath, Path.GetFileName(path.Path))); * foreach(var p in path.InnerClassPaths) * { * File.Copy(p, Path.Combine(tempPath, Path.GetFileName(p))); * } * var result = Decompiler.Decompile(tempPath, r => MessageWhole = r, viewModel.TokenSource.Token, BaseDirectory + "\\raw.jar"); * * if (result.ResultCode == CommonDecompiler.DecompileResultEnum.DecompileSuccess) * { * viewModel.Load(result.Output); * } * }); * viewModel.DecompileTask.Start();*/ viewModel.DecompTaskTokenSource = new CancellationTokenSource(); IBackgroundTask backgroundTask = null; backgroundTask = Container.Resolve <IBackgroundTaskBuilder>() .WithTask(async obj => { var token = obj as CancellationToken?; if (MapSourceToMd5.ContainsKey(path.Path)) { if (APIHelper.GetMd5Of(path.Path) == MapSourceToMd5[path.Path]) { //TODO } } var basedir = Path.GetDirectoryName(path.Path); var tempPath = Path.GetTempFileName(); File.Delete(tempPath); Directory.CreateDirectory(tempPath); File.Copy(path.Path, Path.Combine(tempPath, Path.GetFileName(path.Path))); if (path.InnerClassPaths != null) { foreach (var p in path.InnerClassPaths) { File.Copy(p, Path.Combine(tempPath, Path.GetFileName(p))); } } IDecompileResult result = null; try { result = Decompiler.Decompile(tempPath, r => { if (backgroundTask != null) { backgroundTask.TaskDescription = r; } }, token, BaseDirectory + "\\raw.jar"); if (result.ResultCode == DecompileResultEnum.Success) { var files = Directory.GetFiles(result.OutputDir); #if DEBUG Debug.Assert(files.Length == 1); #endif string newFileName = files[0]; if (EnableDecompiledFileCache) { newFileName = Path.Combine(basedir + '\\', Path.GetFileNameWithoutExtension(files[0]) + ".java"); File.Copy(files[0], newFileName, true); MapSourceToMd5.Add(newFileName, APIHelper.GetMd5Of(newFileName)); } StatusMessage = backgroundTask.TaskDescription = "Processing " + path.ClassPath; await viewModel.LoadAsync(newFileName, path); Application.Current.Dispatcher.Invoke(() => { if (!(Manager.ActiveContent is IDocumentViewModel)) { ActivateDocument(viewModel); } }); } else { Container.Resolve <IDialogService>().ReportError(result.ResultCode.ToString(), _ => { }); Application.Current.Dispatcher.Invoke(() => { Documents.Remove(viewModel); }); } } catch (Exception e) { if (e is OperationCanceledException) { Application.Current.Dispatcher.Invoke(() => { Documents.Remove(viewModel); }); } else { string message = null; if (e is Win32Exception win32Exception) { message = $"Unexpected exception:\n{win32Exception.Message}\nHRESULT is {System.Runtime.InteropServices.Marshal.GetHRForLastWin32Error().ToString("x")}"; } else { message = $"Unexpected exception:\n{e.Message}\n"; } Container.Resolve <IDialogService>().ReportError(message, r => { }, e.StackTrace); Application.Current.Dispatcher.Invoke(() => { Documents.Remove(viewModel); }); } } if (token.HasValue) { token.Value.ThrowIfCancellationRequested(); } Directory.Delete(tempPath, true); StatusMessage = "Ready"; }, viewModel.DecompTaskTokenSource.Token) .WithName($"{Decompiler.GetDecompilerInfo().FriendlyName}:{Path.GetFileName(path.Path)}") .WithDescription($"Decompiler started") .Build(); viewModel.AttachDecompileTask(backgroundTask); viewModel.BackgroundTask.Start(); return(viewModel); }