import tkinter as tk
from tkinter import ttk, messagebox
import json
import subprocess
import socket
import os
from pathlib import Path
class NetworkConfigManager:
def __init__(self, root):
self.root = root
self.root.title("网络配置管理器")
self.root.geometry("800x600")
# 加载配置文件
self.config_file = Path("network_profiles.json")
self.load_profiles()
# 创建主框架
self.create_main_frame()
# 获取网络接口列表
self.get_network_interfaces()
def load_profiles(self):
"""加载保存的网络配置文件"""
if self.config_file.exists():
with open(self.config_file, 'r', encoding='utf-8') as f:
self.profiles = json.load(f)
else:
self.profiles = []
def save_profiles(self):
"""保存网络配置到文件"""
with open(self.config_file, 'w', encoding='utf-8') as f:
json.dump(self.profiles, f, ensure_ascii=False, indent=2)
def get_network_interfaces(self):
"""获取系统中的网络接口列表"""
try:
# 使用 netsh 命令获取网络接口列表
result = subprocess.run(['netsh', 'interface', 'show', 'interface'],
capture_output=True, text=True, encoding='gbk')
# 解析输出获取接口名称
lines = result.stdout.split('\n')[3:] # 跳过头部信息
interfaces = []
for line in lines:
if line.strip():
parts = line.split()
if len(parts) >= 4:
interfaces.append(parts[-1])
# 更新下拉列表
self.interface_combo['values'] = interfaces
if interfaces:
self.interface_combo.set(interfaces[0])
except subprocess.CalledProcessError as e:
messagebox.showerror("错误", f"获取网络接口失败: {str(e)}")
def create_main_frame(self):
"""创建主界面"""
# 网络接口选择区域
interface_frame = ttk.LabelFrame(self.root, text="网络接口", padding=10)
interface_frame.pack(fill=tk.X, padx=10, pady=5)
ttk.Label(interface_frame, text="选择网络接口:").pack(side=tk.LEFT)
self.interface_combo = ttk.Combobox(interface_frame, width=30)
self.interface_combo.pack(side=tk.LEFT, padx=5)
ttk.Button(interface_frame, text="刷新", command=self.get_network_interfaces).pack(side=tk.LEFT, padx=5)
# 配置文件列表
profiles_frame = ttk.LabelFrame(self.root, text="保存的配置", padding=10)
profiles_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
# 创建Treeview来显示配置列表
columns = ('名称', 'IP地址', '子网掩码', '网关', '主DNS', '备用DNS')
self.profile_tree = ttk.Treeview(profiles_frame, columns=columns, show='headings')
# 设置列头
for col in columns:
self.profile_tree.heading(col, text=col)
self.profile_tree.column(col, width=100)
# 添加滚动条
scrollbar = ttk.Scrollbar(profiles_frame, orient=tk.VERTICAL, command=self.profile_tree.yview)
self.profile_tree.configure(yscrollcommand=scrollbar.set)
self.profile_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 更新配置列表
self.update_profile_list()
# 按钮区域
button_frame = ttk.Frame(self.root, padding=10)
button_frame.pack(fill=tk.X, padx=10, pady=5)
ttk.Button(button_frame, text="添加配置", command=self.show_add_profile_window).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="删除配置", command=self.delete_profile).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="应用配置", command=self.apply_profile).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="设置DHCP", command=self.set_dhcp).pack(side=tk.LEFT, padx=5)
def show_add_profile_window(self):
"""显示添加配置窗口"""
add_window = tk.Toplevel(self.root)
add_window.title("添加新配置")
add_window.geometry("400x500")
add_window.transient(self.root)
# 创建主框架并添加内边距
main_frame = ttk.Frame(add_window, padding="10")
main_frame.pack(fill=tk.BOTH, expand=True)
# 创建输入框框架
input_frame = ttk.Frame(main_frame)
input_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
# 添加输入框
labels = ["配置名称:", "IP地址:", "子网掩码:", "默认网关:", "主DNS服务器:", "备用DNS服务器:"]
entries = {}
for i, label in enumerate(labels):
ttk.Label(input_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=5)
entry = ttk.Entry(input_frame, width=40)
entry.grid(row=i, column=1, sticky=tk.W, padx=5, pady=5)
entries[label] = entry
# 设置默认子网掩码
entries["子网掩码:"].insert(0, "255.255.255.0")
# 创建按钮框架
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=(0, 10))
def save_profile():
"""保存新配置"""
profile = {
"名称": entries["配置名称:"].get(),
"IP地址": entries["IP地址:"].get(),
"子网掩码": entries["子网掩码:"].get(),
"网关": entries["默认网关:"].get(),
"主DNS": entries["主DNS服务器:"].get(),
"备用DNS": entries["备用DNS服务器:"].get()
}
if not all([profile["名称"], profile["IP地址"], profile["子网掩码"], profile["网关"]]):
messagebox.showerror("错误", "请填写必要的配置信息")
return
self.profiles.append(profile)
self.save_profiles()
self.update_profile_list()
add_window.destroy()
messagebox.showinfo("成功", "配置已保存")
def cancel():
"""取消添加"""
add_window.destroy()
# 添加保存和取消按钮
ttk.Button(button_frame, text="保存", command=save_profile).pack(side=tk.RIGHT, padx=5)
ttk.Button(button_frame, text="取消", command=cancel).pack(side=tk.RIGHT, padx=5)
# 设置焦点到第一个输入框
entries["配置名称:"].focus()
# 绑定回车键到保存功能
add_window.bind('<Return>', lambda e: save_profile())
# 使窗口模态
add_window.grab_set()
add_window.wait_window()
def update_profile_list(self):
"""更新配置列表显示"""
for item in self.profile_tree.get_children():
self.profile_tree.delete(item)
for profile in self.profiles:
values = [profile[key] for key in ('名称', 'IP地址', '子网掩码', '网关', '主DNS', '备用DNS')]
self.profile_tree.insert('', tk.END, values=values)
def delete_profile(self):
"""删除选中的配置"""
selected = self.profile_tree.selection()
if not selected:
messagebox.showwarning("警告", "请先选择要删除的配置")
return
if messagebox.askyesno("确认", "确定要删除选中的配置吗?"):
for item in selected:
values = self.profile_tree.item(item)['values']
self.profiles = [p for p in self.profiles if p['名称'] != values[0]]
self.save_profiles()
self.update_profile_list()
def apply_profile(self):
"""应用选中的配置"""
selected = self.profile_tree.selection()
if not selected:
messagebox.showwarning("警告", "请先选择要应用的配置")
return
interface = self.interface_combo.get()
if not interface:
messagebox.showwarning("警告", "请先选择网络接口")
return
values = self.profile_tree.item(selected[0])['values']
profile = {
"ip_address": values[1],
"subnet_mask": values[2],
"gateway": values[3],
"primary_dns": values[4],
"secondary_dns": values[5]
}
try:
# 设置静态IP
subprocess.run([
'netsh', 'interface', 'ip', 'set', 'address',
interface, 'static', profile['ip_address'],
profile['subnet_mask'], profile['gateway']
], check=True)
# 设置DNS
subprocess.run([
'netsh', 'interface', 'ip', 'set', 'dns',
interface, 'static', profile['primary_dns']
], check=True)
if profile['secondary_dns']:
subprocess.run([
'netsh', 'interface', 'ip', 'add', 'dns',
interface, profile['secondary_dns'], 'index=2'
], check=True)
messagebox.showinfo("成功", "网络配置已成功应用")
except subprocess.CalledProcessError as e:
messagebox.showerror("错误", f"应用配置失败: {str(e)}")
def set_dhcp(self):
"""设置DHCP"""
interface = self.interface_combo.get()
if not interface:
messagebox.showwarning("警告", "请先选择网络接口")
return
try:
subprocess.run(['netsh', 'interface', 'ip', 'set', 'address',
interface, 'dhcp'], check=True)
subprocess.run(['netsh', 'interface', 'ip', 'set', 'dns',
interface, 'dhcp'], check=True)
messagebox.showinfo("成功", "已成功设置为DHCP模式")
except subprocess.CalledProcessError as e:
messagebox.showerror("错误", f"设置DHCP失败: {str(e)}")
def main():
root = tk.Tk()
app = NetworkConfigManager(root)
root.mainloop()
if __name__ == "__main__":
main()