根据框架将 Int 转换为字符串时不可靠的 Marshal

Unreliable Marshal when Converting Int to String Depending on Framework

我正在使用以下行将我的 WTS_PROCESS_INFO 对象的 ProcessName 属性 转换为字符串:

string name = Marshal.PtrToStringUni(processInfos[I].processName)

这个好像挺靠谱的,进程名都转换成功了。

但是,如果我在 WTS_PROCESS_INFO 传递给另一个 class 和方法之后进行相同的调用 ,则每次尝试转换为字符串都会导致 ""除了第一次尝试。

这只会在使用 .NET-3.5 时发生,但似乎在 .NET-4.0

中工作正常

示例:

有效 - 在传递整个列表之前,每个名称都被转换为正确的字符串。

    public static List<Proc> WTSEnumerateProcesses(string servername)
    {
        IntPtr pProcessInfo = IntPtr.Zero;
        int processCount = 0;
        var hServer = OpenServer(servername);

        if (!Native.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] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
            pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
        }

        List<Proc> asd = new List<Proc>();
        foreach (var item in processInfos)
        {
            if (item.SessionID == 5)
            {
                string procname = Marshal.PtrToStringUni(item.ProcessName);
                var proc = new Proc(servername, 5, item.SessionID, procname);
                asd.Add(proc);
            }
        }

        Native.WTSFreeMemory(pMemory);
        return asd;
    }

不工作 - 在传递 WTS_PROCESS_INFO 后发生的转换导致空字符串(第一个除外)。

    public static WTS_PROCESS_INFO[] WTSEnumerateProcesses(string servername)
    {
        IntPtr pProcessInfo = IntPtr.Zero;
        int processCount = 0;
        var hServer = OpenServer(servername);

        if (!Native.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] = (WTS_PROCESS_INFO)Marshal.PtrToStructure(pProcessInfo, typeof(WTS_PROCESS_INFO));
            pProcessInfo = (IntPtr)((int)pProcessInfo + Marshal.SizeOf(processInfos[i]));
        }

        Native.WTSFreeMemory(pMemory);
        return processInfos;
    }

谁能解释为什么会这样?

因为您调用的 Native.WTSFreeMemory(pMemory); 正在释放与字符串关联的内存。此调用同时释放 pMemory(即 WTS_PROCESS_INFO 的数组)和从各种 pProcessName 指向的内存。所以解决方案是在调用 Native.WTSFreeMemory(pMemory);

之前将这些字符串复制到某处