3

アプリケーションを起動すると、アプリケーションの別のプロセスがあるかどうかを調べようとします。また、別のユーザー セッションで実行されているかどうかを調べようとします。

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;
    }

しかし、要件が変更されました。単純な WinAPI を使用して、C++ でこのコードが必要です。

これまではCreateToolhelp32SnapshotOpenProcess、 など を使用して、同じ実行パスを持つプロセスを見つけることができました。

欠落している部分は、プロセスのセッション ID を取得する方法です (現在のプロセスと他のプロセス、および現在のセッションと他のセッション)

4

3 に答える 3

3

このProcessIdToSessionId関数は、プロセス ID をセッション ID にマップします。

これには、.Net では必要のない過剰なアクセス許可が必要なようです。

.Net はレジストリの HKEY_PERFORMANCE_DATA からプロセス データの一部を取得しますが、これにはセッション ID は含まれません。セッション ID は、構造体NtQuerySystemInformationの配列を返すために使用して取得されます。SYSTEM_PROCESS_INFORMATIONこの構造は十分に文書化されていませんが、ハンドル カウントの直後にセッション ID が続きます (つまり、現在 として宣言されているフィールドですBYTE Reserved4[4];)。Microsoft は、これが Windows の将来のバージョンでも引き続き当てはまることを保証しません。

于 2013-10-17T16:03:08.857 に答える
1

すべての 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 %s\n" ), pOneSPI->UniqueProcessId, *reinterpret_cast<LONG*>( &pOneSPI->Reserved4 ), pwch );
        if ( pOneSPI->NextEntryOffset ) pSPI += pOneSPI->NextEntryOffset;
        else break;
    } 

    return 0;
}

SO の SPI 構造のドキュメントを提供してくれた @Oleg に感謝します。

于 2013-10-18T15:31:16.570 に答える