如何在Tkinter标签页中嵌入Remote Desktop连接并实现免密登录?
问题描述
我需要实现点击Tkinter HOME标签页中的按钮,在新的Tkinter标签页内打开对应PC的远程桌面连接。当前代码点击按钮后会以独立的mstsc窗口打开远程桌面,而非嵌入到Tkinter标签页中。另外,我目前使用保存了用户名和密码的rdp文件,也希望了解Python中无需反复输入账号密码的其他远程桌面方案。
我的当前代码如下:
SETUPS = {'system_1': ['1', 'RDP1'], 'System_2': ['2', 'RDP2'], } from tkinter import Tk, Button import ttk main_frame = Tk() tab_handler = ttk.Notebook(main_frame) # this creates the TKINTER Home tab def home_tab(): h_tab = ttk.Frame(tab_handler) tab_handler.add(h_tab, text='HOME') tab_handler.grid(row=1, column=0, columnspan=4, padx=5) for idx,setup_name in enumerate(SETUPS.keys()): setup_button = Button(h_tab, name=f'{setup_name.lower()}_button', text=f'{SETUPS[setup_name][0]}', height=5, width=5, command=lambda name=setup_name.lower(): open_new_setup(system_name=name)) setup_button.grid(row=0, column=0+idx, sticky="W", padx=5, pady=5) # this function helps to open the tab on click of button def open_new_setup(system_name: str): setup_tab_name = ttk.Frame(tab_handler, name=system_name) tab_handler.add(setup_tab_name, text=system_name.upper()) connect_remote_desktop(remote_desktop_to_pc=SETUPS[system_name][1]) # select the tab which is opened tab_handler.select(setup_tab_name) tab_handler.grid(row=1, column=0, columnspan=4, padx=5) def connect_remote_desktop(remote_desktop_to_pc: str): import subprocess subprocess.call(["mstsc", remote_desktop_to_pc.lower()+'.rdp']) home_tab() # always open the app in full screen mode main_frame.attributes('-fullscreen', True) main_frame.mainloop()
解决方案
一、将远程桌面嵌入Tkinter标签页
mstsc.exe是独立的Windows应用程序,无法直接通过Tkinter组件嵌入,我们可以借助Windows API抓取mstsc窗口,将其设置为Tkinter框架的子窗口实现嵌入效果。修改后的代码如下:
SETUPS = {'system_1': ['1', 'RDP1'], 'System_2': ['2', 'RDP2'], } from tkinter import Tk, Button import ttk import subprocess import win32gui import win32con import time main_frame = Tk() tab_handler = ttk.Notebook(main_frame) # 创建HOME标签页 def home_tab(): h_tab = ttk.Frame(tab_handler) tab_handler.add(h_tab, text='HOME') tab_handler.grid(row=1, column=0, columnspan=4, padx=5) for idx,setup_name in enumerate(SETUPS.keys()): setup_button = Button(h_tab, name=f'{setup_name.lower()}_button', text=f'{SETUPS[setup_name][0]}', height=5, width=5, command=lambda name=setup_name.lower(): open_new_setup(system_name=name)) setup_button.grid(row=0, column=0+idx, sticky="W", padx=5, pady=5) # 打开新标签页并启动远程桌面 def open_new_setup(system_name: str): setup_tab_name = ttk.Frame(tab_handler, name=system_name) tab_handler.add(setup_tab_name, text=system_name.upper()) # 传递标签页框架作为父窗口 connect_remote_desktop(remote_desktop_to_pc=SETUPS[system_name][1], parent_frame=setup_tab_name) tab_handler.select(setup_tab_name) tab_handler.grid(row=1, column=0, columnspan=4, padx=5) def connect_remote_desktop(remote_desktop_to_pc: str, parent_frame=None): # 启动远程桌面,使用Popen避免阻塞主线程 subprocess.Popen(["mstsc", remote_desktop_to_pc.lower()+'.rdp']) # 等待窗口加载,时间根据网络情况调整 time.sleep(2) if parent_frame: # 获取Tkinter框架的句柄 parent_handle = parent_frame.winfo_id() # 查找目标mstsc窗口(根据窗口标题匹配,需根据实际情况调整) def find_target_window(hwnd, extra): window_title = win32gui.GetWindowText(hwnd) # 匹配远程PC名称或"远程桌面连接"标题 if remote_desktop_to_pc in window_title or "远程桌面连接" in window_title: extra.append(hwnd) return True target_windows = [] win32gui.EnumWindows(find_target_window, target_windows) if target_windows: mstsc_handle = target_windows[0] # 将mstsc窗口设置为Tkinter框架的子窗口 win32gui.SetParent(mstsc_handle, parent_handle) # 调整窗口大小适配标签页 win32gui.MoveWindow(mstsc_handle, 0, 0, parent_frame.winfo_width(), parent_frame.winfo_height(), True) # 移除窗口标题栏和边框,实现融合效果 style = win32gui.GetWindowLong(mstsc_handle, win32con.GWL_STYLE) style &= ~(win32con.WS_CAPTION | win32con.WS_THICKFRAME) win32gui.SetWindowLong(mstsc_handle, win32con.GWL_STYLE, style) win32gui.ShowWindow(mstsc_handle, win32con.SW_SHOW) home_tab() main_frame.attributes('-fullscreen', True) main_frame.mainloop()
关键说明:
- 需要提前安装
pywin32库:pip install pywin32 - 窗口标题匹配逻辑需根据实际环境调整,部分场景下远程桌面窗口标题会显示"远程桌面连接"加上PC名称
- 等待窗口加载的
time.sleep时间可根据网络速度微调,避免窗口未创建就执行查找逻辑
二、免密远程桌面的替代方案
1. 优化RDP凭据保存
你当前使用的RDP文件保存凭据方案可进一步优化,通过cmdkey工具提前存储凭据,避免手动输入:
cmdkey /generic:TERMSRV/远程PC的IP或名称 /user:用户名 /pass:密码
执行后,mstsc会自动读取已保存的凭据,无需重复输入。
2. 使用FreeRDP Python绑定(推荐嵌入场景)
FreeRDP是开源远程桌面客户端,其Python绑定pyfreerdp支持直接在应用窗口内渲染远程桌面,无需独立mstsc窗口,更适合嵌入场景。示例框架:
import pyfreerdp def render_callback(data, width, height): # 将渲染数据转换为Tkinter画布可识别的格式并绘制 pass # 初始化远程连接 rdp_client = pyfreerdp.RDP( server="远程PC的IP", username="用户名", password="密码", width=800, height=600, callback=render_callback ) # 在Tkinter标签页的画布中启动渲染 rdp_client.connect()
注:pyfreerdp需编译或从第三方源安装,部分环境需额外配置依赖。
3. WinRM协议(无可视化命令执行)
若仅需执行远程命令而非可视化桌面,可使用pywinrm通过WinRM协议操作:
import winrm # 建立远程会话 session = winrm.Session('远程PC的IP', auth=('用户名', '密码')) # 执行命令 result = session.run_cmd('ipconfig') # 打印输出 print(result.std_out.decode('utf-8'))
该方案无需打开桌面窗口,适合自动化运维场景。
内容的提问来源于stack exchange,提问作者Prabhjot Singh
相关产品推荐
相关产品推荐

