2015-12-21 49 views
13

有没有办法查询窗口多少时间,直到进入挂起/休眠模式?剩下的时间直到Windows暂停

我正在使用vbscript,并怀疑可能有WMI答案,但如果可能的话,像c/C++,* .NET或甚至java这样的任何语言都可能适合我的需要。

编辑

我希望能够有一个方法来查询的Windows,而不是由事件提醒,当它即将中止。

+0

[?你尝试过什么(http://mattgemmell.com/what-have-you-tried/ ) – Drop

+4

我一直在寻找一个起点,甚至找不到任何这样的问题。所以,我没有代码。 –

+0

https://msdn.microsoft.com/en-us/library/windows/desktop/aa373217%28v=vs.85%29.aspx –

回答

7

由于Windows会尝试尽可能快地完成进入S3(睡眠)或S4(休眠),所以没有API知道剩下多少时间。

Windows将向所有进程发送有关挂起的电源状态更改的通知,并允许应用程序为该事件做准备。

你可以找到你需要的大部分here

基本上你有20秒来处理第一条消息。您的过程可能会延迟回复信息,以处理所有各种电源循环任务,例如关闭文件,保存状态等

4

您可能需要调用CallNtPowerInformation API函数,它采用以下PARAMS:

NTSTATUS WINAPI CallNtPowerInformation(
    _In_ POWER_INFORMATION_LEVEL InformationLevel, 
    _In_ PVOID     lpInputBuffer, 
    _In_ ULONG     nInputBufferSize, 
    _Out_ PVOID     lpOutputBuffer, 
    _In_ ULONG     nOutputBufferSize 
); 

在paramer你传递的是一个充满lpOutputBufferSystemPowerInformation枚举值InformationLevelSYSTEM_POWER_INFORMATION结构:

typedef struct _SYSTEM_POWER_INFORMATION { 
    ULONG MaxIdlenessAllowed; 
    ULONG Idleness; 
    ULONG TimeRemaining; 
    UCHAR CoolingMode; 
} SYSTEM_POWER_INFORMATION, *PSYSTEM_POWER_INFORMATION; 

然后拿到TimeRemaining,其中以秒为单位。

编辑:在VB.NET中测试。 编辑:添加代码。

Queryer.vb

Imports System.Runtime.InteropServices 

Public Class Queryer 

    Const SystemPowerInformation As Integer = 12 
    Const STATUS_SUCCESS As Integer = 0 

    Private Structure SYSTEM_POWER_INFORMATION 
     Public MaxIdlenessAllowed As UInteger 
     Public Idleness As UInteger 
     Public TimeRemaining As Integer 
     Public CoolingMode As Byte 
    End Structure 

    <DllImport("PowrProf.dll", SetLastError:=True, CharSet:=CharSet.Auto)> 
    Public Shared Function CallNtPowerInformation(
      ByVal InformationLevel As Int32, 
      ByVal lpInputBuffer As IntPtr, 
      ByVal nInputBufferSize As UInt32, 
      ByVal lpOutputBuffer As IntPtr, 
      ByRef nOutputBufferSize As UInt32) As UInt32 
    End Function 

    Public Function Query() As Integer 

     Dim PowerInformation As SYSTEM_POWER_INFORMATION 
     Dim Status As IntPtr = IntPtr.Zero 
     Dim ReturnValue As UInteger 
     Try 
      Status = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(SYSTEM_POWER_INFORMATION))) 
      ReturnValue = CallNtPowerInformation(SystemPowerInformation, Nothing, 0, Status, Marshal.SizeOf(GetType(SYSTEM_POWER_INFORMATION))) 

      PowerInformation = Marshal.PtrToStructure(Status, GetType(SYSTEM_POWER_INFORMATION)) 
     Catch ex As Exception 
      Return 0 
     Finally 
      Marshal.FreeCoTaskMem(Status) 

     End Try 
     Return PowerInformation.TimeRemaining 

    End Function 

End Class 

表:

Public Class Form1 


    Public Sub Loader() Handles Me.Load 

     Dim rolex As New Timer() 
     rolex.Interval = 500 
     AddHandler rolex.Tick, AddressOf TimerScattato 

     rolex.Start() 

    End Sub 

    Private Sub TimerScattato() 
     Dim secondi As Integer = q.Query() 
     Dim iSpan As TimeSpan = TimeSpan.FromSeconds(secondi) 

     lblTimeLeft.Text = String.Format("{0,2}:{1,2}:{2,2}", iSpan.Hours, iSpan.Minutes, iSpan.Seconds) 


    End Sub 

    Private q As New Queryer 
End Class 
+1

从@HansPassant链接中提到了一个错误 - * TimeRemaining实际上是LONG ,不是ULONG。 (当系统由于睡眠原因,但由于某种原因无法启动时,TimeRemaining会变为负数。)* –

+0

我可否看到您的VB.NET测试代码? –

+0

@EduardoPoço完成。 – vulkanino