Skip to content

Commit

Permalink
使用外部exe解决32位下无法获取64位进程路径的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
imba-tjd committed Feb 9, 2023
1 parent de59030 commit eb430cc
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
37 changes: 6 additions & 31 deletions MisakaTranslator-WPF/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,9 @@ private void Back_MouseLeftButtonDown(object sender, System.Windows.Input.MouseB
private async Task StartTranslateByGid(int gid) {
var pidList = new List<Process>();

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());
Expand Down Expand Up @@ -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;
}
Expand Down
69 changes: 58 additions & 11 deletions TextHookLibrary/ProcessHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@

namespace TextHookLibrary
{
public class ProcessHelper
public static class ProcessHelper
{
const string ExtPath = "lib\\ProcessHelperExt.exe";

/// <summary>
/// 获得当前系统进程列表 形式:直接用于显示的字串和进程PID
/// </summary>
/// <returns></returns>
public static Dictionary<string,int> GetProcessList_Name_PID()
public static Dictionary<string, int> GetProcessList_Name_PID()
{
Dictionary<string, int> ret = new Dictionary<string, int>();

//获取系统进程列表
foreach (Process p in Process.GetProcesses())
{
Expand All @@ -42,11 +43,8 @@ public static List<Process> FindSameNameProcess(int pid)
string DesProcessName = Process.GetProcessById(pid).ProcessName;

List<Process> res = new List<Process>();
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;
}

Expand All @@ -55,18 +53,67 @@ public static List<Process> FindSameNameProcess(int pid)
/// </summary>
/// <param name="pid"></param>
/// <returns></returns>
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;
}
}

/// <summary>
/// 返回 pid,绝对路径 的列表
/// </summary>
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;
}
}
}
26 changes: 26 additions & 0 deletions Tools/ProcessHelperExt.cs
Original file line number Diff line number Diff line change
@@ -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; }

0 comments on commit eb430cc

Please sign in to comment.