根据框架将 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);
之前将这些字符串复制到某处
我正在使用以下行将我的 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);