将 IntPtr 解码为 MultiString

use*_*089 5 c# marshalling

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

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

我无法轻松使用,Marshal.Copy因为我不知道块的长度。我想知道是否有一种简单的方法可以移动它或确定将哪些内容复制到我可以更轻松地转换的内容。一种想法是传递out IntPtr lpEnvironmentas out char [] lpEnvironment

有什么建议么?

You*_*elf 4

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

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

[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));
    }
}
Run Code Online (Sandbox Code Playgroud)