GetLastInputInfo 不返回 dwTime
GetLastInputInfo not returning dwTime
我有以下代码:
using System;
using System.Runtime.InteropServices;
public class WindowsFunctions
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public static int TicksSinceLastInput()
{
var info = new LASTINPUTINFO();
GetLastInputInfo(ref info);
var lastInputTickCount = info.dwTime;
return (int)lastInputTickCount;
}
}
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
[MarshalAs(UnmanagedType.U4)]
public UInt32 cbSize;
[MarshalAs(UnmanagedType.U4)]
public UInt32 dwTime;
}
但是,在 运行 上,info.dwTime
为零。
运行 VS2019 IDE
更新:
我试着让 TicksSinceLastInput
不是静态的,但无论如何都失败了。
我失败的单元测试现在是:
[TestMethod]
public void TestTicksSinceLastInput()
{
var funcs = new WindowsFunctions();
var ticks = funcs.TicksSinceLastInput();
Assert.IsTrue( ticks > 0);
}
更新:
我的代码现在是:
public class WindowsFunctions
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public int TicksSinceLastInput()
{
var info = new LASTINPUTINFO();
var result = GetLastInputInfo(ref info);
var lastInputTickCount = info.dwTime;
return (int)lastInputTickCount;
}
}
结果被设置为 false。
LASTINPUTINFO
的声明似乎来自 PInvoke.net。
该结构包含一个静态整数:
public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
它可能看起来像是在定义结构的大小,但它实际上没有实际用途。
在您的原始代码中,结构的 cbSize
成员未初始化,它必须是:它指定结构本身的大小;分配它是强制性的。
GetLastInputInfo函数声明正确:
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO info);
它的return类型是BOOL
(定义为typedef int BOOL
),而不是BOOLEAN
(定义为typedef BYTE BOOLEAN
)。
BOOL
已托管,不需要:
[return: MarshalAs(UnmanagedType.Bool)]
可以简化 LASTINPUTINFO 结构的声明和初始化,以包含一个初始化其成员的非空构造函数:
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
public LASTINPUTINFO(uint init) {
cbSize = (uint)Marshal.SizeOf<LASTINPUTINFO>();
dwTime = init;
}
}
其成员的类型是:
UINT cbSize
:UINT
定义为 typedef unsigned int UINT
,无符号整数。
这是一个托管类型,它不需要(这里)[MarshalAs(UnmanagedType.U4)]
DWORD dwTime
:DWORD
定义为typedef unsigned long DWORD
,是一个32位无符号整数。仍然管理,它不需要(这里)[MarshalAs(UnmanagedType.U4)]
.
当然,指定编组类型没有坏处(当它正确时)。
示例用法,使用计时器显示自上次输入以来经过的毫秒数:
// Better resolution than System.Windows.Forms.Timer
System.Timers.Timer sysIdleTimer = null;
// [...]
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
sysIdleTimer = new System.Timers.Timer() {
Interval = 100,
SynchronizingObject = this // Marshal events to the UI Thread
};
sysIdleTimer.Elapsed += OnTimerElapsed;
sysIdleTimer.Start();
}
static uint GetLastInputTimeMilliseconds()
{
var info = new LASTINPUTINFO(0);
if (GetLastInputInfo(ref info)) {
// Valid within 24.9 days of machine activity
uint idleTime = (uint)Environment.TickCount - info.dwTime;
return idleTime;
}
return 0;
}
protected void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// Shows the Input Idle time in a Label
lblInputIdle.Text = $"Idle Time: {GetLastInputTimeMilliseconds()} milliseconds";
}
我有以下代码:
using System;
using System.Runtime.InteropServices;
public class WindowsFunctions
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public static int TicksSinceLastInput()
{
var info = new LASTINPUTINFO();
GetLastInputInfo(ref info);
var lastInputTickCount = info.dwTime;
return (int)lastInputTickCount;
}
}
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
[MarshalAs(UnmanagedType.U4)]
public UInt32 cbSize;
[MarshalAs(UnmanagedType.U4)]
public UInt32 dwTime;
}
但是,在 运行 上,info.dwTime
为零。
运行 VS2019 IDE
更新:
我试着让 TicksSinceLastInput
不是静态的,但无论如何都失败了。
我失败的单元测试现在是:
[TestMethod]
public void TestTicksSinceLastInput()
{
var funcs = new WindowsFunctions();
var ticks = funcs.TicksSinceLastInput();
Assert.IsTrue( ticks > 0);
}
更新:
我的代码现在是:
public class WindowsFunctions
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
public int TicksSinceLastInput()
{
var info = new LASTINPUTINFO();
var result = GetLastInputInfo(ref info);
var lastInputTickCount = info.dwTime;
return (int)lastInputTickCount;
}
}
结果被设置为 false。
LASTINPUTINFO
的声明似乎来自 PInvoke.net。
该结构包含一个静态整数:
public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
它可能看起来像是在定义结构的大小,但它实际上没有实际用途。
在您的原始代码中,结构的 cbSize
成员未初始化,它必须是:它指定结构本身的大小;分配它是强制性的。
GetLastInputInfo函数声明正确:
[DllImport("user32.dll")]
static extern bool GetLastInputInfo(ref LASTINPUTINFO info);
它的return类型是BOOL
(定义为typedef int BOOL
),而不是BOOLEAN
(定义为typedef BYTE BOOLEAN
)。
BOOL
已托管,不需要:
[return: MarshalAs(UnmanagedType.Bool)]
可以简化 LASTINPUTINFO 结构的声明和初始化,以包含一个初始化其成员的非空构造函数:
[StructLayout(LayoutKind.Sequential)]
struct LASTINPUTINFO
{
public uint cbSize;
public uint dwTime;
public LASTINPUTINFO(uint init) {
cbSize = (uint)Marshal.SizeOf<LASTINPUTINFO>();
dwTime = init;
}
}
其成员的类型是:
UINT cbSize
:UINT
定义为typedef unsigned int UINT
,无符号整数。 这是一个托管类型,它不需要(这里)[MarshalAs(UnmanagedType.U4)]
DWORD dwTime
:DWORD
定义为typedef unsigned long DWORD
,是一个32位无符号整数。仍然管理,它不需要(这里)[MarshalAs(UnmanagedType.U4)]
.
当然,指定编组类型没有坏处(当它正确时)。
示例用法,使用计时器显示自上次输入以来经过的毫秒数:
// Better resolution than System.Windows.Forms.Timer
System.Timers.Timer sysIdleTimer = null;
// [...]
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
sysIdleTimer = new System.Timers.Timer() {
Interval = 100,
SynchronizingObject = this // Marshal events to the UI Thread
};
sysIdleTimer.Elapsed += OnTimerElapsed;
sysIdleTimer.Start();
}
static uint GetLastInputTimeMilliseconds()
{
var info = new LASTINPUTINFO(0);
if (GetLastInputInfo(ref info)) {
// Valid within 24.9 days of machine activity
uint idleTime = (uint)Environment.TickCount - info.dwTime;
return idleTime;
}
return 0;
}
protected void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// Shows the Input Idle time in a Label
lblInputIdle.Text = $"Idle Time: {GetLastInputTimeMilliseconds()} milliseconds";
}