Python實現(xiàn)局域網遠程控制電腦
1.簡介
一款由Python可以遠程控制局域網電腦關機、重啟、注銷、鎖定 、休眠、退出登錄甚至能操作遠程電腦Cmd終端命令的一款工具。資源及源碼已打包,大家可自行下載。
工具分為1.0以及2.0版本,2.0版本在1.0終端命令行模式更改為網頁界面化操作,可利用手機等多終端設備控制,更加美觀實用;優(yōu)化了端口設置,添加了條件判斷;可結合“Radmin_LAN”軟件,實現(xiàn)異地控制。工具可用Pyinstaller打包成無窗口后臺靜默運行。
默認賬號:root
默認密碼:123456
2. 運行效果
1.0版本運行效果:

2.0版本運行效果:
PC端頁面效果:
服務端頁面:

客戶端登錄頁面:

客戶端操作頁面:

手機移動端展示效果:


3. 1.0版本相關源碼
服務端server.py
import socket
import keyboard
import subprocess
import threading
import logging
import queue
'''
import win32gui
import win32con
# 獲取當前窗口句柄
hwnd = win32gui.GetForegroundWindow()
# 設置窗口屬性,隱藏窗口
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關閉服務器")
print()
ip1 = '192.168.137.1' # 默認ip地址
print(f"請輸入服務器IP地址(電腦的IPv4地址),不輸入默認為 {ip1}")
# 超時設置,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=("請輸入服務器IP地址:", 15, result_queue))
input_thread.start()
# 等待輸入,如果超時則返回默認值
input_thread.join(15)
if not result_queue.empty():
ip = result_queue.get()
if ip is None:
ip = ip1 # 如果用戶直接回車,使用默認值
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)
# 設置 SO_REUSEADDR 選項
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 綁定服務器地址和端口
server_address = (ip, 5000)
server_socket.bind(server_address)
# 監(jiān)聽連接
server_socket.listen(5) # 支持最多5個并發(fā)連接
print('服務器正在等待連接...')
def close_server():
print('服務器已關閉')
server_socket.close()
exit()
# 監(jiān)聽 F3 鍵關閉服務器
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ù)據: {data.decode()}")
# 解析賬號和密碼
try:
account, password = data.decode().split(':')
except ValueError:
logging.error("賬號和密碼格式錯誤")
message = '賬號和密碼格式錯誤!'
client_socket.send(message.encode())
return
# 驗證賬號和密碼
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':
# 關機
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("命令結果已發(fā)送")
except subprocess.CalledProcessError as e:
logging.error(f"{e.stderr}")
# 發(fā)送錯誤信息
client_socket.sendall(str(e).encode())
finally:
# 發(fā)送一個結束標記
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:
# 關閉連接
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('服務器已關閉')
break
else:
raise
input("按回車鍵退出...")
客戶端client.py
import socket
def run_script():
try:
print()
ip1 = '192.168.137.1'
print("請輸入服務器的IP地址,不輸入默認ip為", ip1)
print()
ip = input("請輸入服務器的IP地址:") or ip1
print()
# 服務器地址和端口
server_address = (ip, 5000)
# 創(chuàng)建一個 TCP/IP socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
# 連接到服務器
client_socket.connect(server_address)
print('已連接到服務器')
# 獲取用戶輸入的賬號和密碼
account = input('請輸入賬號:') or 'root'
password = input('請輸入密碼:') or '123456'
# 發(fā)送賬號和密碼
message = f'{account}:{password}'
client_socket.sendall(message.encode())
# 接收服務器響應
response = client_socket.recv(1024).decode()
print('服務器響應:', response)
if response == '登錄成功!':
print('登錄成功')
print()
# 發(fā)送默認請求
print("[0]退出登錄---[1]關機---[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())
# 設置超時時間
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:
# 關閉連接
client_socket.close()
user_choice = input("輸入1繼續(xù)運行,輸入2結束代碼: ")
if user_choice == '2':
print("結束代碼")
return
elif user_choice == '1':
print("繼續(xù)運行")
run_script()
else:
print("無效輸入,默認退出代碼")
except Exception as e:
print(f"An error occurred: {e}")
else:
print("Script completed successfully.")
run_script()
4. 2.0版本相關源碼
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:
# 連接到一個公網DNS服務器,不發(fā)送任何數(shù)據,只是為了獲取本地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可達,否則返回False
"""
try:
# 在Windows系統(tǒng)上使用-4參數(shù)強制使用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"從文件加載服務器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,因為文件不存在或內容為空
# 如果server_ip.txt中的IP不可用,嘗試獲取本機IP
if not server_ip:
server_ip = get_local_ip()
if server_ip:
print(f"獲取到服務器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("無法獲取本機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;
}
/* 結果顯示區(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;
}
/* 響應式設計 */
@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">關機</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>結果:</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": "關機成功"}), 200
except subprocess.CalledProcessError as e:
return jsonify({"message": "關機失敗", "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()
到此這篇關于Python實現(xiàn)局域網遠程控制電腦的文章就介紹到這了,更多相關Python遠程控制電腦內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python?Traceback(most?recent?call?last)報錯信息:示例解讀
這篇文章主要介紹了Python?Traceback(most?recent?call?last)報錯信息:示例解讀,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Python利用函數(shù)式編程實現(xiàn)優(yōu)化代碼
函數(shù)式編程(Functional Programming)是一種編程范式,它將計算視為函數(shù)的求值,并且避免使用可變狀態(tài)和循環(huán),在Python中還可以利用它的簡潔和高效來解決實際問題,下面我們就來學習一下它的具體用法吧2023-11-11
python四個坐標點對圖片區(qū)域最小外接矩形進行裁剪
在圖像裁剪操作中,opencv和pillow兩個庫都具有相應的函數(shù),如果想要對目標的最小外接矩形進行裁剪該如何操作呢?本文就來詳細的介紹一下2021-06-06
python數(shù)字圖像處理實現(xiàn)直方圖與均衡化
在圖像處理中,直方圖是非常重要,也是非常有用的一個處理要素。這篇文章主要介紹了python數(shù)字圖像處理實現(xiàn)直方圖與均衡化,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05

