vb.net 模拟用户操作以防止系统被视为空闲的最简单方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18214065/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 14:38:33  来源:igfitidea点击:

Easiest way to simulate user action to prevent system being considered idle

c#vb.netwinforms

提问by John Bustos

I know this question must have been asked hundreds of times before and so, maybe, I'm just doing something wrong. But I have a WinForms program I'm writing to try and keep the system appearing active so as to stop it as registering idle.

我知道这个问题以前肯定被问过数百次,所以,也许,我只是做错了什么。但是我有一个 WinForms 程序,我正在编写它来尝试使系统保持活动状态,以阻止它注册空闲。

I figured that having a Timer on my form and doing something as simple as either moving the mouse via System.Windows.Forms.Cursor.Positionor using the SendKeys.Sendmethod would be enough to register user interaction, but it's not registering as user action and still letting the system appear as inactive after a set amount of time.

我认为在我的表单上有一个 Timer 并做一些像通过移动鼠标System.Windows.Forms.Cursor.Position或使用该SendKeys.Send方法这样简单的事情就足以注册用户交互,但它并没有注册为用户操作并且仍然让系统在设置后显示为非活动状态多少时间。

My code is fairly straightforward... Either:

我的代码相当简单......要么:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick
    SendKeys.Send("+")
End Sub

Or doing something along the lines of:

或者按照以下方式做一些事情:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick
    Dim MyMousePosition As Point
    MyMousePosition = Windows.Forms.Cursor.Position

    Windows.Forms.Cursor.Position = New Point(MyMousePosition.X - 10, MyMousePosition.Y)
End Sub

But neither is doing the trick... How can I get this to work AND preferably in a way that would be of least inconvnience to a user if they are actually using the system? (Meaning that I don't want to send a bunch of keys that may mess up the user if they're actually being active or move the mouse clear across the screen)

但两者都没有做到这一点......我怎样才能让它工作,并且最好以一种对用户来说最不方便的方式在他们实际使用系统时?(这意味着我不想发送一堆可能会弄乱用户的键,如果他们实际上处于活动状态或在屏幕上移动鼠标清除)

I know this coce is in VB, but I'm good with VB / C# solutions.

我知道这个 coce 在 VB 中,但我很擅长 VB/C# 解决方案。

Thanks!!!

谢谢!!!



EDIT

编辑

As an addition to this question, I used the GetLastInputInfofrom the User32.dllto check on the system activity.

作为这个问题的补充,我使用了GetLastInputInfofromUser32.dll来检查系统活动。

Even with my mouse / keyboard events linked to the Timer_Tickevent, GetLastInputInfoonly gets reset if I physically move the mouse / perform some action on the computer...

即使我的鼠标/键盘事件与事件相关联Timer_Tick,也GetLastInputInfo只有在我物理移动鼠标/在计算机上执行某些操作时才会重置...

I guess my question is What events can I add to my Timer_Tick event that will reset the GetLastInputInfo- In other words, have windows believe the user actually did something on the machine??

我想我的问题是 我可以向 Timer_Tick 事件添加哪些事件来重置GetLastInputInfo- 换句话说,让 Windows 相信用户实际上在机器上做了什么?

Thanks!!!

谢谢!!!

回答by John Bustos

After a lot of playing around, I came up with a solution that worked and I'm answering this question so as to help anyone out there that may be looking for the same information.

经过大量的尝试,我想出了一个有效的解决方案,我正在回答这个问题,以帮助可能正在寻找相同信息的任何人。

(Coded in VB):

(用VB编码):

In Declarations Section:

在声明部分:

Private Declare Function SendInput Lib "user32.dll" (ByVal nInputs As Integer, ByRef pInputs As INPUT_TYPE, ByVal cbSize As Integer) As Integer
Const INPUT_MOUSE = 0
Const MOUSEEVENTF_MOVE = &H1

Public Structure MOUSEINPUT
    Public dx As Integer
    Public dy As Integer
    Public mouseData As Integer
    Public dwFlags As Integer
    Public dwtime As Integer
    Public dwExtraInfo As Integer
End Structure

Public Structure INPUT_TYPE
    Public dwType As Integer
    Public xi As MOUSEINPUT
End Structure

The Sub to move the mouse:

Sub 移动鼠标:

Public Sub MoveMouse(ByVal x As Integer, ByVal y As Integer, ByVal flag As Integer)

    Dim inputEvents As INPUT_TYPE
    Dim xi As New MOUSEINPUT

    xi.dx = x
    xi.dy = y
    xi.mouseData = 0
    xi.dwtime = 0
    xi.dwFlags = flag
    xi.dwExtraInfo = 0

    inputEvents.dwType = INPUT_MOUSE
    inputEvents.xi = xi

    SendInput(1, inputEvents, Len(inputEvents))
End Sub

The Code in the Timer_Tick Event:

Timer_Tick 事件中的代码:

Private Sub Updater_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Updater.Tick

    ' Move the mouse (relatively) 1 pixel away and then back
    MoveMouse(1, 1, MOUSEEVENTF_MOVE)
    MoveMouse(-1, -1, MOUSEEVENTF_MOVE)

End Sub


I tested this using the GetLastInputInfoAPI function and it works!!

我使用GetLastInputInfoAPI 函数对此进行了测试,并且有效!!

... The most helpful link I found was this one: http://homeofcox-cs.blogspot.com/2008/07/c-simulate-mouse-and-keyboard-events.html

...我发现的最有用的链接是这个:http: //homeofcox-cs.blogspot.com/2008/07/c-simulate-mouse-and-keyboard-events.html

Thank you all for all your help and I hope this helps other people too!!

感谢大家的帮助,我希望这也能帮助其他人!!

回答by No Idea For Name

when we needed the system not to go idle (in WM 6.0 when we ha long logic and the device went idle the logic stopped working) we used

当我们需要系统不空闲时(在 WM 6.0 中,当我们有很长的逻辑并且设备空闲时,逻辑停止工作)我们使用

  [DllImport("CoreDll.dll")]
  public static extern void SystemIdleTimerReset();

it reset the idle timer, not interfering with the user's actions and it worked like charm

它重置空闲计时器,不干扰用户的操作,它的工作就像魅力一样

回答by Giulio Franco

There is a much simpler way, that consists in calling the Win32 function:

有一种更简单的方法,即调用Win32 函数

EXECUTION_STATE WINAPI SetThreadExecutionState(
  _In_  EXECUTION_STATE esFlags
);

with ES_SYSTEM_REQUIRED | ES_CONTINUOUSas argument. Anyway, from thisSO issue, it seems that the effect will not persist, even if ES_CONTINUOUSis used. In that case, you should call the function periodically, say every minute, to reset the idle timer. An important thing is that the function only applies to the thread that called it, and its effect terminates when the thread terminates.

ES_SYSTEM_REQUIRED | ES_CONTINUOUS作为参数。不管怎样,从这个SO issue看来,即使ES_CONTINUOUS使用了效果也不会持久。在这种情况下,您应该定期调用该函数,例如每分钟调用一次,以重置空闲计时器。很重要的一点是,该函数只适用于调用它的线程,当线程终止时,它的作用也就终止了。

When you're done, you should call SetThreadExecutionState(ES_CONTINUOUS)to allow the system to go idle again.

完成后,您应该调用SetThreadExecutionState(ES_CONTINUOUS)让系统再次空闲。