获取C++中另一个进程的会话 ID
Get Session ID of another process in C++
当我启动我的应用程序时,我试图弄清楚应用程序是否有另一个进程。我还尝试确定它是否在不同的用户会话中运行。
到目前为止一切顺利,这就是它在 C# 中的样子:
private static bool isThereAnotherInstance() {
string name = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
Process[] pAll = Process.GetProcessesByName(name);
Process pCurrent = Process.GetCurrentProcess();
foreach (Process p in pAll) {
if (p.Id == pCurrent.Id) continue;
if (p.SessionId != pCurrent.SessionId) continue;
return true;
}
return false;
}
但是要求已经改变,我需要这段代码C++使用普通的 WinAPI。
到目前为止,我能够通过使用CreateToolhelp32Snapshot
、OpenProcess
等找到具有相同可执行路径的进程。
缺少的部分是如何获取进程的会话ID(当前和其他进程,以及当前和其他会话)
怎么做?
ProcessIdToSessionId
函数将进程 ID 映射到会话 ID。
请注意,这似乎需要 .Net 不需要的过多权限。
.Net 确实从注册表中的HKEY_PERFORMANCE_DATA获取一些进程数据,但这不包括会话 ID。 会话 ID 是使用 NtQuerySystemInformation
获取的,以返回SYSTEM_PROCESS_INFORMATION
结构数组。 此结构没有很好的文档记录,但会话 ID 紧跟在句柄计数之后(即它是当前声明为 BYTE Reserved4[4];
的字段)。 Microsoft不保证在未来版本的 Windows 中会继续如此。
正如arx所提到的,ProcessIdToSessionId
应该完成这项工作。
但不幸的是,就我而言,它告诉我ACCESS_DENIED
我感兴趣的过程。
它为当前进程完成其工作。
所以这是我的解决方案,使用 NtQuerySystemInformation
.
.NET Process
类在内部使用相同的函数。
typedef struct _SYSTEM_PROCESS_INFORMATION_BUG {
//...
}
typedef NTSTATUS (WINAPI *PNtQuerySystemInformation) (
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
#ifndef NT_ERROR
#define NT_ERROR(Status) ((ULONG)(Status) >> 30 == 3)
#endif
#define PROCESSINFO_BUFFERSIZE (256*1024)
DLL_EXPORT int GetProcessIdFromPath2(char *exePath, int flags) {
char exe[MAX_PATH], *exeName, file[MAX_PATH], *fileName;
DWORD pidCurrent, sessionIdCurrent;
int ret=-1;
strcpy(exe, exePath);
strupr(exe);
exeName=getFileName(exe);
pidCurrent = GetCurrentProcessId();
if (!ProcessIdToSessionId(pidCurrent, &sessionIdCurrent)) sessionIdCurrent=0;
HMODULE hNT = LoadLibrary("Ntdll.dll");
if (hNT) {
PNtQuerySystemInformation pNtQuerySystemInformation = (PNtQuerySystemInformation)GetProcAddress(hNT, "NtQuerySystemInformation");
if (pNtQuerySystemInformation) {
SYSTEM_PROCESS_INFORMATION_BUG* processInfo;
char *buffer = (char*)malloc(PROCESSINFO_BUFFERSIZE);
if (!buffer) {
ret=-3;
}
else {
char *current=buffer;
DWORD len;
int count=0;
NTSTATUS s = pNtQuerySystemInformation(SystemProcessInformation, buffer, PROCESSINFO_BUFFERSIZE, &len);
if (NT_ERROR(s)) {
ret=-2;
}
else {
ret=0;
while(1) {
processInfo = (SYSTEM_PROCESS_INFORMATION_BUG*)current;
if (processInfo->ImageName.Buffer!=NULL){
wcstombs(file, processInfo->ImageName.Buffer, MAX_PATH-1);
strupr(file);
fileName=getFileName(file);
if (strcmp(fileName, exeName)==0) {
if (processInfo->UniqueProcessId!=pidCurrent) {
if (processInfo->SessionId==sessionIdCurrent) {
ret = processInfo->UniqueProcessId;
}
}
}
}
if (processInfo->NextEntryOffset==0) break;
current+=processInfo->NextEntryOffset;
count++;
}
}
free(buffer);
buffer=NULL;
}
}
FreeLibrary(hNT);
}
return ret;
}
列出所有 PID、SID、EXE 的代码("ala"任务管理器,有点)适用于我 (Windows 7 64b) VS2012 Express
#include <stdio.h>
#include <tchar.h>
#include <Windows.h>
#include <Winternl.h>
#pragma comment( lib, "ntdll.lib" )
typedef LONG KPRIORITY; // Thread priority
typedef struct _SYSTEM_PROCESS_INFORMATION_DETAILD {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER SpareLi1;
LARGE_INTEGER SpareLi2;
LARGE_INTEGER SpareLi3;
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
KPRIORITY BasePriority;
HANDLE UniqueProcessId;
ULONG InheritedFromUniqueProcessId;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
} SYSTEM_PROCESS_INFORMATION_DETAILD, *PSYSTEM_PROCESS_INFORMATION_DETAILD;
int _tmain(int argc, _TCHAR* argv[]) {
SYSTEM_PROCESS_INFORMATION aSPI[ 1024 ];
// could ask for actual needed size size and malloc (with few extra new processes bonus...)
NTSTATUS nts = NtQuerySystemInformation( SystemProcessInformation, aSPI, sizeof( aSPI ), NULL );
if ( NT_ERROR( nts ) ) return -1;
char * pSPI = reinterpret_cast<char*>( &aSPI[ 0 ] );
while ( true ) {
SYSTEM_PROCESS_INFORMATION_DETAILD * pOneSPI = reinterpret_cast<SYSTEM_PROCESS_INFORMATION_DETAILD*>( pSPI );
WCHAR * pwch = pOneSPI->ImageName.Buffer;
if ( pwch == 0 || pOneSPI->ImageName.Length == 0 ) pwch = TEXT( "Unknown" );
_tprintf( TEXT( "PID %d - SID %d EXE %sn" ), pOneSPI->UniqueProcessId, *reinterpret_cast<LONG*>( &pOneSPI->Reserved4 ), pwch );
if ( pOneSPI->NextEntryOffset ) pSPI += pOneSPI->NextEntryOffset;
else break;
}
return 0;
}
非常感谢@Oleg在此处提供有关SO的SPI结构的文档
- 为多个会话保留XPtr
- 是否可以用"iostream"包装现有的TCP/OOpenSSL会话
- 从函数角度看ID到文件路径的内部与外部映射
- 通过组合不同的类型来创建唯一的id
- 我不断收到 [错误] ID 返回 1 退出状态错误,但看不到问题所在
- FFMPEG配置文件级别id大小无效
- 方法内部但循环仍得到预期的不合格id错误C++
- 如何修复 Onnx运行时会话>运行问题?
- 如何获取 GLFW 窗口 ID?
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 显示数组中的学生 ID 和最高分
- 为什么 KMS drmModeSetCrtc() 在 X11 会话中运行时会失败并被拒绝权限?
- C++:"("令牌"之前有预期的非限定 id 指向类中成员函数的指针
- 在PostgreSQL中根据它们的ID选择大量行的最快方法是什么?
- 获取 Winlogon.exe 的会话 ID 和进程 ID
- 使用哪种类型的 API 或算法来生成会话 ID
- 获取C++中另一个进程的会话 ID
- 使用FFmpeg通过RTMP连接到nginx服务器,会话id为
- 是否使用默认的mt19937 RNG对会话id安全生成boost uuid ?
- SSL握手错误:会话id上下文未初始化