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!?
I know it's not "complete" (I'm sure newp and newlen still need to be modified, but I don't use them anyway), but here is what I did to finally get this to work
[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;
}
Check out my answer here: https://stackoverflow.com/a/14711348/1134836 . I called sysctlbyname
to get the UIDevice information.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.