【发布时间】:2015-12-21 14:06:58
【问题描述】:
有没有办法查询窗口在进入挂起/睡眠模式之前还剩多少时间?
我正在使用 vbscript 并怀疑可能有 WMI 答案,但任何语言,如 c/c++、*.NET 甚至 java,如果可能的话,都可能满足我的需求。
编辑
我希望能够使用一种方法查询 Windows,而不是在即将挂起时收到事件警报。
【问题讨论】:
-
我一直在到处寻找起点,甚至找不到这样的问题。所以,我没有代码。
有没有办法查询窗口在进入挂起/睡眠模式之前还剩多少时间?
我正在使用 vbscript 并怀疑可能有 WMI 答案,但任何语言,如 c/c++、*.NET 甚至 java,如果可能的话,都可能满足我的需求。
编辑
我希望能够使用一种方法查询 Windows,而不是在即将挂起时收到事件警报。
【问题讨论】:
没有 API 可以知道还剩多少时间,因为 Windows 会尝试尽快完成进入 S3(睡眠)或 S4(休眠)。
Windows 将向所有进程发送有关未决电源状态更改的通知,并允许应用程序为该事件做好准备。
您可以在here找到大部分您需要的东西。
基本上你有 20 秒的时间来处理第一条消息。您的进程可能会延迟回复消息,处理所有各种电源循环任务,例如关闭文件,保存您的状态等。
【讨论】:
您可能想要调用采用以下参数的CallNtPowerInformation API 函数:
NTSTATUS WINAPI CallNtPowerInformation(
_In_ POWER_INFORMATION_LEVEL InformationLevel,
_In_ PVOID lpInputBuffer,
_In_ ULONG nInputBufferSize,
_Out_ PVOID lpOutputBuffer,
_In_ ULONG nOutputBufferSize
);
在InformationLevel 参数中,您传递SystemPowerInformation 枚举值,该值用SYSTEM_POWER_INFORMATION 结构填充lpOutputBuffer:
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
【讨论】:
TimeRemaining 在函数返回值不为 0 时未定义。问题是这个函数返回一个我无法解读的错误,可能是由于查询权限? 0xC0000005