feat(exe): use /proc/self/maps to get exe for ui and core lsfg-vk

This commit is contained in:
Rerence1016 2025-08-03 23:27:24 +08:00 committed by Pancake
parent b899324b8c
commit ec59c072b5
2 changed files with 40 additions and 38 deletions

View file

@ -8,6 +8,7 @@
#include <unistd.h> #include <unistd.h>
#include <unordered_map> #include <unordered_map>
#include <filesystem>
#include <algorithm> #include <algorithm>
#include <optional> #include <optional>
#include <iostream> #include <iostream>
@ -19,7 +20,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include <array> #include <array>
#include <regex>
using namespace Utils; using namespace Utils;
@ -237,29 +237,22 @@ std::pair<std::string, std::string> Utils::getProcessName() {
// For .exe apps running through Proton/Wine // For .exe apps running through Proton/Wine
std::ifstream cmdline_file("/proc/self/cmdline"); std::ifstream maps_file("/proc/self/maps");
if (!cmdline_file.is_open()) { std::string line;
return {"", ""}; // Not sure what to do if it ISN'T open
}
std::string cmdline;
getline(cmdline_file, cmdline, '\0');
// If the process is a Proton/Wine app while (getline(maps_file, line)) {
if (cmdline.find(".exe") != std::string::npos) { if (line.find(".exe") != std::string::npos) {
// Extract just the executable name // Backslash needs to be a raw string literal
std::regex pattern(R"([-\w\s\.()\[\]!@]*(\.[Ee][Xx][Ee]))"); size_t path_start = line.find("/") || line.find(R"(\)");
std::smatch match; if (path_start != std::string::npos) {
if (std::regex_search(cmdline, match, pattern)) { std::string path = line.substr(path_start);
comm_str = match[0]; comm_str = std::filesystem::path(path).filename().string();
} } else {
} else { // If nothing found, default to 0
path_start = 0;
// If it's not a .exe app, just use the comm string }
}
// Note: if not a Windows app, the name will still be
// cut off to just 15 characters as a limitation of
// using comm in /proc
} }
return{ std::string(exe.data()), comm_str }; return{ std::string(exe.data()), comm_str };

View file

@ -1,11 +1,7 @@
use procfs::{process, ProcResult}; use procfs::{process, ProcResult};
use regex::Regex; use std::path::Path;
pub fn find_vulkan_processes() -> ProcResult<Vec<(String, String)>> { pub fn find_vulkan_processes() -> ProcResult<Vec<(String, String)>> {
// Extract just .exe name from a running Wine or Proton process
let pattern = Regex::new(r"[-\w\s\.()\[\]!@]*(\.[Ee][Xx][Ee])").unwrap();
let mut processes = Vec::new(); let mut processes = Vec::new();
let apps = process::all_processes()?; let apps = process::all_processes()?;
@ -26,25 +22,38 @@ pub fn find_vulkan_processes() -> ProcResult<Vec<(String, String)>> {
continue; continue;
} }
// format process information // Format process information
let pid = process.pid(); let pid = process.pid();
let name: String;
// By default, assume Linux process, and use comm
let mut name = process.stat()?.comm;
// Solely just for checking if it's a Proton or Wine process
// Not sure if there's a more efficient way to do this
let cmdline = process.cmdline()?.join(" "); let cmdline = process.cmdline()?.join(" ");
// If this is a Proton or Wine process with .exe, // If this is a Proton or Wine process with .exe,
// then extract just the .exe name with RegEx // then extract just the .exe name with RegEx
if cmdline.contains(".exe") { if cmdline.contains(".exe") {
name = pattern.find(&cmdline) for map in &maps {
.unwrap() if let Some(path) = map.filename() {
.as_str() let path_str = path.to_string_lossy().to_lowercase();
.to_string(); if path_str.contains(".exe") &&
} else { !path_str.contains("wine") &&
path_str.contains('/') ||
path_str.contains('\\') {
// If just a normal Linux process, then use name = Path::new(&path_str).file_name()
// the normal name .unwrap_or_default()
name = process.stat()?.comm; .to_string_lossy()
.to_string();
break;
}
}
}
} }
let process_info = format!("PID {pid}: {name}"); let process_info = format!("PID {pid}: {name}");
processes.push((process_info, name)); processes.push((process_info, name));
} }