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!?