C# 讓電腦不要進入螢幕保護狀態 do not let windows into screen saver(lock)
對不起,管理員
因為公司強迫要求使用者未使用電腦情況下,5分鐘要鎖定螢幕,由於是使用AD強制控制,所以使用者沒有辦法自己去關閉。
而我,因為常有需要參考畫面上的內容,在另外一部電腦操作,因此導致這部電腦一直會進入螢幕鎖定。超級麻煩又討厭。
所以開發了一隻小程式來防止Windows進入螢幕鎖定狀態。
這是利用Timer不斷偵測 Idle 時間
而這個 Idle 時間則是利用 GetLastInputInfo 取得鍵盤滑鼠輸入的最後時間計算與現在的時間差得到的,當這個時間差超過預定檢測的時間(我的程式碼是設定4分鐘,因為進入螢幕鎖定是5分鐘)時,會去模擬滑鼠輸入動作,這個模擬動作是透過SendInput來達成,以上這些功能都是呼叫Windows API來處理。
由於Windows API是非託管程序(Unmanaged)因此得引用
using System.Runtime.InteropServices;
主程序:
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Configuration;
namespace DONTSLEEP
{
public partial class Form1 : Form
{
public int Idle_time = 240; //閒置秒數(4分鐘)
public int CCount = 0;
public bool shacking = false;
public enum MonitorState : int
{
MONITOR_ON = -1,
MONITOR_OFF = 2,
MONITOR_STANBY = 1
};
public Form1()
{
InitializeComponent();
string itvl = ConfigurationManager.AppSettings["interval"];
Idle_time = int.Parse(itvl);
timer1.Interval = 1000;//設定計時器幾毫秒執行一次
timer1.Enabled = true;//打開定時器
}
/// <summary>
/// 調用windows API獲取鼠標鍵盤空閒時間
/// </summary>
/// <param name="plii"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
/// <summary>
/// 調用windows API設定鼠標位置
/// </summary>
/// <param name="X"></param>
/// <param name="Y"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);
/// <summary>
/// 獲取鼠標鍵盤空閒時間
/// </summary>
/// <returns></returns>
public static long GetIdleTick()
{
LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
if (!GetLastInputInfo(ref lastInputInfo)) return 0;
return Environment.TickCount - (long)lastInputInfo.dwTime;
}
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO
{
[MarshalAs(UnmanagedType.U4)]
public int cbSize;
[MarshalAs(UnmanagedType.U4)]
public uint dwTime;
}
public int WM_SYSCOMMAND = 0x0112;
public int SC_MONITORPOWER = 0xF170;
[DllImport("user32.dll")]
private static extern int SendMessage(int hWnd, int hMsg, int wParam, int lParam);
private void timer1_Tick(object sender, EventArgs e)
{
int X = MousePosition.X;
int Y = MousePosition.Y;
label2.Text = X.ToString() + "," + Y.ToString(); // 顯示座標
long tick = GetIdleTick() / 1000;
if (tick > 0)//發生閒置
{
//如果滑鼠動作還在持續,則不要進入處理
if (shacking) return;
CCount++;
label1.Text = (Idle_time - CCount).ToString();
//檢查時間是否達到設定的處理時間
if (CCount == Idle_time)
{
shacking = true;
// off screen power
//SendMessage(this.Handle.ToInt32(), WM_SYSCOMMAND, SC_MONITORPOWER, (int)MonitorState.MONITOR_OFF);
// 模擬移動滑鼠
ShakeMouse(X, Y);
shacking = false;
CCount = 0;
}
}
else
{
label1.Text = "User Control";
CCount = 0;
}
}
async void ShakeMouse(int X , int Y)
{
//這道指令才有將LASTINPUTINFO時間歸0的作用
MouseSimulator.MouseMove(100, 100);
await Delay(200);
// 恢復滑鼠作標
SetCursorPos(X, Y);
await Delay(200);
}
async System.Threading.Tasks.Task Delay(int imSecond)
{
await System.Threading.Tasks.Task.Delay(imSecond);
}
}
}
模擬滑鼠輸入的類別:
using System;
using System.Runtime.InteropServices;
namespace DONTSLEEP
{
public class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001,
MOUSEEVENTF_LEFTDOWN = 0x0002,
MOUSEEVENTF_LEFTUP = 0x0004,
MOUSEEVENTF_RIGHTDOWN = 0x0008,
MOUSEEVENTF_RIGHTUP = 0x0010,
MOUSEEVENTF_MIDDLEDOWN = 0x0020,
MOUSEEVENTF_MIDDLEUP = 0x0040,
MOUSEEVENTF_XDOWN = 0x0080,
MOUSEEVENTF_XUP = 0x0100,
MOUSEEVENTF_WHEEL = 0x0800,
MOUSEEVENTF_VIRTUALDESK = 0x4000,
MOUSEEVENTF_ABSOLUTE = 0x8000
}
enum SendInputEventType : int
{
InputMouse,
InputKeyboard,
InputHardware
}
public static void ClickLeftMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
public static void ClickRightMouseButton()
{
INPUT mouseDownInput = new INPUT();
mouseDownInput.type = SendInputEventType.InputMouse;
mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN;
SendInput(1, ref mouseDownInput, Marshal.SizeOf(new INPUT()));
INPUT mouseUpInput = new INPUT();
mouseUpInput.type = SendInputEventType.InputMouse;
mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP;
SendInput(1, ref mouseUpInput, Marshal.SizeOf(new INPUT()));
}
public static void MouseMove(int X, int Y)
{
INPUT mouseMoveInput = new INPUT();
mouseMoveInput.type = SendInputEventType.InputMouse;
mouseMoveInput.mkhi.mi.dx = X;
mouseMoveInput.mkhi.mi.dy = Y;
mouseMoveInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_ABSOLUTE | MouseEventFlags.MOUSEEVENTF_MOVE | MouseEventFlags.MOUSEEVENTF_LEFTDOWN | MouseEventFlags.MOUSEEVENTF_LEFTUP;
mouseMoveInput.mkhi.mi.time = 0;
mouseMoveInput.mkhi.mi.mouseData = 0;
SendInput(1, ref mouseMoveInput, Marshal.SizeOf(new INPUT()));
}
}
}
參考來源:
https://www.codeproject.com/Questions/754626/Help-with-SendInput-and-Moving-Clicking-mouse-DELP
http://www.aspphp.online/bianchen/dnet/cxiapu/cxpjc/201701/132565.html
留言