骑着悟空看八戒 发表于 2025-11-12 15:37:12

WebDAV 挂载工具1.0


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


功能说明:
1.0

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

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



需要其他功能的请留言。
源码:

import os
import sys
import ctypes
import platform
import subprocess
import tkinter as tk
from tkinter import messagebox, ttk
import winreg
import json
from urllib.parse import urlparse

def is_admin():
    """检查是否以管理员权限运行"""
    try:
      return ctypes.windll.shell32.IsUserAnAdmin()
    except:
      return False

def require_admin():
    """如果未以管理员运行,则重新启动"""
    if not is_admin():
      ctypes.windll.shell32.ShellExecuteW(
            None, "runas", sys.executable, " ".join(sys.argv), None, 1)
      sys.exit()

def get_windows_version():
    """获取Windows系统版本信息"""
    return platform.platform()

def enable_http_webdav():
    """启用HTTP WebDAV支持"""
    try:
      # 修改注册表以允许基本身份验证
      subprocess.run([
            'reg', 'add',
            'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\WebClient\\Parameters',
            '/v', 'BasicAuthLevel', '/t', 'REG_DWORD', '/d', '2', '/f'
      ], check=True)

      # 设置更大的文件大小限制(解决大文件问题)
      subprocess.run([
            'reg', 'add',
            'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\WebClient\\Parameters',
            '/v', 'FileSizeLimitInBytes', '/t', 'REG_DWORD', '/d', '0xFFFFFFFF', '/f'
      ], check=True)

      # 重启WebClient服务
      subprocess.run(['net', 'stop', 'webclient'], check=True)
      subprocess.run(['net', 'start', 'webclient'], check=True)

      return True, "HTTP WebDAV支持已启用"
    except subprocess.CalledProcessError as e:
      return False, f"启用HTTP WebDAV失败: {e}"
    except Exception as e:
      return False, f"未知错误: {str(e)}"

def check_webclient_service():
    """检查WebClient服务状态"""
    try:
      result = subprocess.run(
            ['sc', 'query', 'webclient'],
            capture_output=True,
            text=True
      )
      return "RUNNING" in result.stdout
    except Exception as e:
      return False

def url_to_unc(server):
    """将WebDAV URL转换为UNC路径"""
    parsed = urlparse(server)
    scheme = parsed.scheme.lower()
    host = parsed.hostname
    port = parsed.port
    path = parsed.path.lstrip('/')

    if scheme == 'http':
      ssl = ''
      default_port = 80
    elif scheme == 'https':
      ssl = '@SSL'
      default_port = 443
    else:
      raise ValueError("仅支持HTTP或HTTPS协议")

    if port and port != default_port:
      unc_host = f"{host}@{port}"
    else:
      unc_host = host

    unc = f"\\\\{unc_host}{ssl}\\DavWWWRoot\\{path}"
    return unc

def set_drive_label(drive_letter, nickname):
    """设置驱动器标签(支持中文)"""
    try:
      # 使用 label 命令设置驱动器名称
      subprocess.run(['label', f'{drive_letter}:', nickname], check=True, shell=True)
      return True, "驱动器标签设置成功"
    except subprocess.CalledProcessError as e:
      return False, f"设置驱动器标签失败: {e}"
    except Exception as e:
      return False, f"设置驱动器标签失败: {str(e)}"

def mount_webdav(server, drive_letter, username=None, password=None, nickname=None):
    """挂载WebDAV到本地驱动器并设置昵称"""
    try:
      unc = url_to_unc(server)

      # 先尝试取消可能存在的旧映射
      subprocess.run(['net', 'use', f'{drive_letter}:', '/delete', '/y'],
                      stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)

      # 构造net use命令
      cmd = ['net', 'use', f'{drive_letter}:', unc, '/persistent:yes']

      if username:
            cmd.extend(['/user:' + username])
            if password:
                cmd.append(password)

      # 执行挂载命令
      result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)

      if result.returncode == 0:
            # 设置驱动器标签
            if nickname:
                success, message = set_drive_label(drive_letter, nickname)
                if not success:
                  return True, f"挂载成功,但{message}"
            return True, "挂载成功"
      else:
            error_msg = result.stderr or "未知错误"

            # 常见错误代码处理
            if "67" in error_msg:
                return False, "错误67: 找不到网络名。请检查:\n1. WebDAV服务器地址是否正确\n2. 服务器是否运行\n3. 防火墙是否阻止连接"
            elif "1219" in error_msg:
                return False, "错误1219: 已有其他用户使用相同凭证连接。请先断开所有连接或重启电脑。"
            elif "1326" in error_msg:
                return False, "错误1326: 用户名或密码错误。"
            else:
                return False, error_msg
    except subprocess.TimeoutExpired:
      return False, "连接超时,请检查网络连接"
    except ValueError as ve:
      return False, str(ve)
    except Exception as e:
      return False, str(e)

