WebDAV 挂载工具1.0

[复制链接]
124 |11
发表于 2025-11-12 15:37:12 | 显示全部楼层 |阅读模式

开发原因:每次设置都需要点来点去的,而且网站共享软件不支持http需要改注册表,设置也比较麻烦,主要为了方便小白,所以就开发这款工具直接一步到位的工具。
软件界面:


功能说明:
1.0

    检查管理员权限,强行要求必须管理员运行获取系统版本信息增加HTTP WebDAV支持选项勾选自动改注册表并重启WebClient服务,添加对大文件支持增加挂载失败的常见错误提示。增加自定义信息挂载功能。

1.5
    取消HTTP WebDAV支持选项勾选自动内部处理。添加了配置文件自动保存下次直接读取添加了批量添加功能



需要其他功能的请留言。
源码:
[Python]  
  1. import os
  2. import sys
  3. import ctypes
  4. import platform
  5. import subprocess
  6. import tkinter as tk
  7. from tkinter import messagebox, ttk
  8. import winreg
  9. import json
  10. from urllib.parse import urlparse
  11. def is_admin():
  12.     """检查是否以管理员权限运行"""
  13.     try:
  14.         return ctypes.windll.shell32.IsUserAnAdmin()
  15.     except:
  16.         return False
  17. def require_admin():
  18.     """如果未以管理员运行,则重新启动"""
  19.     if not is_admin():
  20.         ctypes.windll.shell32.ShellExecuteW(
  21.             None, "runas", sys.executable, " ".join(sys.argv), None, 1)
  22.         sys.exit()
  23. def get_windows_version():
  24.     """获取Windows系统版本信息"""
  25.     return platform.platform()
  26. def enable_http_webdav():
  27.     """启用HTTP WebDAV支持"""
  28.     try:
  29.         # 修改注册表以允许基本身份验证
  30.         subprocess.run([
  31.             'reg', 'add',
  32.             'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\WebClient\\Parameters',
  33.             '/v', 'BasicAuthLevel', '/t', 'REG_DWORD', '/d', '2', '/f'
  34.         ], check=True)
  35.         # 设置更大的文件大小限制(解决大文件问题)
  36.         subprocess.run([
  37.             'reg', 'add',
  38.             'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\WebClient\\Parameters',
  39.             '/v', 'FileSizeLimitInBytes', '/t', 'REG_DWORD', '/d', '0xFFFFFFFF', '/f'
  40.         ], check=True)
  41.         # 重启WebClient服务
  42.         subprocess.run(['net', 'stop', 'webclient'], check=True)
  43.         subprocess.run(['net', 'start', 'webclient'], check=True)
  44.         return True, "HTTP WebDAV支持已启用"
  45.     except subprocess.CalledProcessError as e:
  46.         return False, f"启用HTTP WebDAV失败: {e}"
  47.     except Exception as e:
  48.         return False, f"未知错误: {str(e)}"
  49. def check_webclient_service():
  50.     """检查WebClient服务状态"""
  51.     try:
  52.         result = subprocess.run(
  53.             ['sc', 'query', 'webclient'],
  54.             capture_output=True,
  55.             text=True
  56.         )
  57.         return "RUNNING" in result.stdout
  58.     except Exception as e:
  59.         return False
  60. def url_to_unc(server):
  61.     """将WebDAV URL转换为UNC路径"""
  62.     parsed = urlparse(server)
  63.     scheme = parsed.scheme.lower()
  64.     host = parsed.hostname
  65.     port = parsed.port
  66.     path = parsed.path.lstrip('/')
  67.     if scheme == 'http':
  68.         ssl = ''
  69.         default_port = 80
  70.     elif scheme == 'https':
  71.         ssl = '@SSL'
  72.         default_port = 443
  73.     else:
  74.         raise ValueError("仅支持HTTP或HTTPS协议")
  75.     if port and port != default_port:
  76.         unc_host = f"{host}@{port}"
  77.     else:
  78.         unc_host = host
  79.     unc = f"\\\\{unc_host}{ssl}\\DavWWWRoot\\{path}"
  80.     return unc
  81. def set_drive_label(drive_letter, nickname):
  82.     """设置驱动器标签(支持中文)"""
  83.     try:
  84.         # 使用 label 命令设置驱动器名称
  85.         subprocess.run(['label', f'{drive_letter}:', nickname], check=True, shell=True)
  86.         return True, "驱动器标签设置成功"
  87.     except subprocess.CalledProcessError as e:
  88.         return False, f"设置驱动器标签失败: {e}"
  89.     except Exception as e:
  90.         return False, f"设置驱动器标签失败: {str(e)}"
  91. def mount_webdav(server, drive_letter, username=None, password=None, nickname=None):
  92.     """挂载WebDAV到本地驱动器并设置昵称"""
  93.     try:
  94.         unc = url_to_unc(server)
  95.         # 先尝试取消可能存在的旧映射
  96.         subprocess.run(['net', 'use', f'{drive_letter}:', '/delete', '/y'],
  97.                       stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
  98.         # 构造net use命令
  99.         cmd = ['net', 'use', f'{drive_letter}:', unc, '/persistent:yes']
  100.         if username:
  101.             cmd.extend(['/user:' + username])
  102.             if password:
  103.                 cmd.append(password)
  104.         # 执行挂载命令
  105.         result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
  106.         if result.returncode == 0:
  107.             # 设置驱动器标签
  108.             if nickname:
  109.                 success, message = set_drive_label(drive_letter, nickname)
  110.                 if not success:
  111.                     return True, f"挂载成功,但{message}"
  112.             return True, "挂载成功"
  113.         else:
  114.             error_msg = result.stderr or "未知错误"
  115.             # 常见错误代码处理
  116.             if "67" in error_msg:
  117.                 return False, "错误67: 找不到网络名。请检查:\n1. WebDAV服务器地址是否正确\n2. 服务器是否运行\n3. 防火墙是否阻止连接"
  118.             elif "1219" in error_msg:
  119.                 return False, "错误1219: 已有其他用户使用相同凭证连接。请先断开所有连接或重启电脑。"
  120.             elif "1326" in error_msg:
  121.                 return False, "错误1326: 用户名或密码错误。"
  122.             else:
  123.                 return False, error_msg
  124.     except subprocess.TimeoutExpired:
  125.         return False, "连接超时,请检查网络连接"
  126.     except ValueError as ve:
  127.         return False, str(ve)
  128.     except Exception as e:
  129.         return False, str(e)
  130. class WebDAVMounterApp:
  131.     def __init__(self, root):
  132.         self.root = root
  133.         self.root.title("WebDAV 挂载工具 by吾爱破解")
  134.         self.root.geometry("500x650")
  135.         # 系统信息
  136.         self.windows_version = get_windows_version()
  137.         # 配置列表
  138.         self.configs = []
  139.         self.load_configs()
  140.         # 创建UI
  141.         self.create_ui()
  142.         # 强制启用HTTP WebDAV支持
  143.         self.check_webdav_support()
  144.     def load_configs(self):
  145.         """加载配置文件"""
  146.         config_file = 'config.json'
  147.         try:
  148.             with open(config_file, 'r', encoding='utf-8') as f:
  149.                 self.configs = json.load(f)
  150.         except FileNotFoundError:
  151.             with open(config_file, 'w', encoding='utf-8') as f:
  152.                 json.dump([], f)
  153.         except json.JSONDecodeError:
  154.             self.configs = []
  155.     def save_configs(self):
  156.         """保存配置到文件"""
  157.         config_file = 'config.json'
  158.         with open(config_file, 'w', encoding='utf-8') as f:
  159.             json.dump(self.configs, f, indent=4, ensure_ascii=False)
  160.     def create_ui(self):
  161.         """创建用户界面"""
  162.         # 系统信息标签
  163.         ttk.Label(self.root, text=f"系统版本: {self.windows_version}").pack(pady=5)
  164.         # 分隔线
  165.         ttk.Separator(self.root, orient='horizontal').pack(fill='x', pady=10)
  166.         # 单挂载部分
  167.         single_frame = ttk.LabelFrame(self.root, text="单个挂载", padding=(10, 5))
  168.         single_frame.pack(pady=10, fill='x')
  169.         ttk.Label(single_frame, text="WebDAV服务器地址 (例如: http://server.com/path):").pack()
  170.         self.server_entry = ttk.Entry(single_frame, width=50)
  171.         self.server_entry.pack()
  172.         self.server_entry.insert(0, "http://example.com/webdav")
  173.         ttk.Label(single_frame, text="本地驱动器盘符 (例如: Z):").pack()
  174.         self.drive_entry = ttk.Entry(single_frame, width=5)
  175.         self.drive_entry.pack()
  176.         self.drive_entry.insert(0, "U")
  177.         ttk.Label(single_frame, text="驱动器昵称 (支持中文,可选):").pack()
  178.         self.nickname_entry = ttk.Entry(single_frame, width=20)
  179.         self.nickname_entry.pack()
  180.         ttk.Label(single_frame, text="用户名 (可选):").pack()
  181.         self.user_entry = ttk.Entry(single_frame, width=20)
  182.         self.user_entry.pack()
  183.         ttk.Label(single_frame, text="密码 (可选):").pack()
  184.         self.pass_entry = ttk.Entry(single_frame, width=20, show="*")
  185.         self.pass_entry.pack()
  186.         # 保存配置按钮
  187.         ttk.Button(single_frame, text="保存配置", command=self.save_config).pack(pady=5)
  188.         self.mount_btn = ttk.Button(
  189.             single_frame,
  190.             text="挂载 WebDAV",
  191.             command=self.on_mount
  192.         )
  193.         self.mount_btn.pack(pady=10)
  194.         # 批量挂载部分
  195.         batch_frame = ttk.LabelFrame(self.root, text="批量挂载 (从config.json加载)", padding=(10, 5))
  196.         batch_frame.pack(pady=10, fill='both', expand=True)
  197.         columns = ("nickname", "server", "drive", "user")
  198.         self.config_tree = ttk.Treeview(batch_frame, columns=columns, show="headings")
  199.         self.config_tree.heading("nickname", text="昵称")
  200.         self.config_tree.heading("server", text="服务器地址")
  201.         self.config_tree.heading("drive", text="盘符")
  202.         self.config_tree.heading("user", text="用户名")
  203.         self.config_tree.pack(fill='both', expand=True)
  204.         # 填充配置
  205.         for config in self.configs:
  206.             self.config_tree.insert("", tk.END, values=(
  207.                 config.get("nickname", ""),
  208.                 config.get("server", ""),
  209.                 config.get("drive", ""),
  210.                 config.get("user", "")
  211.             ))
  212.         self.batch_btn = ttk.Button(
  213.             batch_frame,
  214.             text="批量挂载",
  215.             command=self.batch_mount
  216.         )
  217.         self.batch_btn.pack(pady=10)
  218.         # 日志区域
  219.         ttk.Label(self.root, text="日志:").pack()
  220.         self.log_text = tk.Text(self.root, height=10, width=60)
  221.         self.log_text.pack(pady=5)
  222.         # 状态标签
  223.         self.status_label = ttk.Label(
  224.             self.root,
  225.             text="准备就绪",
  226.             foreground="blue",
  227.             wraplength=400
  228.         )
  229.         self.status_label.pack()
  230.         # 自动加载第一个配置
  231.         if self.configs:
  232.             first_config = self.configs[0]
  233.             self.server_entry.delete(0, tk.END)
  234.             self.server_entry.insert(0, first_config.get("server", ""))
  235.             self.drive_entry.delete(0, tk.END)
  236.             self.drive_entry.insert(0, first_config.get("drive", ""))
  237.             self.nickname_entry.delete(0, tk.END)
  238.             self.nickname_entry.insert(0, first_config.get("nickname", ""))
  239.             self.user_entry.delete(0, tk.END)
  240.             self.user_entry.insert(0, first_config.get("user", ""))
  241.             self.pass_entry.delete(0, tk.END)
  242.             self.pass_entry.insert(0, first_config.get("pass", ""))
  243.     def save_config(self):
  244.         """保存当前输入的配置到config.json"""
  245.         server = self.server_entry.get().strip()
  246.         drive = self.drive_entry.get().strip().upper()
  247.         nickname = self.nickname_entry.get().strip() or ""
  248.         username = self.user_entry.get().strip() or ""
  249.         password = self.pass_entry.get().strip() or ""
  250.         if not server or not drive:
  251.             messagebox.showerror("错误", "请输入服务器地址和驱动器盘符")
  252.             return
  253.         if len(drive) != 1 or not drive.isalpha():
  254.             messagebox.showerror("错误", "驱动器盘符必须是单个字母 (A-Z)")
  255.             return
  256.         # 检查是否已存在相同配置
  257.         for config in self.configs:
  258.             if config.get("server") == server and config.get("drive") == drive:
  259.                 messagebox.showinfo("信息", "此配置已存在")
  260.                 return
  261.         # 添加新配置
  262.         new_config = {
  263.             "server": server,
  264.             "drive": drive,
  265.             "nickname": nickname,
  266.             "user": username,
  267.             "pass": password
  268.         }
  269.         self.configs.append(new_config)
  270.         self.save_configs()
  271.         # 更新Treeview
  272.         self.config_tree.insert("", tk.END, values=(nickname, server, drive, username))
  273.         self.log_text.insert(tk.END, f"配置已保存: {nickname or server} 到 {drive}:\n")
  274.         messagebox.showinfo("成功", "配置已保存到config.json")
  275.     def check_webdav_support(self):
  276.         """强制启用HTTP WebDAV支持"""
  277.         self.status_label.config(
  278.             text="正在启用WebClient服务...",
  279.             foreground="orange"
  280.         )
  281.         self.root.update()
  282.         success, message = enable_http_webdav()
  283.         if success:
  284.             self.status_label.config(
  285.                 text=message,
  286.                 foreground="green"
  287.             )
  288.             self.log_text.insert(tk.END, message + "\n")
  289.         else:
  290.             self.status_label.config(
  291.                 text=message,
  292.                 foreground="red"
  293.             )
  294.             self.log_text.insert(tk.END, message + "\n")
  295.             messagebox.showerror("错误", message)
  296.     def on_mount(self):
  297.         """单个挂载按钮点击事件"""
  298.         server = self.server_entry.get().strip()
  299.         drive = self.drive_entry.get().strip().upper()
  300.         nickname = self.nickname_entry.get().strip() or None
  301.         username = self.user_entry.get().strip() or None
  302.         password = self.pass_entry.get().strip() or None
  303.         if not server or not drive:
  304.             messagebox.showerror("错误", "请输入服务器地址和驱动器盘符")
  305.             return
  306.         if len(drive) != 1 or not drive.isalpha():
  307.             messagebox.showerror("错误", "驱动器盘符必须是单个字母 (A-Z)")
  308.             return
  309.         self.status_label.config(text="正在尝试挂载...", foreground="blue")
  310.         self.mount_btn.config(state='disabled')
  311.         self.root.update()
  312.         success, message = mount_webdav(server, drive, username, password, nickname)
  313.         if success:
  314.             self.status_label.config(text="挂载成功", foreground="green")
  315.             messagebox.showinfo("成功", f"WebDAV已成功挂载到 {drive}: ({nickname or '无昵称'})")
  316.             self.log_text.insert(tk.END, f"单个挂载成功: {nickname or server} 到 {drive}:\n")
  317.         else:
  318.             self.status_label.config(text=f"挂载失败: {message}", foreground="red")
  319.             messagebox.showerror("错误", f"挂载失败:\n{message}")
  320.             self.log_text.insert(tk.END, f"单个挂载失败: {nickname or server} - {message}\n")
  321.         self.mount_btn.config(state='normal')
  322.     def batch_mount(self):
  323.         """批量挂载"""
  324.         if not self.configs:
  325.             messagebox.showinfo("信息", "没有配置可挂载。请编辑config.json或保存新配置。")
  326.             return
  327.         self.status_label.config(text="正在批量挂载...", foreground="blue")
  328.         self.batch_btn.config(state='disabled')
  329.         self.root.update()
  330.         for config in self.configs:
  331.             server = config.get("server")
  332.             drive = config.get("drive", "").upper()
  333.             nickname = config.get("nickname") or None
  334.             username = config.get("user") or None
  335.             password = config.get("pass") or None
  336.             if not server or not drive:
  337.                 self.log_text.insert(tk.END, f"配置无效 (缺少server或drive): {config}\n")
  338.                 continue
  339.             if len(drive) != 1 or not drive.isalpha():
  340.                 self.log_text.insert(tk.END, f"无效盘符 {drive} for {nickname or server}\n")
  341.                 continue
  342.             success, message = mount_webdav(server, drive, username, password, nickname)
  343.             if success:
  344.                 self.log_text.insert(tk.END, f"挂载成功: {nickname or server} 到 {drive}:\n")
  345.             else:
  346.                 self.log_text.insert(tk.END, f"挂载失败: {nickname or server} - {message}\n")
  347.         self.status_label.config(text="批量挂载完成", foreground="green")
  348.         self.batch_btn.config(state='normal')
  349. if __name__ == "__main__":
  350.     # 强制要求管理员权限
  351.     require_admin()
  352.     # 创建GUI
  353.     root = tk.Tk()
  354.     app = WebDAVMounterApp(root)
  355.     # 设置窗口图标 (可选)
  356.     try:
  357.         root.iconbitmap(default='webdav.ico')
  358.     except:
  359.         pass
  360.     root.mainloop()
复制代码




1.0下载地址:  打包exe文件
链接:https://pan.baidu.com/s/1yzZhgX0iLigZiCdmy1Cc3A?pwd=52pj 提取码:52pj
1.5下载地址:  打包exe文件
链接: https://pan.baidu.com/s/1CDDIQyJRmQ58TAW6UKaHQA?pwd=52pj  提取码:52pj

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

发表于 2025-11-12 15:37:42 | 显示全部楼层
试了一下,不支持停用,退出后,不能保存配置,下将打开要重新设置。而且挂载只能以网域映射方式挂载,不能以本地硬盘方式挂载。
回复

使用道具 举报

发表于 2025-11-12 15:38:32 | 显示全部楼层
最好能默认强制 http 勾选,另外,默认打开是账号密码登录框,设置框可以弄个按钮进去配置添加信息。
回复

使用道具 举报

发表于 2025-11-12 15:39:03 | 显示全部楼层
终于碰上这样的软件了。好用!
回复

使用道具 举报

发表于 2025-11-12 15:39:08 | 显示全部楼层
感谢分享,在用RaiDrive,可以挂载NAS,不知道这个能不能支持
回复

使用道具 举报

发表于 2025-11-12 15:39:32 | 显示全部楼层
电脑上好像用的smb现在
回复

使用道具 举报

发表于 2025-11-12 15:39:48 | 显示全部楼层
感谢分享,不错的软件
回复

使用道具 举报

发表于 2025-11-12 15:40:00 | 显示全部楼层
很不错,Nice
回复

使用道具 举报

发表于 2025-11-12 15:40:35 | 显示全部楼层
很不多。谢谢分享了。整好需要呢。
回复

使用道具 举报

发表于 2025-11-12 15:41:02 | 显示全部楼层
感谢分享,先收藏备用!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表