You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:25:14