1

I'm banging my head about how to properly call sysctlbyname from C# directly. I've read the man page and I think what I'm doing is very close, just something is messed up with marshalling.

     [DllImport(MonoTouch.Constants.SystemLibrary)]  
    internal static extern int sysctlbyname( [MarshalAs(UnmanagedType.LPStr)] string property, IntPtr output, IntPtr oldLen, IntPtr newp, uint newlen);

    //only works on sysctls that return strings
    public static string SystemStringInfo(string property)
    {
        GCHandle? lenh = null, valh = null;
        try
        {
            object len = 0L;
            lenh=GCHandle.Alloc(len, GCHandleType.Pinned);

            byte[] val;
            int status = sysctlbyname(property, IntPtr.Zero, GCHandle.ToIntPtr(lenh.Value), IntPtr.Zero, 0); //crash here
            if (status == 0)
            {

                val = new byte[(Int64)len];
                valh=GCHandle.Alloc(val, GCHandleType.Pinned);
                status = sysctlbyname(property, GCHandle.ToIntPtr(valh.Value), GCHandle.ToIntPtr(lenh.Value), IntPtr.Zero, 0);
                if (status == 0)
                {
                    return Encoding.UTF8.GetString(val);
                }
            }
            return null;
        }
        finally
        {
            if (lenh.HasValue)
            {
                lenh.Value.Free();
            }
            if (valh.HasValue)
            {
                valh.Value.Free();
            }
        }
    }

It will properly return from sysctlbyname (with -1) when I give it a bogus sysctl property name, like "foobar". However, when I give it a proper name like kern.osrelease, it'll hit that line and freeze and/or crash.

What is wrong and how do I get this to work!?

4

2 回答 2

2

我知道它不是“完整的”(我确信 newp 和 newlen 仍然需要修改,但我无论如何都不使用它们),但这是我最终让它工作的方法

[DllImport(MonoTouch.Constants.SystemLibrary)]  
internal static extern int sysctlbyname( [MarshalAs(UnmanagedType.LPStr)] string property, byte[] output, ref Int64 oldLen, IntPtr newp, uint newlen);

public static string SystemStringInfo(string property)
{
    GCHandle? lenh = null, valh = null;
    Int64 len = 0L;

    byte[] val;
    int status = sysctlbyname(property, null, ref len, IntPtr.Zero, 0);
    if (status == 0)
    {

        val = new byte[(Int64) len];
        status = sysctlbyname(property, val, ref len, IntPtr.Zero, 0);
        if (status == 0)
        {
            return Encoding.UTF8.GetString(val);
        }
    }
    return null;
}
于 2013-09-10T19:33:06.987 回答
1

在这里查看我的答案:https ://stackoverflow.com/a/14711348/1134836 。我打电话sysctlbyname来获取 UIDevice 信息。

于 2013-09-10T20:40:00.693 回答