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

时间:2016-02-23 12:30:20

标签: c# string marshalling native

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

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

这似乎非常可靠,并且所有进程名称都已成功转换。

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

这仅在使用.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 s out结果传递给空字符串后发生的转换(除第一个之外)。

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

任何人都可以解释为什么会这样吗?

1 个答案:

答案 0 :(得分:2)

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

之前复制那些字符串