如何将进程信息转换为WTS_PROCESS_INFO

本文关键字:WTS PROCESS INFO 转换 进程 信息 | 更新日期: 2023-09-27 18:36:00

我正在尝试调用WTSEnumerateProcesses()但是在将类型ProcessInfo转换为WTS_PROCESS_INFO时遇到一些问题。

这是我到目前为止的代码:

进程信息

    class ProcessInfo
    {
        public int basePriority;
        public int handleCount;
        public int mainModuleId;
        public long pageFileBytes;
        public long pageFileBytesPeak;
        public long poolNonpagedBytes;
        public long poolPagedBytes;
        public long privateBytes;
        public int processId;
        public string processName;
        public int sessionId;
        public ArrayList threadInfoList;
        public long virtualBytes;
        public long virtualBytesPeak;
        public long workingSet;
        public long workingSetPeak;
        public ProcessInfo()
        {
        }
    }

WTS_PROCESS_INFO

    public struct WTS_PROCESS_INFO
    {
        public int SessionID;
        public int ProcessID;
        // This is spointer to a string...
        public IntPtr ProcessName;
        public IntPtr userSid;
    }

WTSEnumerateProcesses()

    [DllImport("wtsapi32.dll", SetLastError = true)]
    static extern bool WTSEnumerateProcesses(
        IntPtr serverHandle, // Handle to a terminal server. 
        Int32 reserved,     // must be 0
        Int32 version,      // must be 1
        ref IntPtr ppProcessInfo, // pointer to array of WTS_PROCESS_INFO
        ref Int32 pCount     // pointer to number of processes
    );
    public static WTS_PROCESS_INFO[] WTSEnumerateProcesses()
    {
        IntPtr pProcessInfo = IntPtr.Zero;
        int processCount = 0;
        var hServer = OpenServer("XA7-06");
        if (!WTSEnumerateProcesses(hServer, 0, 1, ref pProcessInfo, ref processCount))
            return null;
        IntPtr pMemory = pProcessInfo;
        WTS_PROCESS_INFO[] processInfos = new WTS_PROCESS_INFO[processCount];
        for (int i = 0; i < processCount; i++)
        {
            processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
            pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
        }
        WTSFreeMemory(pMemory);
        return processInfos;
    }

我的问题接近此行WTSEnumerateProcesses()方法的末尾:

processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));

我认为我可能错过了定义WTS_PROCESS_INFOProcessInfo之间关系的步骤,但我不确定如何做到这一点。有人能为我指出正确的方向吗?

这是我看到的错误:

// Cannot implicitly convert type 'ProcessInfo' to 'WTS_PROCESS_INFO'

如何将进程信息转换为WTS_PROCESS_INFO

您的ProcessInfo类型与WTS_PROCESS_INFO无关。所以这行:

processInfos[i] = (ProcessInfo)Marshal.PtrToStructure(pProcessInfo, 
    typeof(WTS_PROCESS_INFO));

实际上包含两个错误。编译器选取一个。具体来说,该processInfos[i]属于 WTS_PROCESS_INFO 类型,并且与 ProcessInfo 的赋值不兼容。另一个错误更微妙一些。Marshal.PtrToStructure()返回的值转换为类型 ProcessInfo 是错误的。Marshal.PtrToStructure()返回的值是一个带框的WTS_PROCESS_INFO。所以这行代码应该是:

processInfos[i] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, 
    typeof(WTS_PROCESS_INFO));

指针算术可能会在 64 位进程中失败。如果您使用的是最新版本的 .net,则可以直接在 Intptr 上执行算术运算:

pProcessInfo += Marshal.SizeOf(processInfos[i]);

或者,如果面向较旧的 .net 版本,则应通过强制转换为 ulong 而不是 int 在 64 位上下文中执行算术。

至于你的ProcessInfo类型,我认为这只是你的错误想法。这种类型在这里似乎没有用。

如果我是你,我会强制使用 Unicode 版本的 WTSEnumerateProcessesW,例如这样:

[DllImport("wtsapi32.dll", EntryPoint = "WTSEnumerateProcessesW", SetLastError = true)]
static extern bool WTSEnumerateProcesses(
    ....
);

若要将进程名称读取为字符串,请将 WTS_PROCESS_INFO 结构中返回的指针传递给 Marshal.PtrToStringUni