Skip to content

Commit 3f8a801

Browse files
committed
使用外部exe解决32位下无法获取64位进程路径的问题
1 parent de59030 commit 3f8a801

3 files changed

Lines changed: 89 additions & 41 deletions

File tree

MisakaTranslator-WPF/MainWindow.xaml.cs

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,9 @@ private void Back_MouseLeftButtonDown(object sender, System.Windows.Input.MouseB
207207
private async Task StartTranslateByGid(int gid) {
208208
var pidList = new List<Process>();
209209

210-
foreach (var p in Process.GetProcesses())
211-
{
212-
try
213-
{
214-
if (p.MainModule.FileName == gameInfoList[gid].FilePath)
215-
pidList.Add(p);
216-
else
217-
p.Dispose();
218-
}
219-
catch (System.ComponentModel.Win32Exception)
220-
{
221-
//这个地方直接跳过,是因为32位程序确实会读到64位的系统进程,而系统进程是不能被访问的
222-
p.Dispose();
223-
}
224-
}
210+
foreach (var (pid, path) in ProcessHelper.GetProcessesData(gameInfoList[gid].Isx64))
211+
if (path == gameInfoList[gid].FilePath)
212+
pidList.Add(Process.GetProcessById(pid));
225213

226214
if (pidList.Count == 0) {
227215
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() {
393381
if (gameInfoList == null)
394382
return -1;
395383

396-
foreach (var process in Process.GetProcesses()) {
384+
foreach (var (_, path) in ProcessHelper.GetProcessesData(true))
397385
for (int j = 0; j < gameInfoList.Count; j++) {
398-
try
399-
{
400-
if (process.MainModule.FileName == gameInfoList[j].FilePath)
401-
return j;
402-
}
403-
catch (Win32Exception)
404-
{
405-
continue;
406-
}
407-
catch (InvalidOperationException)
408-
{
409-
continue;
410-
}
386+
if (path == gameInfoList[j].FilePath)
387+
return j;
411388
}
412-
process.Dispose();
413-
}
414389

415390
return -1;
416391
}

TextHookLibrary/ProcessHelper.cs

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77

88
namespace TextHookLibrary
99
{
10-
public class ProcessHelper
10+
public static class ProcessHelper
1111
{
12+
const string ExtPath = "lib\\ProcessHelperExt.exe";
1213

1314
/// <summary>
1415
/// 获得当前系统进程列表 形式:直接用于显示的字串和进程PID
1516
/// </summary>
1617
/// <returns></returns>
17-
public static Dictionary<string,int> GetProcessList_Name_PID()
18+
public static Dictionary<string, int> GetProcessList_Name_PID()
1819
{
1920
Dictionary<string, int> ret = new Dictionary<string, int>();
20-
21+
2122
//获取系统进程列表
2223
foreach (Process p in Process.GetProcesses())
2324
{
@@ -42,11 +43,8 @@ public static List<Process> FindSameNameProcess(int pid)
4243
string DesProcessName = Process.GetProcessById(pid).ProcessName;
4344

4445
List<Process> res = new List<Process>();
45-
foreach (Process p in Process.GetProcesses())
46-
if (p.ProcessName == DesProcessName)
47-
res.Add(p);
48-
else
49-
p.Dispose();
46+
foreach (Process p in Process.GetProcessesByName(DesProcessName))
47+
res.Add(p);
5048
return res;
5149
}
5250

@@ -62,11 +60,60 @@ public static string FindProcessPath(int pid)
6260
Process p = Process.GetProcessById(pid);
6361
return p.MainModule.FileName;
6462
}
65-
catch (System.ComponentModel.Win32Exception)
63+
catch (System.ComponentModel.Win32Exception e)
6664
{
67-
return "";
65+
if (e.NativeErrorCode != 299 || !System.IO.File.Exists(ExtPath))
66+
return "";
67+
68+
// Win32Exception:“A 32 bit processes cannot access modules of a 64 bit process.”
69+
// 通过调用外部64位程序,使主程序在32位下获取其它64位程序的路径。外部程序不存在或不是此错误时保持原有逻辑返回""
70+
var p = Process.Start(new ProcessStartInfo(ExtPath, pid.ToString())
71+
{
72+
UseShellExecute = false,
73+
RedirectStandardOutput = true,
74+
CreateNoWindow = true
75+
});
76+
string path = p.StandardOutput.ReadToEnd().TrimEnd();
77+
if (p.ExitCode == 3) // 不存在此pid对应的进程
78+
return "";
79+
else if (p.ExitCode != 0)
80+
throw new InvalidOperationException("Failed to execute ProcessHelper.exe");
81+
return path;
6882
}
6983
}
7084

85+
/// <summary>
86+
/// 返回 pid,绝对路径 的列表
87+
/// </summary>
88+
public static List<(int, string)> GetProcessesData(bool isx64game = false)
89+
{
90+
var l = new List<(int, string)>();
91+
// 在32位主程序、64位游戏(或想获取全部进程)、存在外部程序时调用
92+
if (isx64game && !Environment.Is64BitProcess && System.IO.File.Exists(ExtPath))
93+
{
94+
var p = Process.Start(new ProcessStartInfo(ExtPath)
95+
{
96+
UseShellExecute = false,
97+
RedirectStandardOutput = true,
98+
CreateNoWindow = true
99+
});
100+
string output = p.StandardOutput.ReadToEnd();
101+
if (p.ExitCode != 0)
102+
throw new InvalidOperationException("Failed to execute ProcessHelperExt.exe");
103+
104+
string[] lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
105+
foreach (string line in lines)
106+
{
107+
var parts = line.Split('|');
108+
l.Add((int.Parse(parts[0]), parts[1]));
109+
}
110+
}
111+
else
112+
foreach (var p in Process.GetProcesses())
113+
using (p)
114+
try { l.Add((p.Id, p.MainModule.FileName)); }
115+
catch (System.ComponentModel.Win32Exception) { }
116+
return l;
117+
}
71118
}
72119
}

Tools/ProcessHelperExt.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// 无参使用时输出所有进程的 pid|绝对路径,有参使用时输出指定pid进程的路径
2+
// 编译:csc ProcessHelperExt.cs /o /platform:x64
3+
using System;
4+
using System.Diagnostics;
5+
6+
if (args.Length > 1)
7+
return 1;
8+
9+
try
10+
{
11+
if (args.Length == 1)
12+
{
13+
int pid = int.Parse(args[0]);
14+
Process p;
15+
try { p = Process.GetProcessById(pid); }
16+
catch (System.ArgumentException) { return 3; } // 不存在pid对应的进程
17+
Console.WriteLine(p.MainModule.FileName);
18+
}
19+
else
20+
foreach (var p in Process.GetProcesses())
21+
try { Console.WriteLine("{0}|{1}", p.Id, p.MainModule.FileName); }
22+
catch (System.ComponentModel.Win32Exception) { } // 跳过权限不够的进程
23+
24+
return 0;
25+
}
26+
catch { return 2; }

0 commit comments

Comments
 (0)