using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int SystemPowerInformation = 11;
const uint STATUS_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential)]
struct PROCESSOR_POWER_INFORMATION
{
public uint Number;
public uint MaxMhz;
public uint CurrentMhz;
public uint MhzLimit;
public uint MaxIdleState;
public uint CurrentIdleState;
}
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[MarshalAs(UnmanagedType.LPArray)]
out byte[] lpOutputBuffer,
int nOutputBufferSize
);
static void Main(string[] args)
{
byte[] buffer = new byte[4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))];
uint retval = CallNtPowerInformation(
SystemPowerInformation,
IntPtr.Zero,
0,
out buffer,
4 * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
if (retval == STATUS_SUCCESS)
Console.WriteLine(buffer);
}
}
}
I am trying to get some data out of CallNtPowerInformation
. I tried to create a struct and call CallNtPowerInformation
and marshal the data from it, but that didn't work. So I am trying to see if I can get the data into a byte array, but I get the following:
Object reference not set to an instance of an object.
I believe I am allocating the memory to the buffer.
I am not sure why. Any pointers would be helpful.
Your constant named SystemPowerInformation
with value 11
has the wrong name. It should be named ProcessorInformation
.
You should declare the p/invoke like this:
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[Out] PROCESSOR_POWER_INFORMATION[] processorPowerInformation,
int nOutputBufferSize
);
In order to call the function you need to allocate a suitably sized array of PROCESSOR_POWER_INFORMATION
structs. Like this:
PROCESSOR_POWER_INFORMATION[] powerInfo =
new PROCESSOR_POWER_INFORMATION[procCount];
The documentation for CallNtPowerInformation
tells you to use GetSystemInfo
to work out how many processors you have. You can use Environment.ProcessorCount
.
Then you call the function like this:
uint retval = CallNtPowerInformation(
ProcessorInformation,
IntPtr.Zero,
0,
powerInfo,
powerInfo.Length*Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
Here's a complete program:
using System;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int ProcessorInformation = 11;
const uint STATUS_SUCCESS = 0;
[StructLayout(LayoutKind.Sequential)]
struct PROCESSOR_POWER_INFORMATION
{
public uint Number;
public uint MaxMhz;
public uint CurrentMhz;
public uint MhzLimit;
public uint MaxIdleState;
public uint CurrentIdleState;
}
[DllImport("powrprof.dll")]
static extern uint CallNtPowerInformation(
int InformationLevel,
IntPtr lpInputBuffer,
int nInputBufferSize,
[Out] PROCESSOR_POWER_INFORMATION[] lpOutputBuffer,
int nOutputBufferSize
);
static void Main(string[] args)
{
int procCount = Environment.ProcessorCount;
PROCESSOR_POWER_INFORMATION[] procInfo =
new PROCESSOR_POWER_INFORMATION[procCount];
uint retval = CallNtPowerInformation(
ProcessorInformation,
IntPtr.Zero,
0,
procInfo,
procInfo.Length * Marshal.SizeOf(typeof(PROCESSOR_POWER_INFORMATION))
);
if (retval == STATUS_SUCCESS)
{
foreach (var item in procInfo)
{
Console.WriteLine(item.CurrentMhz);
}
}
}
}
}