C'est probablement la manière la plus naturelle de le faire, tout en couvrant la plupart des principales plates-formes de bureau. Je ne suis pas sûr, mais je pense que cela devrait fonctionner avec tous les BSD, pas seulement FreeBSD, si vous modifiez la vérification des macros de la plate-forme pour les couvrir tous. Si jamais j'arrive à installer Solaris, je veillerai à ajouter cette plate-forme à la liste prise en charge.
Prise en charge complète de UTF-8 sur Windows, ce que tout le monde ne se soucie pas suffisamment pour aller aussi loin.
procinfo / win32 / procinfo.cpp
#ifdef _WIN32
#include "../procinfo.h"
#include <windows.h>
#include <tlhelp32.h>
#include <cstddef>
#include <vector>
#include <cwchar>
using std::string;
using std::wstring;
using std::vector;
using std::size_t;
static inline string narrow(wstring wstr) {
int nbytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), NULL, 0, NULL, NULL);
vector<char> buf(nbytes);
return string{ buf.data(), (size_t)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.length(), buf.data(), nbytes, NULL, NULL) };
}
process_t ppid_from_pid(process_t pid) {
process_t ppid;
HANDLE hp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 pe = { 0 };
pe.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hp, &pe)) {
do {
if (pe.th32ProcessID == pid) {
ppid = pe.th32ParentProcessID;
break;
}
} while (Process32Next(hp, &pe));
}
CloseHandle(hp);
return ppid;
}
string path_from_pid(process_t pid) {
string path;
HANDLE hm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
MODULEENTRY32W me = { 0 };
me.dwSize = sizeof(MODULEENTRY32W);
if (Module32FirstW(hm, &me)) {
do {
if (me.th32ProcessID == pid) {
path = narrow(me.szExePath);
break;
}
} while (Module32NextW(hm, &me));
}
CloseHandle(hm);
return path;
}
#endif
procinfo / macosx / procinfo.cpp
#if defined(__APPLE__) && defined(__MACH__)
#include "../procinfo.h"
#include <libproc.h>
using std::string;
string path_from_pid(process_t pid) {
string path;
char buffer[PROC_PIDPATHINFO_MAXSIZE];
if (proc_pidpath(pid, buffer, sizeof(buffer)) > 0) {
path = string(buffer) + "\0";
}
return path;
}
#endif
procinfo / linux / procinfo.cpp
#ifdef __linux__
#include "../procinfo.h"
#include <cstdlib>
using std::string;
using std::to_string;
string path_from_pid(process_t pid) {
string path;
string link = string("/proc/") + to_string(pid) + string("/exe");
char *buffer = realpath(link.c_str(), NULL);
path = buffer ? : "";
free(buffer);
return path;
}
#endif
procinfo / freebsd / procinfo.cpp
#ifdef __FreeBSD__
#include "../procinfo.h"
#include <sys/sysctl.h>
#include <cstddef>
using std::string;
using std::size_t;
string path_from_pid(process_t pid) {
string path;
size_t length;
// CTL_KERN::KERN_PROC::KERN_PROC_PATHNAME(pid)
int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, pid };
if (sysctl(mib, 4, NULL, &length, NULL, 0) == 0) {
path.resize(length, '\0');
char *buffer = path.data();
if (sysctl(mib, 4, buffer, &length, NULL, 0) == 0) {
path = string(buffer) + "\0";
}
}
return path;
}
#endif
procinfo / procinfo.cpp
#include "procinfo.h"
#ifdef _WiN32
#include <process.h>
#endif
#include <unistd.h>
#include <cstddef>
using std::string;
using std::size_t;
process_t pid_from_self() {
#ifdef _WIN32
return _getpid();
#else
return getpid();
#endif
}
process_t ppid_from_self() {
#ifdef _WIN32
return ppid_from_pid(pid_from_self());
#else
return getppid();
#endif
}
string dir_from_pid(process_t pid) {
string fname = path_from_pid(pid);
size_t fp = fname.find_last_of("/\\");
return fname.substr(0, fp + 1);
}
string name_from_pid(process_t pid) {
string fname = path_from_pid(pid);
size_t fp = fname.find_last_of("/\\");
return fname.substr(fp + 1);
}
procinfo / procinfo.h
#ifdef _WiN32
#include <windows.h>
typedef DWORD process_t;
#else
#include <sys/types.h>
typedef pid_t process_t;
#endif
#include <string>
/* windows-only helper function */
process_t ppid_from_pid(process_t pid);
/* get current process process id */
process_t pid_from_self();
/* get parent process process id */
process_t ppid_from_self();
/* std::string possible_result = "C:\\path\\to\\file.exe"; */
std::string path_from_pid(process_t pid);
/* std::string possible_result = "C:\\path\\to\\"; */
std::string dir_from_pid(process_t pid);
/* std::string possible_result = "file.exe"; */
std::string name_from_pid(process_t pid);
Cela permet d'obtenir le chemin complet vers l'exécutable de quasiment n'importe quel identifiant de processus, sauf sous Windows, il existe des processus avec des attributs de sécurité qui ne le permettront tout simplement pas, donc wysiwyg, cette solution n'est pas parfaite.
Pour répondre plus précisément à ce que la question posait, vous pouvez faire ceci:
procinfo.cpp
#include "procinfo/procinfo.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;
int main() {
cout << dir_from_pid(pid_from_self()) << endl;
return 0;
}
Construisez la structure de fichier ci-dessus avec cette commande:
procinfo.sh
cd "${0%/*}"
g++ procinfo.cpp procinfo/procinfo.cpp procinfo/win32/procinfo.cpp procinfo/macosx/procinfo.cpp procinfo/linux/procinfo.cpp procinfo/freebsd/procinfo.cpp -o procinfo.exe
Pour télécharger une copie des fichiers répertoriés ci-dessus:
git clone git://github.com/time-killer-games/procinfo.git
Pour plus de qualité liée aux processus multiplateformes:
https://github.com/time-killer-games/enigma-dev
Voir le readme pour une liste de la plupart des fonctions incluses.