class WebDAVMounterApp:
    def __init__(self, root):
      self.root = root
      self.root.title("WebDAV 挂载工具 by吾爱破解")
      self.root.geometry("500x650")

      # 系统信息
      self.windows_version = get_windows_version()

      # 配置列表
      self.configs = []
      self.load_configs()

      # 创建UI
      self.create_ui()

      # 强制启用HTTP WebDAV支持
      self.check_webdav_support()

    def load_configs(self):
      """加载配置文件"""
      config_file = 'config.json'
      try:
            with open(config_file, 'r', encoding='utf-8') as f:
                self.configs = json.load(f)
      except FileNotFoundError:
            with open(config_file, 'w', encoding='utf-8') as f:
                json.dump([], f)
      except json.JSONDecodeError:
            self.configs = []

    def save_configs(self):
      """保存配置到文件"""
      config_file = 'config.json'
      with open(config_file, 'w', encoding='utf-8') as f:
            json.dump(self.configs, f, indent=4, ensure_ascii=False)

    def create_ui(self):
      """创建用户界面"""
      # 系统信息标签
      ttk.Label(self.root, text=f"系统版本: {self.windows_version}").pack(pady=5)

      # 分隔线
      ttk.Separator(self.root, orient='horizontal').pack(fill='x', pady=10)

      # 单挂载部分
      single_frame = ttk.LabelFrame(self.root, text="单个挂载", padding=(10, 5))
      single_frame.pack(pady=10, fill='x')

      ttk.Label(single_frame, text="WebDAV服务器地址 (例如: http://server.com/path):").pack()
      self.server_entry = ttk.Entry(single_frame, width=50)
      self.server_entry.pack()
      self.server_entry.insert(0, "http://example.com/webdav")

      ttk.Label(single_frame, text="本地驱动器盘符 (例如: Z):").pack()
      self.drive_entry = ttk.Entry(single_frame, width=5)
      self.drive_entry.pack()
      self.drive_entry.insert(0, "U")

      ttk.Label(single_frame, text="驱动器昵称 (支持中文,可选):").pack()
      self.nickname_entry = ttk.Entry(single_frame, width=20)
      self.nickname_entry.pack()

      ttk.Label(single_frame, text="用户名 (可选):").pack()
      self.user_entry = ttk.Entry(single_frame, width=20)
      self.user_entry.pack()

      ttk.Label(single_frame, text="密码 (可选):").pack()
      self.pass_entry = ttk.Entry(single_frame, width=20, show="*")
      self.pass_entry.pack()

      # 保存配置按钮
      ttk.Button(single_frame, text="保存配置", command=self.save_config).pack(pady=5)

      self.mount_btn = ttk.Button(
            single_frame,
            text="挂载 WebDAV",
            command=self.on_mount
      )
      self.mount_btn.pack(pady=10)

      # 批量挂载部分
      batch_frame = ttk.LabelFrame(self.root, text="批量挂载 (从config.json加载)", padding=(10, 5))
      batch_frame.pack(pady=10, fill='both', expand=True)

      columns = ("nickname", "server", "drive", "user")
      self.config_tree = ttk.Treeview(batch_frame, columns=columns, show="headings")
      self.config_tree.heading("nickname", text="昵称")
      self.config_tree.heading("server", text="服务器地址")
      self.config_tree.heading("drive", text="盘符")
      self.config_tree.heading("user", text="用户名")
      self.config_tree.pack(fill='both', expand=True)

      # 填充配置
      for config in self.configs:
            self.config_tree.insert("", tk.END, values=(
                config.get("nickname", ""),
                config.get("server", ""),
                config.get("drive", ""),
                config.get("user", "")
            ))

      self.batch_btn = ttk.Button(
            batch_frame,
            text="批量挂载",
            command=self.batch_mount
      )
      self.batch_btn.pack(pady=10)

      # 日志区域
      ttk.Label(self.root, text="日志:").pack()
      self.log_text = tk.Text(self.root, height=10, width=60)
      self.log_text.pack(pady=5)

      # 状态标签
      self.status_label = ttk.Label(
            self.root,
            text="准备就绪",
            foreground="blue",
            wraplength=400
      )
      self.status_label.pack()

      # 自动加载第一个配置
      if self.configs:
            first_config = self.configs
            self.server_entry.delete(0, tk.END)
            self.server_entry.insert(0, first_config.get("server", ""))
            self.drive_entry.delete(0, tk.END)
            self.drive_entry.insert(0, first_config.get("drive", ""))
            self.nickname_entry.delete(0, tk.END)
            self.nickname_entry.insert(0, first_config.get("nickname", ""))
            self.user_entry.delete(0, tk.END)
            self.user_entry.insert(0, first_config.get("user", ""))
            self.pass_entry.delete(0, tk.END)
            self.pass_entry.insert(0, first_config.get("pass", ""))

    def save_config(self):
      """保存当前输入的配置到config.json"""
      server = self.server_entry.get().strip()
      drive = self.drive_entry.get().strip().upper()
      nickname = self.nickname_entry.get().strip() or ""
      username = self.user_entry.get().strip() or ""
      password = self.pass_entry.get().strip() or ""

      if not server or not drive:
            messagebox.showerror("错误", "请输入服务器地址和驱动器盘符")
            return

      if len(drive) != 1 or not drive.isalpha():
            messagebox.showerror("错误", "驱动器盘符必须是单个字母 (A-Z)")
            return

      # 检查是否已存在相同配置
      for config in self.configs:
            if config.get("server") == server and config.get("drive") == drive:
                messagebox.showinfo("信息", "此配置已存在")
                return

      # 添加新配置
      new_config = {
            "server": server,
            "drive": drive,
            "nickname": nickname,
            "user": username,
            "pass": password
      }
      self.configs.append(new_config)
      self.save_configs()

      # 更新Treeview
      self.config_tree.insert("", tk.END, values=(nickname, server, drive, username))
      self.log_text.insert(tk.END, f"配置已保存: {nickname or server} 到 {drive}:\n")
      messagebox.showinfo("成功", "配置已保存到config.json")

    def check_webdav_support(self):
      """强制启用HTTP WebDAV支持"""
      self.status_label.config(
            text="正在启用WebClient服务...",
            foreground="orange"
      )
      self.root.update()

      success, message = enable_http_webdav()
      if success:
            self.status_label.config(
                text=message,
                foreground="green"
            )
            self.log_text.insert(tk.END, message + "\n")
      else:
            self.status_label.config(
                text=message,
                foreground="red"
            )
            self.log_text.insert(tk.END, message + "\n")
            messagebox.showerror("错误", message)

    def on_mount(self):
      """单个挂载按钮点击事件"""
      server = self.server_entry.get().strip()
      drive = self.drive_entry.get().strip().upper()
      nickname = self.nickname_entry.get().strip() or None
      username = self.user_entry.get().strip() or None
      password = self.pass_entry.get().strip() or None

      if not server or not drive:
            messagebox.showerror("错误", "请输入服务器地址和驱动器盘符")
            return

      if len(drive) != 1 or not drive.isalpha():
            messagebox.showerror("错误", "驱动器盘符必须是单个字母 (A-Z)")
            return

      self.status_label.config(text="正在尝试挂载...", foreground="blue")
      self.mount_btn.config(state='disabled')
      self.root.update()

      success, message = mount_webdav(server, drive, username, password, nickname)

      if success:
            self.status_label.config(text="挂载成功", foreground="green")
            messagebox.showinfo("成功", f"WebDAV已成功挂载到 {drive}: ({nickname or '无昵称'})")
            self.log_text.insert(tk.END, f"单个挂载成功: {nickname or server} 到 {drive}:\n")
      else:
            self.status_label.config(text=f"挂载失败: {message}", foreground="red")
            messagebox.showerror("错误", f"挂载失败:\n{message}")
            self.log_text.insert(tk.END, f"单个挂载失败: {nickname or server} - {message}\n")

      self.mount_btn.config(state='normal')

    def batch_mount(self):
      """批量挂载"""
      if not self.configs:
            messagebox.showinfo("信息", "没有配置可挂载。请编辑config.json或保存新配置。")
            return

      self.status_label.config(text="正在批量挂载...", foreground="blue")
      self.batch_btn.config(state='disabled')
      self.root.update()

      for config in self.configs:
            server = config.get("server")
            drive = config.get("drive", "").upper()
            nickname = config.get("nickname") or None
            username = config.get("user") or None
            password = config.get("pass") or None

            if not server or not drive:
                self.log_text.insert(tk.END, f"配置无效 (缺少server或drive): {config}\n")
                continue

            if len(drive) != 1 or not drive.isalpha():
                self.log_text.insert(tk.END, f"无效盘符 {drive} for {nickname or server}\n")
                continue

            success, message = mount_webdav(server, drive, username, password, nickname)

            if success:
                self.log_text.insert(tk.END, f"挂载成功: {nickname or server} 到 {drive}:\n")
            else:
                self.log_text.insert(tk.END, f"挂载失败: {nickname or server} - {message}\n")

      self.status_label.config(text="批量挂载完成", foreground="green")
      self.batch_btn.config(state='normal')

if __name__ == "__main__":
    # 强制要求管理员权限
    require_admin()

    # 创建GUI
    root = tk.Tk()
    app = WebDAVMounterApp(root)

    # 设置窗口图标 (可选)
    try:
      root.iconbitmap(default='webdav.ico')
    except:
      pass

    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

寒哥Gh61ac8 发表于 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现在

huoxianghui913 发表于 2025-11-12 15:39:48

感谢分享,不错的软件

huoxianghui913 发表于 2025-11-12 15:40:00

很不错,Nice

寒哥Gh61ac8 发表于 2025-11-12 15:40:35

很不多。谢谢分享了。整好需要呢。

huoxianghui913 发表于 2025-11-12 15:41:02

感谢分享,先收藏备用!
页: [1] 2
查看完整版本: WebDAV 挂载工具1.0