diff --git a/MisakaTranslator-WPF/GuidePages/Hook/ChooseGamePage.xaml.cs b/MisakaTranslator-WPF/GuidePages/Hook/ChooseGamePage.xaml.cs index 74fefd6b..26be5646 100644 --- a/MisakaTranslator-WPF/GuidePages/Hook/ChooseGamePage.xaml.cs +++ b/MisakaTranslator-WPF/GuidePages/Hook/ChooseGamePage.xaml.cs @@ -61,7 +61,7 @@ private void ConfirmButton_Click(object sender, RoutedEventArgs e) } Common.GameID = -1; - string filepath = ProcessHelper.FindProcessPath(GamePid); + string filepath = ProcessHelper.FindProcessPath(GamePid, (bool)x64GameCheckBox.IsChecked); if (filepath != "") { Common.GameID = GameLibraryHelper.GetGameID(filepath); } diff --git a/MisakaTranslator-WPF/MainWindow.xaml.cs b/MisakaTranslator-WPF/MainWindow.xaml.cs index 68abc973..6d6253f8 100644 --- a/MisakaTranslator-WPF/MainWindow.xaml.cs +++ b/MisakaTranslator-WPF/MainWindow.xaml.cs @@ -207,21 +207,9 @@ private void Back_MouseLeftButtonDown(object sender, System.Windows.Input.MouseB private async Task StartTranslateByGid(int gid) { var pidList = new List(); - foreach (var p in Process.GetProcesses()) - { - try - { - if (p.MainModule.FileName == gameInfoList[gid].FilePath) - pidList.Add(p); - else - p.Dispose(); - } - catch (System.ComponentModel.Win32Exception) - { - //这个地方直接跳过,是因为32位程序确实会读到64位的系统进程,而系统进程是不能被访问的 - p.Dispose(); - } - } + foreach (var (pid, path) in ProcessHelper.GetProcessesData(gameInfoList[gid].Isx64)) + if (path == gameInfoList[gid].FilePath) + pidList.Add(Process.GetProcessById(pid)); if (pidList.Count == 0) { HandyControl.Controls.MessageBox.Show(Application.Current.Resources["MainWindow_StartError_Hint"].ToString(), Application.Current.Resources["MessageBox_Hint"].ToString()); @@ -393,24 +381,11 @@ private int GetGameListHasProcessGame_PID_ID() { if (gameInfoList == null) return -1; - foreach (var process in Process.GetProcesses()) { + foreach (var (_, path) in ProcessHelper.GetProcessesData(true)) for (int j = 0; j < gameInfoList.Count; j++) { - try - { - if (process.MainModule.FileName == gameInfoList[j].FilePath) - return j; - } - catch (Win32Exception) - { - continue; - } - catch (InvalidOperationException) - { - continue; - } + if (path == gameInfoList[j].FilePath) + return j; } - process.Dispose(); - } return -1; } diff --git a/TextHookLibrary/ProcessHelper.cs b/TextHookLibrary/ProcessHelper.cs index 7a59e4da..16cf50ab 100644 --- a/TextHookLibrary/ProcessHelper.cs +++ b/TextHookLibrary/ProcessHelper.cs @@ -7,17 +7,18 @@ namespace TextHookLibrary { - public class ProcessHelper + public static class ProcessHelper { + const string ExtPath = "lib\\ProcessHelperExt.exe"; /// /// 获得当前系统进程列表 形式:直接用于显示的字串和进程PID /// /// - public static Dictionary GetProcessList_Name_PID() + public static Dictionary GetProcessList_Name_PID() { Dictionary ret = new Dictionary(); - + //获取系统进程列表 foreach (Process p in Process.GetProcesses()) { @@ -42,11 +43,8 @@ public static List FindSameNameProcess(int pid) string DesProcessName = Process.GetProcessById(pid).ProcessName; List res = new List(); - foreach (Process p in Process.GetProcesses()) - if (p.ProcessName == DesProcessName) - res.Add(p); - else - p.Dispose(); + foreach (Process p in Process.GetProcessesByName(DesProcessName)) + res.Add(p); return res; } @@ -55,18 +53,67 @@ public static List FindSameNameProcess(int pid) /// /// /// - public static string FindProcessPath(int pid) + public static string FindProcessPath(int pid, bool isx64game = false) { try { Process p = Process.GetProcessById(pid); return p.MainModule.FileName; } - catch (System.ComponentModel.Win32Exception) + catch (System.ComponentModel.Win32Exception e) { - return ""; + if (!(isx64game && e.NativeErrorCode == 299 && System.IO.File.Exists(ExtPath))) + return ""; + + // Win32Exception:“A 32 bit processes cannot access modules of a 64 bit process.” + // 通过调用外部64位程序,使主程序在32位下获取其它64位程序的路径。外部程序不存在或不是此错误时保持原有逻辑返回"" + var p = Process.Start(new ProcessStartInfo(ExtPath, pid.ToString()) + { + UseShellExecute = false, + RedirectStandardOutput = true, + CreateNoWindow = true + }); + string path = p.StandardOutput.ReadToEnd().TrimEnd(); + if (p.ExitCode == 3) // 不存在此pid对应的进程 + return ""; + else if (p.ExitCode != 0) + throw new InvalidOperationException("Failed to execute ProcessHelper.exe"); + return path; } } + /// + /// 返回 pid,绝对路径 的列表 + /// + public static List<(int, string)> GetProcessesData(bool isx64game = false) + { + var l = new List<(int, string)>(); + // 在32位主程序、64位游戏(或想获取全部进程)、存在外部程序时调用 + if (isx64game && !Environment.Is64BitProcess && System.IO.File.Exists(ExtPath)) + { + var p = Process.Start(new ProcessStartInfo(ExtPath) + { + UseShellExecute = false, + RedirectStandardOutput = true, + CreateNoWindow = true + }); + string output = p.StandardOutput.ReadToEnd(); + if (p.ExitCode != 0) + throw new InvalidOperationException("Failed to execute ProcessHelperExt.exe"); + + string[] lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string line in lines) + { + var parts = line.Split('|'); + l.Add((int.Parse(parts[0]), parts[1])); + } + } + else + foreach (var p in Process.GetProcesses()) + using (p) + try { l.Add((p.Id, p.MainModule.FileName)); } + catch (System.ComponentModel.Win32Exception) { } + return l; + } } } diff --git a/Tools/ProcessHelperExt.cs b/Tools/ProcessHelperExt.cs new file mode 100644 index 00000000..505cbea4 --- /dev/null +++ b/Tools/ProcessHelperExt.cs @@ -0,0 +1,26 @@ +// 无参使用时输出所有进程的 pid|绝对路径,有参使用时输出指定pid进程的路径 +// 编译:csc ProcessHelperExt.cs /o /platform:x64 +using System; +using System.Diagnostics; + +if (args.Length > 1) + return 1; + +try +{ + if (args.Length == 1) + { + int pid = int.Parse(args[0]); + Process p; + try { p = Process.GetProcessById(pid); } + catch (System.ArgumentException) { return 3; } // 不存在pid对应的进程 + Console.WriteLine(p.MainModule.FileName); + } + else + foreach (var p in Process.GetProcesses()) + try { Console.WriteLine("{0}|{1}", p.Id, p.MainModule.FileName); } + catch (System.ComponentModel.Win32Exception) { } // 跳过权限不够的进程 + + return 0; +} +catch { return 2; }