C# 讓電腦不要進入螢幕保護狀態 do not let windows into screen saver(lock)

 對不起,管理員

因為公司強迫要求使用者未使用電腦情況下,5分鐘要鎖定螢幕,由於是使用AD強制控制,所以使用者沒有辦法自己去關閉。

而我,因為常有需要參考畫面上的內容,在另外一部電腦操作,因此導致這部電腦一直會進入螢幕鎖定。超級麻煩又討厭。

所以開發了一隻小程式來防止Windows進入螢幕鎖定狀態。


  程式下載(我只想使用):這裡
  密碼:radio-idea.blogspot.com
  平台:.Net FrameWork 4.5
  注意:可能會與軟體KVM衝突

這是利用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://stackoverflow.com/questions/5094398/how-to-programmatically-mouse-move-click-right-click-and-keypress-etc-in-winfo

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

https://dotblogs.com.tw/hung-chin/2011/10/04/38752

留言

這個網誌中的熱門文章

【研究】列印的條碼為什麼很難刷(掃描)

C# 使用 Process.Start 執行外部程式

統一發票列印小程式