如何使用CallNtPowerInformation获取LastSleepTime

时间:2018-04-11 09:20:19

标签: c# winapi

我有一些代码,我将使用它来获取CallNtPowerInformation的一些电源信息。目前我在上一次睡眠时遇到了一些问题。有人可以帮助他吗?

 [DllImport("PowrProf.dll", SetLastError = true)]
    private static extern uint CallNtPowerInformation(
        POWER_INFORMATION_LEVEL InformationLevel,
        IntPtr lpInputBuffer,
        int nInputBufferSize,
        ref IntPtr lpOutputBuffer,
        int nOutputBufferSize
    );

 public void GetPowerInfo(int pil)
    {
        IntPtr buff = new IntPtr();
        var result = CallNtPowerInformation(
            (POWER_INFORMATION_LEVEL) pil,
            IntPtr.Zero,
            0,
            ref buff,
            Marshal.SizeOf(pil)
        );

        if (result != 0) return;

        var fields = 
            typeof( SYSTEM_BATTERY_STATE ).GetFields( BindingFlags.Public | BindingFlags.Instance );
        foreach (var t in fields)
            Debug.WriteLine(
                "{0}: {1}",
                t.Name,
                t.GetValue( buff )
            );
    }

现在我收到错误代码0xc0000023 STATUS_BUFFER_TOO_SMALL

2 个答案:

答案 0 :(得分:0)

实际上你的代码对我来说看起来有些奇怪,但是如果你想要获得最后的睡眠时间,你要么应该使用适当大小的变量(在你的情况下长,使用适当的CallNtPowerInformation声明)或手动编组(参见下面的示例) )。

假设声明 CallNtPowerInformation 如下:

    [DllImport("PowrProf.dll", EntryPoint = "CallNtPowerInformation", ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
            private static extern int CallNtPowerInformation(
                PowerInformationLevel informationLevel,
                [In]IntPtr lpInputBuffer,
                uint nInputBufferSize,
            [In, Out]IntPtr lpOutputBuffer,
            uint nOutputBufferSize); 

然后像这样称呼它:

public long GetLastSleepTime()
{
    IntPtr lastSleep = IntPtr.Zero;
    try
    {
        lastSleep = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(long)));

        int ntStatus = CallNtPowerInformation(PowerInformationLevel.LastSleepTime, IntPtr.Zero, 0, lastSleep,
            (uint)Marshal.SizeOf(typeof(long)));

        if (ntStatus != 0)
            return 0;

        // receives a ULONGLONG that specifies the interrupt-time count, in 100-nanosecond units, at the last system sleep time
        // there are 1e9 nanoseconds in a second, so there are 1e7 100 - nanoseconds in a second

        long lastSleepTimeInSeconds = Marshal.ReadInt64(lastSleep, 0) / 10000000;

        return lastSleepTimeInSeconds;

    }
    finally
    {
        if (lastSleep != IntPtr.Zero)
            Marshal.FreeCoTaskMem(lastSleep);
    }
}

答案 1 :(得分:-1)

我已经更改了代码。现在它没有任何错误,但buff值始终为0;

   public ulong GetLastSleepTime()
    {
        IntPtr buff = new IntPtr();
        var result = CallNtPowerInformation(
            POWER_INFORMATION_LEVEL.LastSleepTime,
            IntPtr.Zero,
            0,
            ref buff,
            Marshal.SizeOf(buff)
        );

        return result!=0?(ulong)buff:result;
    }