做爲一個開發,個人電腦常常是一個禮拜不關機,甚至時間更久,不知道在其餘人看來這是否是一個常規操做。在平常工做中,咱們的電腦也是一直處於非鎖屏狀態,出於對我的工做成果的安全性保護,咱們公司給每一個人的電腦上下發了一個組策略(屬於強制下發,抗議無效),5min不對電腦進行操做,電腦就鎖屏,這可真是使人操蛋,出去上個廁所的功夫電腦就鎖屏啦、和別人討論問題的功夫電腦又鎖屏了,做爲一個開發,這真不能忍。html
最近一直在學習
python
,恰好接觸到了python
寫windows
服務相關的一些東西,嘿嘿,5分鐘不操做電腦鎖屏是吧,那麼咱們在無任何操做下2分鐘給他模擬一次鍵盤或者鼠標操做可好。python
要寫一個windows
服務也是比較簡單的,只須要繼承自win32serviceutil.ServiceFramework這個類,而後實現相關方法便可,主要的方法是SvcDoRun,服務啓動後,該方法處於激活狀態,該方法結束服務退出c++
具體的實現方式可參考Python-定時爬取指定城市天氣(二)-郵件提醒文章中的第三小節,優化定時任務。windows
python
實現這裏我只貼出關鍵代碼,服務的總體框架不在細說,不會的同窗請看這裏Python-定時爬取指定城市天氣(二)-郵件提醒安全
python
服務首先判斷鼠標2分鐘內是否有操做,咱們須要能獲取到當前鼠標位置的函數,pyautogui
是一個python
的自動化庫,知足咱們的需求,該庫提供了豐富的鼠標、鍵盤操做,使用該庫,首先就得使用pip進行安裝框架
pip install pyautogui函數
使用方式以下,x和y便是當前鼠標相對於屏幕左上角(0,0)的座標學習
import pyautogui as pag x, y = pag.position() #返回鼠標的座標
模擬鼠標、鍵盤操做,無非是鼠標點擊、移動、鍵盤按下等,這些pyautogui
都已經提供,看名字就知道什麼意思,這裏咱們先進行了鼠標點擊,默認是左鍵,而後移動了鼠標位置,而且在最後按下了鍵盤上的esc鍵測試
pag.click() pag.moveTo(x + 10, y + 10, 0.1) pag.moveTo(x, y, 0.1) writeLog('模擬一次鼠標移動\n')# pag.press('esc') writeLog('模擬點擊esc\n')#
完整的SvcDoRUn函數以下優化
def SvcDoRun(self): #what to do# prev_time = datetime.datetime.now() oldx = 0 oldy = 0 while self.run: x, y = pag.position() #返回鼠標的座標 now_time = datetime.datetime.now() if x == oldx and y == oldy: stay_seconds = (now_time - prev_time).seconds if stay_seconds >= 60: prev_time = now_time pag.click() pag.moveTo(x + 10, y + 10, 0.1) pag.moveTo(x, y, 0.1) writeLog('模擬一次鼠標移動\n')# pag.press('esc') writeLog('模擬點擊esc\n')# else: #更新舊座標 最後一次移動鼠標時間 oldx = x oldy = y prev_time = now_time #os.system('cls')#清楚屏幕 stay_seconds = (now_time - prev_time).seconds writeLog('鼠標{}秒未移動\n'.format(stay_seconds))#打印座標 posStr = "Position:" + str(x).rjust(4) + ',' + str(y).rjust(4) writeLog(posStr + '\n')#打印座標 time.sleep(2)
服務函數寫完了,接下來是打包服務的過程,並啓動服務
1. 打包服務成一個exe,pyinstaller -F aaa.py 2. 安裝服務 python aaa.exe install 3. 啓動服務 python aaa.exe start 4. 中止服務 python aaa.exe stop 5. 移除服務 python aaa.exe remove
執行上述流程的一、2和3,服務就已經被成功啓動,但不幸的是發現pag.position()
返回的座標一直是0,各類測試都不對,開始懷疑是服務裏可能找不到pyautogui
資源致使失敗,後來在網上找了另外一種或許鼠標位置的函數
def get_mouse_point(): po = POINT() windll.user32.GetCursorPos(byref(po)) return int(po.x), int(po.y)
通過測試,該函數單獨運行時沒有問題,放在服務裏拿到的座標仍是(0, 0),寫服務的路子算是泡湯啦
爲了更好的查找服務的運行狀態,咱們這裏把服務的運行時狀態卸載了一個文件裏,寫日誌代碼以下
#寫日誌 def writeLog(msg): try: f = open('./prevent_lock_screen.log', 'a', encoding = 'utf-8') f.write(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ':' + msg) f.close() except BaseException: pass
python
函數
python
服務的方式暫時算是中斷了,可是咱們仍是不能放棄啊,通過嘗試,把運行在服務裏的代碼拿出來放在正常python
文件裏執行仍是好使的。不明因此啊,++哪位大神若是知道服務裏的代碼爲何運行失敗,還請評論區支出,不勝感激。。。++
爲了防止電腦自動鎖屏,要一直運行一個dos
窗口看起來確實挺扯的,初學python
可能好多東西仍是不懂,所以爲了讓這個需求更優雅一些,我拿起了C++
,咱們仍是先來寫一個服務吧
C++
實現爲了實現這個需求,我也真是拼了
C++
服務不得不說,
C++
寫服務仍是挺費勁的,在網上扒了一個服務的模子,我便開始寫了,其實最主要的仍是要實現服務中的死循環函數,代碼邏輯和上述python
的思路一塊兒,區別就是咱們須要使用C++
的語法實現一遍而已。
POINT p; GetCursorPos(&p);//獲取鼠標座標 int x = p.x, y = p.y;//返回鼠標的座標 time_t now_time = time(NULL); if (x == oldx && y == oldy) { int stay_seconds = int(now_time - prev_time); if (stay_seconds >= 6) { prev_time = now_time; SetCursorPos(x + 10, y + 10); SetCursorPos(x, y); WriteToLog("模擬一次鼠標移動"); mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, x, y, 0, 0); WriteToLog("模擬鼠標單擊"); keybd_event('esc', 0, 0, 0); keybd_event('a', 0, 0, 0); WriteToLog("模擬點擊esc"); } } else { //更新舊座標 最後一次移動鼠標時間 oldx = x; oldy = y; prev_time = now_time; }
接下來的操做就是咱們須要把寫好的服務安裝並啓動
1. sc create test binPath= 可執行文件的路徑 2. net start test 3. net stop test 4. net delete test
執行上述步驟1和2便可啓動服務
通過測試,太不幸了,
GetCursorPos(&p)
返回的座標也爲(0, 0),這下真是鬱悶了,服務這條路難道真的走不通了嗎?看到的大神有解決思路的還請在評論區支出,不勝感激。。。
C++
可執行程序照搬照抄上述python
服務轉可執行程序的邏輯,咱們把C++
服務裏的代碼拿出來,放到 C++
可執行程序中,咱們也能夠實現一個C++
可執行程序
進過測試,以上
python
程序和C++
程序都還有一些問題,在一些特定的窗口上模擬鼠標、鍵盤操做很差使,好比notepad ++
、windows任務管理器等,系統在5分鐘後仍是鎖屏,思前想後,覺着這個可能和程序權限有關係,隨即把C++
工程的屬性進行了調整,生成的exe須要帶有管理員權限,在次進行測試,結果是完美的,咱們終於能夠防止系統自動鎖屏了,執行上述python的程序這裏就不作權限升級研究了,有興趣的同窗自行研究
c++
程序咱們能夠經過設置來吧程序設置成後臺運行的,沒有任何界面,這樣顯得更優雅一些,首先咱們建立的是一個dos程序,設置設置兩個地方便可
最開始的模擬用戶操做,咱們使用的是點擊鼠標左鍵、移動鼠標、和模擬點擊esc按鍵,可是上述操做都會不懂程度的帶來一些影響。
例如:
模擬操做優化過程
切換到桌面,隨即在開切換回來,這個操做相對來講比較靠譜,可是若是有一個窗口上有模態窗口存在,也會對打亂原始的窗口順序
點擊windows
鍵,隨即在點擊一次,恢復到點擊以前的狀態,這個操做相對第一種仍是比較友好的
點擊CapsLk按鍵,進行大小寫切換,因爲這個時候用戶沒有操做電腦,所以切換大小寫不會對用戶操做進行干擾,並且動靜更小、更優雅
上述3中模擬操做行爲基本思路都是同樣的,只是模擬的方式全部不一樣,下邊咱們就以第三種方式講解實現過程
點擊CapsLk的操做分兩部分,第一次主要是爲了模擬用戶點擊,第二次是爲了恢復第一次操做留下的痕跡,爲了讓程序更優雅的運行,咱們這裏須要啓動子線程來恢復主線程留下的痕跡
main函數代碼以下
hMutex = CreateMutex(NULL, FALSE, (LPCWSTR)"PreventLockScreenApp"); WaitForSingleObject(hMutex, INFINITE); HANDLE hThread = CreateThread(NULL, 0, RestoreWinState, NULL, 0, NULL); //建立線程01 CloseHandle(hThread); //關閉句柄 remove(LOGFILE); time_t prev_time = time(NULL);// int oldx = 0; int oldy = 0; char positionText[100] = { 0 }; sprintf(positionText, "防鎖屏進程已啓動,程序將在無鼠標移動狀況下每隔%d秒模擬一次鍵盤操做", Job_TIME); WriteToLog(positionText); while (1) { POINT p; GetCursorPos(&p);//獲取鼠標座標 int x = p.x, y = p.y;//返回鼠標的座標 time_t now_time = time(NULL); if (x == oldx && y == oldy) { int stay_seconds = int(now_time - prev_time); if (stay_seconds >= Job_TIME) { prev_time = now_time; keybd_event(VK_CAPITAL, (BYTE)0, 0, 0); keybd_event(VK_CAPITAL, (BYTE)0, KEYEVENTF_KEYUP, 0); WriteToLog("模擬點擊CapsLk,切換大小寫"); //釋放鎖 讓子線程去恢復win鍵狀態 ReleaseMutex(hMutex); Sleep(Restore_TIME / 2); WaitForSingleObject(hMutex, INFINITE); } } else { //更新舊座標 最後一次移動鼠標時間 oldx = x; oldy = y; prev_time = now_time; } int stay_seconds = int(now_time - prev_time); char mousemoved[100] = { 0 }; sprintf(mousemoved, "鼠標%d秒未移動", stay_seconds); WriteToLog(mousemoved);//打印座標 char positionText[100] = { 0 }; sprintf(positionText, "當前鼠標位置(%d,%d)", x, y); WriteToLog(positionText);//打印座標 Sleep(SLEEP_TIME); }
子線程代碼以下
void SimulationBehavior() { keybd_event(VK_CAPITAL, (BYTE)0, 0, 0); keybd_event(VK_CAPITAL, (BYTE)0, KEYEVENTF_KEYUP, 0); } DWORD WINAPI RestoreWinState(LPVOID lvParamter) { while (true) { WaitForSingleObject(hMutex, INFINITE); Sleep(Restore_TIME); SimulationBehavior(); ReleaseMutex(hMutex); } return 0; }
主子線程使用一個全局的信號量來進行同步
須要C++
和python
代碼的同窗到csdn
下載:C++實現的防鎖屏後臺進程-內含python實現代碼
博客園地址:防止系統鎖屏-python、C++實現
簡書地址:防止系統鎖屏-python、C++實現