通过steam://rungameid/获取启动Steam游戏后的进程ID或进程名称#

Get process Id or process name after launching a Steam game via steam://rungameid/#

有没有办法获取通过以下方式启动的 Steam 游戏的进程 name/id:

Process.Start("steam://rungameid/#");

果然如上方法returns Steam.exe.

一般不会。

Steam 仅使用自定义 URI 前缀,它允许您指定哪个应用程序将为该请求提供服务。但它不会为每个游戏创建新的前缀 - 相反,它由 steam.exe 处理,它决定实际 运行.

的应用程序

Steam 本身当然会跟踪它 运行 的游戏,但我认为它只是跟踪它们的进程 ID,可能受到 Steam 集成或 Steam 覆盖注入的影响以跟踪游戏使用启动器。如果您不愿意弄乱其他应用程序的私有信息,我认为没有任何简单的方法可以保留该信息。

在某些情况下,您可能有其他解决方案;例如如果您不介意同时 运行ning 多个 Steam 游戏,您可以尝试查找具有 Steam 覆盖的所有进程,但这些进程相当具体 - 它们可能适合您,但是其他用户失败。

由于新进程不会作为steam的子进程启动,因此无法推导出其id。不过,您可以尝试导出当前的 运行 游戏 via the API - 然后在所有 运行 进程中搜索它们的名称。 API 应该通过 gameextrainfo 属性 公开游戏的名称,这应该与进程的名称相同(尽管未经测试)。

每个游戏在 HKCU\SOFTWARE\Valve\Steam\Apps

下的注册表中都有一个密钥

您应该可以从那里检查游戏的 Installed 值,然后 运行 使用 steam://rungameid/# 的游戏,然后等待 RunningUpdating 值更改为 1,然后再次更改为 0

这使得跟踪游戏执行成为可能,但是,您仍然无法直接获得游戏的进程 ID。

这是一个老问题,但我刚刚完成了同样的事情(对于一个与您正在从事的项目有点相似的项目)。您可以使用 System.Management 中的 ManagementObjects 来查找进程的 ParentId。如果您正在启动 Steam,您将拥有 Steam 的进程 ID,尽管您当前启动游戏的方式,您将需要查找 Steam 的进程 ID。

您会发现,每个游戏通常会生成 2-3 个不同的子进程。 Steam 覆盖、webclienthelper,然后是游戏本身(可能还有另一个用于游戏启动器)。不过,它们都应该是 Steam 进程的子进程,并且都应该显示在找到的进程列表中。

看起来像这样。

List<Process> procs = Process.GetProcesses();
Process steam = procs.Find(x => x.ProcessName == "Steam");
int steamId = steam.Id;

foreach (var proc in procs)
{
    using (ManagementObject mo = new ManagementObject($"win32_process.handle='{proc.Id}'"))
    {
        if (mo != null)
        {
            try
            {
                mo.Get();
                int parentPid = Convert.ToInt32(mo["ParentProcessId"]);
                if (parentPid == steamId)
                {
                    Console.WriteLine($"{proc.ProcessName} is running as a child to {mo["ParentProcessId"]}");
                }
            }
            catch (Exception ex)
            {
                // the process ended between polling all of the procs and requesting the management object
            }
        }
    }
}