将IntPtr解码为MultiString

时间:2014-08-13 11:40:52

标签: c# marshalling

我需要从调用CreateEnvironmentBlock( out IntPtr lpEnvironment, IntPtr hToken, bool bInherit )中提取环境字符串,以便根据变量名称及其值将它们放入字典中。

  

当此函数返回时,lpEnvironment会收到指向该函数的指针   新环境块。环境块是一个数组   以null结尾的Unicode字符串。该列表以两个空值结尾   (\0\0)。

我不能轻易使用Marshal.Copy,因为我不知道块的长度。我想知道是否有一种简单的方法来移动它或确定要复制到什么东西然后我可以更容易地转换。一种想法是将out IntPtr lpEnvironment作为out char [] lpEnvironment传递。

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

您不知道Marshal.Copy()的整个长度,但是如果您执行Marshal.PtrToString(),则知道第一个字符串的长度。有了这些知识,您可以前进到下一个字符串,依此类推,直到您读取一个空字符串,表示该地址只存在\0,这是多字符串的结尾。

请注意,以下代码假定Unicode charset可用并使用它。

[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool CreateEnvironmentBlock(ref IntPtr lpEnvironment,IntPtr hToken,bool bInherit);

static IEnumerable<string> ExtractMultiString(IntPtr ptr)
{
    while (true)
    {
        string str = Marshal.PtrToStringUni(ptr);
        if (str.Length == 0)
            break;
        yield return str;
        ptr = new IntPtr(ptr.ToInt64() + (str.Length + 1 /* char \0 */) * sizeof(char));
    }
}