Python實(shí)現(xiàn)局域網(wǎng)遠(yuǎn)程控制電腦
1.簡介
一款由Python可以遠(yuǎn)程控制局域網(wǎng)電腦關(guān)機(jī)、重啟、注銷、鎖定 、休眠、退出登錄甚至能操作遠(yuǎn)程電腦Cmd終端命令的一款工具。資源及源碼已打包,大家可自行下載。
工具分為1.0以及2.0版本,2.0版本在1.0終端命令行模式更改為網(wǎng)頁界面化操作,可利用手機(jī)等多終端設(shè)備控制,更加美觀實(shí)用;優(yōu)化了端口設(shè)置,添加了條件判斷;可結(jié)合“Radmin_LAN”軟件,實(shí)現(xiàn)異地控制。工具可用Pyinstaller打包成無窗口后臺靜默運(yùn)行。
默認(rèn)賬號:root
默認(rèn)密碼:123456
2. 運(yùn)行效果
1.0版本運(yùn)行效果:
2.0版本運(yùn)行效果:
PC端頁面效果:
服務(wù)端頁面:
客戶端登錄頁面:
客戶端操作頁面:
手機(jī)移動端展示效果:
3. 1.0版本相關(guān)源碼
服務(wù)端server.py
import socket import keyboard import subprocess import threading import logging import queue ''' import win32gui import win32con # 獲取當(dāng)前窗口句柄 hwnd = win32gui.GetForegroundWindow() # 設(shè)置窗口屬性,隱藏窗口 win32gui.ShowWindow(hwnd, win32con.SW_HIDE) ''' # 配置日志 logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') print("客戶端登錄賬號:root,密碼:123456,F(xiàn)3關(guān)閉服務(wù)器") print() ip1 = '192.168.137.1' # 默認(rèn)ip地址 print(f"請輸入服務(wù)器IP地址(電腦的IPv4地址),不輸入默認(rèn)為 {ip1}") # 超時設(shè)置,15秒 def get_input(prompt, timeout, result_queue): try: user_input = input(prompt) if user_input.strip() == "": result_queue.put(None) # 如果用戶直接回車,返回None else: result_queue.put(user_input) except Exception as e: logging.error(f"輸入過程中發(fā)生錯誤: {e}") # 創(chuàng)建一個線程來獲取輸入 print("超時時間---15秒") print() result_queue = queue.Queue() input_thread = threading.Thread(target=get_input, args=("請輸入服務(wù)器IP地址:", 15, result_queue)) input_thread.start() # 等待輸入,如果超時則返回默認(rèn)值 input_thread.join(15) if not result_queue.empty(): ip = result_queue.get() if ip is None: ip = ip1 # 如果用戶直接回車,使用默認(rèn)值 else: ip = ip1 print(f"最終IP地址: {ip}") ''' def get_ipv4_address(): hostname = socket.gethostname() ip_address = socket.gethostbyname(hostname) return ip_address ip=get_ipv4_address() print(ip) ''' # 創(chuàng)建一個 TCP/IP socket server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 設(shè)置 SO_REUSEADDR 選項(xiàng) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # 綁定服務(wù)器地址和端口 server_address = (ip, 5000) server_socket.bind(server_address) # 監(jiān)聽連接 server_socket.listen(5) # 支持最多5個并發(fā)連接 print('服務(wù)器正在等待連接...') def close_server(): print('服務(wù)器已關(guān)閉') server_socket.close() exit() # 監(jiān)聽 F3 鍵關(guān)閉服務(wù)器 keyboard.add_hotkey('F3', close_server) def handle_client(client_socket, client_address): try: print('連接來自:', client_address) # 接收賬號和密碼 data = client_socket.recv(1024) logging.debug(f"接收到的數(shù)據(jù): {data.decode()}") # 解析賬號和密碼 try: account, password = data.decode().split(':') except ValueError: logging.error("賬號和密碼格式錯誤") message = '賬號和密碼格式錯誤!' client_socket.send(message.encode()) return # 驗(yàn)證賬號和密碼 if account == 'root' and password == '123456': # 發(fā)送成功消息 message = '登錄成功!' client_socket.send(message.encode()) # 接收客戶端請求 while True: request = client_socket.recv(1024).decode() logging.debug(f"接收到的請求: {request}") if request == '1': # 關(guān)機(jī) subprocess.call('shutdown /s /t 0', shell=True) elif request == '2': # 重啟 subprocess.call('shutdown /r /t 0', shell=True) elif request == '3': # 休眠 subprocess.call('rundll32.exe powrprof.dll,SetSuspendState 0,1,0', shell=True) elif request == '4': # 鎖定 subprocess.call('rundll32.exe user32.dll,LockWorkStation', shell=True) elif request == '0': # 退出登錄 print(client_address, "退出登錄") break elif request == '5': # 等待用戶輸入 user_input = 1 while True: # 執(zhí)行cmd命令 command = client_socket.recv(1024).decode() logging.debug(f"接收到的命令:{command}") try: # 執(zhí)行命令 result = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) # 獲取命令的輸出 output, error = result.communicate() # 打印命令的輸出到本地控制臺 logging.debug(f"{output}") # 發(fā)送命令的輸出 if error: output = " " client_socket.sendall(output.encode()) logging.debug(f"{error}") # 發(fā)送命令的錯誤 client_socket.sendall(error.encode()) logging.debug("命令結(jié)果已發(fā)送") except subprocess.CalledProcessError as e: logging.error(f"{e.stderr}") # 發(fā)送錯誤信息 client_socket.sendall(str(e).encode()) finally: # 發(fā)送一個結(jié)束標(biāo)記 client_socket.sendall(' '.encode()) # 等待用戶輸入 #接收客戶端的user_input值 user_input = client_socket.recv(1024).decode() logging.debug(f"接收到的請求: {user_input}") if user_input == '1': # 繼續(xù)執(zhí)行命令 continue elif user_input == '2': print(client_address, "退出登錄") # 退出循環(huán) break else: # 無效輸入 client_socket.sendall('無效輸入'.encode()) # 繼續(xù)執(zhí)行命令 continue else: # 無效輸入 client_socket.sendall('無效輸入'.encode()) else: # 無效請求 message = '無效請求!' client_socket.send(message.encode()) else: # 發(fā)送失敗消息 message = '賬號或密碼錯誤!' client_socket.send(message.encode()) except Exception as e: logging.error(f"處理客戶端連接時發(fā)生錯誤: {e}") finally: # 關(guān)閉連接 client_socket.close() while True: try: # 等待客戶端連接 client_socket, client_address = server_socket.accept() logging.debug(f"接受到來自 {client_address} 的連接") # 創(chuàng)建新線程處理客戶端連接 client_thread = threading.Thread(target=handle_client, args=(client_socket, client_address)) client_thread.start() except OSError as e: if e.errno == 10038: print('服務(wù)器已關(guān)閉') break else: raise input("按回車鍵退出...")
客戶端client.py
import socket def run_script(): try: print() ip1 = '192.168.137.1' print("請輸入服務(wù)器的IP地址,不輸入默認(rèn)ip為", ip1) print() ip = input("請輸入服務(wù)器的IP地址:") or ip1 print() # 服務(wù)器地址和端口 server_address = (ip, 5000) # 創(chuàng)建一個 TCP/IP socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: # 連接到服務(wù)器 client_socket.connect(server_address) print('已連接到服務(wù)器') # 獲取用戶輸入的賬號和密碼 account = input('請輸入賬號:') or 'root' password = input('請輸入密碼:') or '123456' # 發(fā)送賬號和密碼 message = f'{account}:{password}' client_socket.sendall(message.encode()) # 接收服務(wù)器響應(yīng) response = client_socket.recv(1024).decode() print('服務(wù)器響應(yīng):', response) if response == '登錄成功!': print('登錄成功') print() # 發(fā)送默認(rèn)請求 print("[0]退出登錄---[1]關(guān)機(jī)---[2]重啟---[3]休眠") print("[4]鎖定---[5]執(zhí)行cmd命令") print() request = input('輸入數(shù)字: ') or "5" # 你可以修改這個請求 if request in ['0', '1', '2', '3', '4', '5']: client_socket.sendall(request.encode()) print("請求已發(fā)送") if request == '0': print("退出登錄成功") elif request == '5': while True: # 獲取用戶輸入的命令 print() command = input('請輸入要執(zhí)行的命令:') or "echo %date% %time%" # 發(fā)送命令 client_socket.sendall(command.encode()) # 設(shè)置超時時間 client_socket.settimeout(60) try: print() print("接收超時時間為60秒") print() # 接收命令的輸出 data = b'' count = 0 while count < 2: packet = client_socket.recv(4096) data += packet count += 1 output = data.decode('utf-8', errors='ignore') print(output) except socket.timeout: print("接收命令的輸出超時") # 等待用戶輸入 print() user_input = input("是否繼續(xù)執(zhí)行命令?[1]繼續(xù)---[2]退出: ") or "1" if user_input == '1': # 發(fā)送 client_socket.sendall(user_input.encode()) # 繼續(xù)執(zhí)行命令 continue elif user_input == '2': print("退出登錄成功") break else: # 無效輸入 print('無效輸入,繼續(xù)執(zhí)行命令') # 發(fā)送 client_socket.sendall(user_input.encode()) # 繼續(xù)執(zhí)行命令 continue else: print("無效的請求") else: print('登錄失敗') finally: # 關(guān)閉連接 client_socket.close() user_choice = input("輸入1繼續(xù)運(yùn)行,輸入2結(jié)束代碼: ") if user_choice == '2': print("結(jié)束代碼") return elif user_choice == '1': print("繼續(xù)運(yùn)行") run_script() else: print("無效輸入,默認(rèn)退出代碼") except Exception as e: print(f"An error occurred: {e}") else: print("Script completed successfully.") run_script()
4. 2.0版本相關(guān)源碼
from flask import Flask, request, render_template_string, jsonify import subprocess import socket import os app = Flask(__name__) def get_local_ip(): try: with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: # 連接到一個公網(wǎng)DNS服務(wù)器,不發(fā)送任何數(shù)據(jù),只是為了獲取本地IP s.connect(("8.8.8.8", 53)) return s.getsockname()[0] except: return None # 如果無法獲取IP,返回None def load_server_ip(): ip_file = 'server_ip.txt' if not os.path.exists(ip_file): return None with open(ip_file, 'r') as f: ip = f.read().strip() return ip if ip else None def save_server_ip(ip): ip_file = 'server_ip.txt' with open(ip_file, 'w') as f: f.write(ip) def ping_ip(ip): """ Ping指定的IP,返回True如果IP可達(dá),否則返回False """ try: # 在Windows系統(tǒng)上使用-4參數(shù)強(qiáng)制使用IPv4 output = subprocess.check_output(['ping', '-4', '-n', '1', ip], stderr=subprocess.STDOUT, universal_newlines=True) if "unreachable" in output.lower(): return False return True except subprocess.CalledProcessError: return False def bind_server(host_ip): try: print(f"嘗試綁定到IP: {host_ip}") app.run(host=host_ip, port=80) except Exception as e: print(f"綁定到 {host_ip} 失敗: {e}") return False return True def main(): # 嘗試從server_ip.txt讀取IP server_ip = load_server_ip() if server_ip: print(f"從文件加載服務(wù)器IP: {server_ip}") if not ping_ip(server_ip): print(f"Ping測試失敗,IP {server_ip} 不可用") server_ip = None else: print(f"Ping測試成功,IP {server_ip} 可用") else: server_ip = None # 重置server_ip,因?yàn)槲募淮嬖诨騼?nèi)容為空 # 如果server_ip.txt中的IP不可用,嘗試獲取本機(jī)IP if not server_ip: server_ip = get_local_ip() if server_ip: print(f"獲取到服務(wù)器IP: {server_ip}") if not ping_ip(server_ip): print(f"Ping測試失敗,IP {server_ip} 不可用") server_ip = None else: print(f"Ping測試成功,IP {server_ip} 可用") save_server_ip(server_ip) else: print("無法獲取本機(jī)IP") # 嘗試綁定到server_ip if server_ip: if not bind_server(server_ip): # 如果綁定失敗,嘗試綁定到127.0.0.1 print("綁定到指定IP失敗,嘗試綁定到127.0.0.1") if not bind_server('127.0.0.1'): print("綁定到127.0.0.1也失敗,終止腳本") exit(1) else: # 如果沒有有效的IP,嘗試綁定到127.0.0.1 print("沒有有效的IP,嘗試綁定到127.0.0.1") if not bind_server('127.0.0.1'): print("綁定到127.0.0.1失敗,終止腳本") exit(1) @app.route('/', methods=['GET', 'POST']) def login(): if request.method == 'POST': data = request.form if 'username' in data and 'password' in data: username = data['username'] password = data['password'] print(f"Received username: {username}, password: {password}") if username == 'root' and password == '123456': # 這里是用戶名和密碼,請自行修改。 return render_template_string(''' <!DOCTYPE html> <html> <head> <title>登錄成功</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { font-family: Arial, sans-serif; margin: 20px; } h1, h2 { text-align: center; } /* 按鈕樣式 */ .btn { padding: 10px 20px; font-size: 16px; margin: 5px; border: none; border-radius: 4px; cursor: pointer; background-color: #007bff; color: white; } .btn:hover { background-color: #0056b3; } /* 輸入框樣式 */ #command-input { width: 100%; height: 100px; font-size: 16px; padding: 10px; resize: vertical; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } /* 結(jié)果顯示區(qū)域 */ #result { margin-top: 20px; padding: 10px; border: 1px solid #ddd; border-radius: 4px; background-color: #f9f9f9; white-space: pre-wrap; /* 保留換行 */ } /* 執(zhí)行按鈕樣式 */ #execute-button { float: right; margin-top: 10px; } /* 響應(yīng)式設(shè)計 */ @media (max-width: 600px) { .btn { width: 100%; font-size: 14px; } #command-input { height: 100px; font-size: 14px; } #execute-button { width: 100%; float: none; } #result { font-size: 14px; } } </style> </head> <body> <h1>登錄成功</h1> <div style="text-align: center;"> <button class="btn">退出登錄</button> <button class="btn">關(guān)機(jī)</button> <button class="btn">重啟</button> <button class="btn">休眠</button> <button class="btn">鎖定</button> </div> <br> <h2>執(zhí)行命令</h2> <textarea id="command-input" placeholder="請輸入命令"></textarea> <button id="execute-button" class="btn">執(zhí)行</button> <h3>結(jié)果:</h3> <div id="result"></div> <script> function logout() { fetch('/logout', { method: 'GET' }) .then(response => response.json()) .then(data => { alert(data.message); window.location.href = '/'; }); } function shutdown() { fetch('/shutdown', { method: 'GET' }) .then(response => response.json()) .then(data => alert(data.message)); } function restart() { fetch('/restart', { method: 'GET' }) .then(response => response.json()) .then(data => alert(data.message)); } function sleep() { fetch('/sleep', { method: 'GET' }) .then(response => response.json()) .then(data => alert(data.message)); } function lock() { fetch('/lock', { method: 'GET' }) .then(response => response.json()) .then(data => alert(data.message)); } function executeCommand() { const command = document.getElementById('command-input').value; fetch('/execute', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ command: command }) }) .then(response => response.json()) .then(data => { document.getElementById('result').innerText = data.output; }) .catch(error => { document.getElementById('result').innerText = '執(zhí)行失敗'; }); } </script> </body> </html> ''') else: return jsonify({"message": "登錄失敗"}), 401 else: return jsonify({"message": "缺少用戶名或密碼"}), 400 else: return render_template_string(''' <!DOCTYPE html> <html> <head> <title>登錄</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> body { font-family: Arial, sans-serif; margin: 20px; } form { max-width: 400px; margin: 0 auto; } input[type="text"], input[type="password"] { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } input[type="submit"] { width: 100%; padding: 10px; background-color: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer; } input[type="submit"]:hover { background-color: #218838; } @media (max-width: 600px) { form { max-width: 100%; } } </style> </head> <body> <h1>登錄</h1> <form method="post"> <input type="text" name="username" placeholder="用戶名"><br> <input type="password" name="password" placeholder="密碼"><br> <input type="submit" value="登錄"> </form> </body> </html> ''') @app.route('/logout', methods=['GET']) def logout(): return jsonify({"message": "退出登錄成功"}), 200 @app.route('/shutdown', methods=['GET']) def shutdown(): try: subprocess.run(["shutdown", "/s", "/t", "1"], check=True) return jsonify({"message": "關(guān)機(jī)成功"}), 200 except subprocess.CalledProcessError as e: return jsonify({"message": "關(guān)機(jī)失敗", "error": str(e)}), 500 @app.route('/restart', methods=['GET']) def restart(): try: subprocess.run(["shutdown", "/r", "/t", "1"], check=True) return jsonify({"message": "重啟成功"}), 200 except subprocess.CalledProcessError as e: return jsonify({"message": "重啟失敗", "error": str(e)}), 500 @app.route('/sleep', methods=['GET']) def sleep(): try: subprocess.run(["rundll32.exe", "powrprof.dll,SetSuspendState", "0,1,0"], check=True) return jsonify({"message": "休眠成功"}), 200 except subprocess.CalledProcessError as e: return jsonify({"message": "休眠失敗", "error": str(e)}), 500 @app.route('/lock', methods=['GET']) def lock(): try: subprocess.run(["rundll32", "user32.dll,LockWorkStation"], check=True) return jsonify({"message": "鎖定成功"}), 200 except subprocess.CalledProcessError as e: return jsonify({"message": "鎖定失敗", "error": str(e)}), 500 @app.route('/execute', methods=['POST']) def execute(): data = request.get_json() command = data.get('command', '') try: result = subprocess.run(command, shell=True, capture_output=True, text=True) output = result.stdout + result.stderr return jsonify({"output": output}), 200 except Exception as e: return jsonify({"output": f"執(zhí)行失敗: {str(e)}"}), 500 if __name__ == '__main__': main()
到此這篇關(guān)于Python實(shí)現(xiàn)局域網(wǎng)遠(yuǎn)程控制電腦的文章就介紹到這了,更多相關(guān)Python遠(yuǎn)程控制電腦內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Matplotlib繪制混淆矩陣的實(shí)現(xiàn)
對于機(jī)器學(xué)習(xí)多分類模型來說,其評價指標(biāo)除了精度之外,常用的還有混淆矩陣和分類報告,下面來展示一下如何繪制混淆矩陣,這在論文中經(jīng)常會用到。感興趣的可以了解一下2021-05-05Python?Traceback(most?recent?call?last)報錯信息:示例解讀
這篇文章主要介紹了Python?Traceback(most?recent?call?last)報錯信息:示例解讀,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12修改默認(rèn)的pip版本為對應(yīng)python2.7的方法
今天小編就為大家分享一篇修改默認(rèn)的pip版本為對應(yīng)python2.7的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11Python利用函數(shù)式編程實(shí)現(xiàn)優(yōu)化代碼
函數(shù)式編程(Functional Programming)是一種編程范式,它將計算視為函數(shù)的求值,并且避免使用可變狀態(tài)和循環(huán),在Python中還可以利用它的簡潔和高效來解決實(shí)際問題,下面我們就來學(xué)習(xí)一下它的具體用法吧2023-11-11python四個坐標(biāo)點(diǎn)對圖片區(qū)域最小外接矩形進(jìn)行裁剪
在圖像裁剪操作中,opencv和pillow兩個庫都具有相應(yīng)的函數(shù),如果想要對目標(biāo)的最小外接矩形進(jìn)行裁剪該如何操作呢?本文就來詳細(xì)的介紹一下2021-06-06python數(shù)字圖像處理實(shí)現(xiàn)直方圖與均衡化
在圖像處理中,直方圖是非常重要,也是非常有用的一個處理要素。這篇文章主要介紹了python數(shù)字圖像處理實(shí)現(xiàn)直方圖與均衡化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05