无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 2051|回复: 65
打印 上一主题 下一主题

[原创] 程序安装管理器

  [复制链接]
跳转到指定楼层
1#
本帖最后由 什么都不说吧 于 2025-8-15 14:11 编辑

这网上的程序安装管理器是真讨厌,配置麻烦,没办法,做个最基础功能的自己用。软件运行时会生成配置文件install_config.ini和安装程序存放文件夹data,需要把安装程序放到data文件夹里,配置文件也很简单,比如:

腾讯会议 = "腾讯会议.exe" /SilentInstall=0
qq = "qq.exe" /S
微信 = "微信.exe" /S
企业微信 = "企业微信.exe" /S

如果遇到一些软件没有自动安装参数的,那得自己想办法把软件先做成自动安装的。
软件的配色使用了论坛里另一位朋友的同类软件的配色,在此表示感谢。

程序安装管理器.part1.rar (4 MB, 下载次数: 114)     程序安装管理器.part2.rar (3.06 MB, 下载次数: 120)











评分

参与人数 1无忧币 +5 收起 理由
奈绪 + 5 很给力!

查看全部评分

2#
发表于 6 天前 | 只看该作者
感谢分享
回复

使用道具 举报

3#
发表于 6 天前 | 只看该作者
感謝大大分享!^^ 辛苦了!
回复

使用道具 举报

4#
发表于 6 天前 | 只看该作者
很是可以的啊
回复

使用道具 举报

5#
发表于 6 天前 | 只看该作者
谢谢分享
回复

使用道具 举报

6#
发表于 6 天前 | 只看该作者
感谢分享!
回复

使用道具 举报

7#
发表于 6 天前 | 只看该作者

谢谢分享
回复

使用道具 举报

8#
发表于 6 天前 | 只看该作者
挺实用 支持了
回复

使用道具 举报

9#
发表于 6 天前 | 只看该作者
感谢分享
回复

使用道具 举报

10#
发表于 6 天前 | 只看该作者
谢谢分享!
回复

使用道具 举报

11#
发表于 6 天前 | 只看该作者
感谢您的分享!
回复

使用道具 举报

12#
发表于 6 天前 | 只看该作者
谢谢分享
回复

使用道具 举报

13#
发表于 6 天前 | 只看该作者

挺实用 支持了
回复

使用道具 举报

14#
发表于 6 天前 | 只看该作者
谢谢分享
回复

使用道具 举报

15#
发表于 6 天前 | 只看该作者
能设置安装路径吗

点评

默认参数,有些程序能指定安装路径的。 不过建议软件还是安装到C盘,理由如下: 1、操作系统备份后,再还原所有的软件就有了。 2、假设操作系统中了病毒,还原操作系统后C盘就干净了。如应用软件安装到其他分区,  详情 回复 发表于 5 天前
回复

使用道具 举报

16#
发表于 6 天前 | 只看该作者
感谢楼主的分享
回复

使用道具 举报

17#
发表于 5 天前 | 只看该作者
谢谢楼主的分享!
回复

使用道具 举报

18#
 楼主| 发表于 5 天前 | 只看该作者
chtqq 发表于 2025-8-14 22:40
能设置安装路径吗

默认参数,有些程序能指定安装路径的。
不过建议软件还是安装到C盘,理由如下:
1、操作系统备份后,再还原所有的软件就有了。
2、假设操作系统中了病毒,还原操作系统后C盘就干净了。如应用软件安装到其他分区,可能一开机就会有程序自动启动,这种情况下病毒可能瞬间又感染了其他程序。

点评

大佬说的没错,备份还原更方便。  详情 回复 发表于 5 天前
回复

使用道具 举报

19#
发表于 5 天前 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

20#
发表于 5 天前 | 只看该作者
谢谢分享
回复

使用道具 举报

21#
发表于 5 天前 | 只看该作者
感谢分享
回复

使用道具 举报

22#
发表于 5 天前 | 只看该作者
本帖最后由 2010天月来了 于 2025-8-15 09:49 编辑

好东西。确实好,便利部署。
你整个界面上的所有文字都可以配置文件自定义就更好了,例如右下角的立即安装等。整个程序界面的文字都可以自定义才好。
回复

使用道具 举报

23#
发表于 5 天前 | 只看该作者
谢谢分享!!!
回复

使用道具 举报

24#
发表于 5 天前 | 只看该作者
什么都不说吧 发表于 2025-8-15 07:16
默认参数,有些程序能指定安装路径的。
不过建议软件还是安装到C盘,理由如下:
1、操作系统备份后,再 ...

大佬说的没错,备份还原更方便。
回复

使用道具 举报

25#
 楼主| 发表于 5 天前 | 只看该作者
piaomusic 发表于 2025-8-15 12:42
# -*- coding: utf-8 -*-
import os
import configparser

呵,这么快就反翻译出来了。。不过做程序最关键就是思路的问题,我不发源代码也没有其他意思,只是自用的程序,特别是不想涉及到版权的问题,这是原则问题。

点评

我没有反翻译你的啊。 只是看的你发了。修改完善了一下原来的代码、。  详情 回复 发表于 5 天前
回复

使用道具 举报

26#
 楼主| 发表于 5 天前 | 只看该作者
piaomusic 发表于 2025-8-15 12:42
# -*- coding: utf-8 -*-
import os
import configparser

这是我使用配色的原程序的代码,我不是抄袭你的哈,只是借用了你的配色。我的发贴中已对您表示了感谢。呵。。用deepseek写的程序,你是开源的是不?我第一个程序灵感就来自于您这里,在此再次表示感谢!

点评

不存在抄袭的说法。本来就是开源的。 我既然公开了源代码。任何人都可以随便修改。  详情 回复 发表于 5 天前
回复

使用道具 举报

27#
 楼主| 发表于 5 天前 | 只看该作者
piaomusic 发表于 2025-8-15 12:42
# -*- coding: utf-8 -*-
import os
import configparser

好吧,贴出源码,看下吧,真不一样。
import configparser
import subprocess
import threading
import queue
import time
import tkinter as tk
from tkinter import messagebox, Checkbutton, Button, Label, Scrollbar, Frame, ttk
import os
import sys
import ctypes
import shlex

# 获取程序所在目录
def get_app_directory():
    try:
        if getattr(sys, 'frozen', False):
            return os.path.dirname(sys.executable)
        else:
            return os.path.dirname(os.path.abspath(__file__))
    except Exception as e:
        print(f"Error getting app directory: {e}")
        return os.getcwd()  # 默认返回当前工作目录

# 创建配置文件路径
def get_config_path():
    try:
        app_dir = get_app_directory()
        return os.path.join(app_dir, "install_config.ini")
    except Exception as e:
        print(f"Error getting config path: {e}")
        return "install_config.ini"

# 获取data目录路径
def get_data_directory():
    try:
        app_dir = get_app_directory()
        return os.path.join(app_dir, "data")
    except Exception as e:
        print(f"Error getting data directory: {e}")
        return "data"

class InstallManager:
    def set_dark_theme(self, window):
        """设置改进的深色主题"""
        try:
            # 使用深色主题配色方案
            bg_color = "#2c3e50"      # 背景色
            text_color = "#ecf0f1"    # 文字颜色
            tree_bg = "#34495e"       # 表格背景
            primary_color = "#3498db" # 主色
            secondary_color = "#2ecc71" # 辅助色
            
            window.configure(bg=bg_color)
            
            # 设置默认颜色
            window.option_add("*Background", bg_color)
            window.option_add("*Foreground", text_color)
            window.option_add("*Checkbutton.Background", tree_bg)
            window.option_add("*Checkbutton.Foreground", text_color)
            window.option_add("*Label.Background", bg_color)
            window.option_add("*Label.Foreground", text_color)
            window.option_add("*Frame.Background", bg_color)
            
            # 设置滚动条颜色
            window.option_add("*Scrollbar.Background", bg_color)
            window.option_add("*Scrollbar.TroughColor", tree_bg)
            window.option_add("*Scrollbar.Slider", primary_color)
            
            # 设置进度条样式
            style = ttk.Style()
            style.theme_use('default')
            style.configure("Custom.Horizontal.TProgressbar",
                            background=primary_color,
                            troughcolor=tree_bg,
                            thickness=12,
                            lightcolor=primary_color,
                            darkcolor=bg_color,
                            bordercolor=bg_color)
        except Exception as e:
            print(f"设置深色主题时出错: {e}")

    def __init__(self, master):
        try:
            # 设置 DPI 感知以兼容高 DPI 显示器
            try:
                if hasattr(ctypes.windll, 'shcore'):
                    ctypes.windll.shcore.SetProcessDpiAwareness(1)
            except:
                pass
            
            self.master = master
            master.title("程序安装管理器")
            
            # 设置窗口大小并居中显示
            width = 600
            height = 600
            screen_width = master.winfo_screenwidth()
            screen_height = master.winfo_screenheight()
            x = (screen_width - width) // 2
            y = (screen_height - height) // 2
            master.geometry(f"{width}x{height}+{x}+{y}")
            
            # 设置深色主题
            self.set_dark_theme(master)
            
            # 安装队列和状态变量
            self.install_queue = queue.Queue()
            self.currently_installing = []
            self.max_concurrent = 1
            self.selected_count = 0
            self.installations_completed = 0
            self.total_to_install = 0
            self.current_program = ""
            self.success_count = 0  # 成功安装计数
            
            # 创建主容器框架
            self.main_frame = tk.Frame(master, bg="#2c3e50")
            self.main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
            
            # 创建带滚动条的容器
            self.container_frame = Frame(self.main_frame, bg="#34495e")
            self.container_frame.pack(fill=tk.BOTH, expand=True)
            
            # 创建滚动条
            self.scrollbar = Scrollbar(self.container_frame, orient=tk.VERTICAL)
            self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
            
            # 创建Canvas用于滚动
            self.canvas = tk.Canvas(
                self.container_frame,
                bg="#34495e",
                yscrollcommand=self.scrollbar.set,
                highlightthickness=0
            )
            self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
            
            # 配置滚动条
            self.scrollbar.config(command=self.canvas.yview)
            
            # 创建内部框架
            self.inner_frame = Frame(self.canvas, bg="#34495e")
            self.canvas_window = self.canvas.create_window(
                (0, 0),
                window=self.inner_frame,
                anchor="nw"
            )
            
            # 绑定事件
            self.inner_frame.bind("<Configure>", self._on_frame_configure)
            self.canvas.bind("<Configure>", self._on_canvas_configure)
            
            # 绑定鼠标滚轮事件
            self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
            self.inner_frame.bind("<MouseWheel>", self._on_mousewheel)
            self.scrollbar.bind("<MouseWheel>", self._on_mousewheel)
            
            # 加载配置
            self.programs = []
            self.check_vars = []
            self.check_buttons = []
            self.load_config()
            
            # 创建底部控制面板
            self.bottom_frame = tk.Frame(master, bg="#2c3e50")
            self.bottom_frame.pack(fill=tk.X, padx=20, pady=(0, 10), side=tk.BOTTOM)
            
            # 状态标签
            self.status_frame = tk.Frame(self.bottom_frame, bg="#2c3e50")
            self.status_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
            
            # 使用更兼容的字体
            try:
                # 尝试使用系统默认字体
                self.status_label = Label(
                    self.status_frame,
                    text="就绪",
                    fg="#2ecc71",  # 使用辅助色
                    bg="#2c3e50",
                    font=("TkDefaultFont", 11),
                    anchor="w"
                )
            except:
                # 回退到基本设置
                self.status_label = Label(
                    self.status_frame,
                    text="就绪",
                    fg="#2ecc71",  # 使用辅助色
                    bg="#2c3e50",
                    anchor="w"
                )
            self.status_label.pack(side=tk.LEFT, padx=(15, 0))
            
            # 已选安装标签
            try:
                self.selected_label = Label(
                    self.bottom_frame,
                    text="已选安装: 0",
                    fg="#3498db",  # 使用主色
                    bg="#2c3e50",
                    font=("TkDefaultFont", 12, "bold")
                )
            except:
                self.selected_label = Label(
                    self.bottom_frame,
                    text="已选安装: 0",
                    fg="#3498db",  # 使用主色
                    bg="#2c3e50"
                )
            self.selected_label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
            
            # 创建安装按钮
            try:
                self.install_btn = Button(
                    self.bottom_frame,
                    text="立即安装",
                    command=self.start_installation,
                    height=1,
                    width=10,
                    bg="#34495e",
                    fg="white",
                    activebackground="#1A2530",
                    activeforeground="white",
                    font=("TkDefaultFont", 12, "bold"),
                    relief=tk.GROOVE,
                    bd=2
                )
            except:
                self.install_btn = Button(
                    self.bottom_frame,
                    text="立即安装",
                    command=self.start_installation,
                    bg="#34495e",
                    fg="white"
                )
            self.install_btn.pack(side=tk.RIGHT, padx=(0, 15))
            
            # 创建进度显示区域
            self.progress_frame = tk.Frame(master, bg="#2c3e50", height=80)
            # 初始隐藏进度区域
            self.progress_frame.pack_forget()
            
            # 正在安装标签
            self.installing_label = Label(
                self.progress_frame,
                text="",
                fg="#3498db",  # 使用主色
                bg="#2c3e50",
                font=("TkDefaultFont", 10),
                anchor="w"
            )
            self.installing_label.pack(fill=tk.X, padx=20, pady=(5, 0))
            
            # 当前安装标签
            self.current_label = Label(
                self.progress_frame,
                text="",
                fg="#3498db",  # 使用主色
                bg="#2c3e50",
                font=("TkDefaultFont", 10),
                anchor="w"
            )
            self.current_label.pack(fill=tk.X, padx=20, pady=(0, 2))
            
            # 进度标签
            self.progress_text = Label(
                self.progress_frame,
                text="",
                fg="#2ecc71",  # 使用辅助色
                bg="#2c3e50",
                font=("TkDefaultFont", 10),
                anchor="w"
            )
            self.progress_text.pack(fill=tk.X, padx=20, pady=(0, 2))
            
            # 进度条
            self.progress_bar = ttk.Progressbar(
                self.progress_frame,
                orient="horizontal",
                length=500,
                mode="determinate",
                style="Custom.Horizontal.TProgressbar"
            )
            self.progress_bar.pack(fill=tk.X, padx=20, pady=(0, 5))
            
            # 启动安装监控线程
            self.monitor_thread = threading.Thread(target=self.monitor_installations, daemon=True)
            self.monitor_thread.start()
        
        except Exception as e:
            # 在初始化失败时显示错误信息
            error_msg = f"初始化失败: {str(e)}\n\n请检查配置文件是否存在且格式正确。"
            messagebox.showerror("致命错误", error_msg)
            self.master.destroy()
            sys.exit(1)
   
    def _on_frame_configure(self, event=None):
        """当内部框架大小改变时更新滚动区域"""
        self.canvas.configure(scrollregion=self.canvas.bbox("all"))
   
    def _on_canvas_configure(self, event):
        """当Canvas大小改变时调整内部框架宽度"""
        canvas_width = event.width
        self.canvas.itemconfig(self.canvas_window, width=canvas_width)
   
    def _on_mousewheel(self, event):
        """处理鼠标滚轮事件"""
        # Windows使用delta值
        if event.delta > 0:
            self.canvas.yview_scroll(-1, "units")
        elif event.delta < 0:
            self.canvas.yview_scroll(1, "units")
   
    def update_status(self, message, color="#2ecc71"):  # 使用辅助色
        """更新状态标签"""
        self.status_label.config(text=message, fg=color)
   
    def update_selected_count(self):
        """更新已选安装计数"""
        self.selected_label.config(text=f"已选安装: {self.selected_count}")
   
    def load_config(self):
        """加载配置"""
        try:
            config_file = get_config_path()
            
            # 检查配置文件是否存在
            if not os.path.exists(config_file):
                # 尝试创建默认配置文件
                try:
                    self.create_default_config(config_file)
                    # 创建后重新加载
                    self.programs = []
                    self.check_vars = []
                    self.check_buttons = []
                except Exception as e:
                    error_msg = (
                        f"找不到配置文件且无法创建新文件:\n{config_file}\n"
                        f"错误: {str(e)}\n\n"
                        "请手动创建配置文件并重新启动程序。"
                    )
                    messagebox.showerror("配置错误", error_msg)
                    return
            
            config = configparser.ConfigParser()
            
            # 尝试不同编码读取配置文件
            encodings = ['utf-8', 'gbk', 'utf-8-sig', 'latin-1']
            read_ok = False
            
            for encoding in encodings:
                try:
                    config.read(config_file, encoding=encoding)
                    if 'programs' in config:
                        read_ok = True
                        break
                except Exception as e:
                    print(f"尝试 {encoding} 编码失败: {e}")
                    continue
            
            if not read_ok:
                messagebox.showerror("错误", "无法读取配置文件,请检查文件格式和编码")
                return
               
            if 'programs' not in config:
                messagebox.showerror("配置错误", f"配置文件中缺少[programs]部分\n配置文件路径: {config_file}")
                return
            
            # 创建复选框
            row = 0
            for program_name in config['programs']:
                try:
                    full_config = config['programs'][program_name].strip()
                    
                    if not full_config:
                        continue
                        
                    parts = shlex.split(full_config)
                    if not parts:
                        continue
                        
                    path = parts[0]
                    
                    args = parts[1:] if len(parts) > 1 else []
                    
                    if not os.path.isabs(path):
                        data_dir = get_data_directory()
                        path = os.path.join(data_dir, path)
                    
                    # 检查路径是否存在 - 如果不存在则跳过
                    if not os.path.exists(path):
                        print(f"警告: 找不到 {program_name} 的安装路径: {path}")
                        continue
                    
                    var = tk.BooleanVar()
                    
                    # 创建复选框
                    try:
                        cb = Checkbutton(
                            self.inner_frame,
                            text=program_name,
                            variable=var,
                            anchor="w",
                            padx=15,
                            pady=8,
                            bg="#34495e",
                            fg="white",
                            activebackground="#2c3e50",
                            activeforeground="white",
                            selectcolor="#3498db",  # 使用主色
                            font=("TkDefaultFont", 11),
                            command=lambda v=var: self.on_checkbox_change(v)
                        )
                    except:
                        # 字体回退
                        cb = Checkbutton(
                            self.inner_frame,
                            text=program_name,
                            variable=var,
                            anchor="w",
                            padx=15,
                            pady=8,
                            bg="#34495e",
                            fg="white",
                            command=lambda v=var: self.on_checkbox_change(v)
                        )
                    
                    cb.grid(row=row, column=0, sticky="ew", padx=10)
                    
                    self.programs.append({
                        'name': program_name,
                        'path': path,
                        'args': args
                    })
                    self.check_vars.append(var)
                    self.check_buttons.append(cb)
                    row += 1
                    
                except Exception as e:
                    print(f"加载程序 {program_name} 时出错: {e}")
                    continue
               
            # 如果没有加载到任何程序
            if not self.programs:
                try:
                    label = tk.Label(
                        self.inner_frame,
                        text="未找到可安装的程序,请检查配置文件",
                        bg="#34495e",
                        fg="white",
                        font=("TkDefaultFont", 12)
                    )
                    label.grid(row=0, column=0, sticky="w", padx=20, pady=20)
                except:
                    # 简单回退
                    label = tk.Label(
                        self.inner_frame,
                        text="未找到可安装的程序,请检查配置文件",
                        bg="#34495e",
                        fg="white"
                    )
                    label.grid(row=0, column=0, sticky="w", padx=20, pady=20)
               
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            error_msg = (
                f"加载配置时出错: {str(e)}\n"
                f"错误位置: 第 {exc_tb.tb_lineno} 行\n\n"
                "请检查配置文件格式是否正确。"
            )
            messagebox.showerror("配置错误", error_msg)

    def on_checkbox_change(self, var):
        """复选框状态改变时调用"""
        # 更新已选择的数量
        self.selected_count = sum(1 for v in self.check_vars if v.get())
        self.update_selected_count()
   
    def create_default_config(self, config_path):
        """创建默认配置文件"""
        default_config = """[programs]
# 格式:程序名称 = "安装程序路径" [静默安装参数]
# 示例:
# Google Chrome = "ChromeInstaller.exe" /silent
# Visual Studio Code = "VSCodeSetup.exe" /verysilent /suppressmsgboxes
# WinRAR = "wrar.exe" /S

"""
        with open(config_path, 'w', encoding='utf-8') as f:
            f.write(default_config)
            
        # 创建data目录(如果不存在)
        data_dir = get_data_directory()
        if not os.path.exists(data_dir):
            os.makedirs(data_dir)
   
    def start_installation(self):
        """开始安装选中的程序"""
        self.selected_indices = []  # 存储选中程序的索引
        for i, var in enumerate(self.check_vars):
            if var.get():
                self.selected_indices.append(i)  # 记录选中程序的索引
        
        # 使用索引获取选中的程序
        selected = [self.programs for i in self.selected_indices]
        
        if not selected:
            messagebox.showinfo("提示", "请选择至少一个程序进行安装")
            return
        
        # 隐藏"已选安装"标签
        self.selected_label.place_forget()
        
        # 禁用所有复选框
        for cb in self.check_buttons:
            cb.config(state=tk.DISABLED)
        
        # 隐藏安装按钮
        self.install_btn.pack_forget()
        
        # 清空队列并添加新任务
        while not self.install_queue.empty():
            self.install_queue.get()
        
        for program in selected:
            self.install_queue.put(program)
        
        # 重置安装计数器
        self.installations_completed = 0
        self.total_to_install = len(selected)
        self.success_count = 0  # 重置成功计数
        
        # 显示进度区域 - 放在窗口底部
        self.progress_frame.pack(fill=tk.X, padx=20, pady=(0, 0), side=tk.BOTTOM, anchor='s')
        self.update_progress(0, "准备开始安装...")
        
        # 更新正在安装标签
        self.installing_label.config(text=f"正在安装 {self.total_to_install} 个程序")
        
        # 清空状态标签(什么也不显示)
        self.status_label.config(text="")
   
    def update_progress(self, percent, message):
        """更新进度显示"""
        self.progress_bar["value"] = percent
        self.progress_text.config(text=message)
   
    def start_installation_process(self, program):
        """启动单个安装进程"""
        try:
            # 设置当前安装程序
            self.current_program = program['name']
            
            # 根据是否有静默参数显示不同的安装类型
            install_type = "静默安装" if program['args'] else "安装"
            
            # 更新当前安装标签
            self.current_label.config(text=f"当前{install_type}: {program['name']}")
            
            # 更新进度显示
            progress_percent = int((self.installations_completed / self.total_to_install) * 100)
            self.update_progress(progress_percent, f"正在{install_type} {program['name']}...")
            
            # 构建命令
            command = f'"{program["path"]}"'
            
            # 添加静默安装参数(如果有)
            if program['args']:
                command += " " + " ".join(program['args'])
            
            # 执行安装命令
            startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = 0  # 隐藏窗口
            
            process = subprocess.Popen(
                command,
                shell=True,
                startupinfo=startupinfo,
                creationflags=subprocess.CREATE_NO_WINDOW
            )
            
            # 添加到当前安装列表
            self.currently_installing.append(process)
            
            # 启动线程等待安装完成
            threading.Thread(target=self.wait_for_installation, args=(program, process), daemon=True).start()
            
        except Exception as e:
            self.installations_completed += 1
            # 更新进度显示为错误信息
            self.update_progress(100, f"安装失败: {program['name']}")
   
    def monitor_installations(self):
        """监控安装队列并启动安装任务"""
        while True:
            # 检查活跃安装数量
            self.currently_installing = [p for p in self.currently_installing if p.poll() is None]
            
            # 如果有空闲槽位且队列中有任务
            if len(self.currently_installing) < self.max_concurrent and not self.install_queue.empty():
                program = self.install_queue.get()
                self.start_installation_process(program)
            
            # 检查是否所有安装都已完成
            if self.install_queue.empty() and not self.currently_installing and self.total_to_install > 0:
                if self.installations_completed >= self.total_to_install:
                    self.master.after(100, self.finalize_installation)
            
            # 更新进度条
            if self.total_to_install > 0:
                progress_percent = int((self.installations_completed / self.total_to_install) * 100)
                self.master.after(100, lambda: self.update_progress(progress_percent,
                    f"已完成 {self.installations_completed}/{self.total_to_install} 个程序"))
            
            time.sleep(0.5)  # 更频繁地检查(500毫秒)
   
    def wait_for_installation(self, program, process):
        """等待安装完成并处理结果"""
        try:
            # 等待进程结束
            return_code = process.wait()
            
            # 更新安装计数
            self.installations_completed += 1
            
            # 从活跃列表中移除
            if process in self.currently_installing:
                self.currently_installing.remove(process)
            
            # 记录成功安装
            if return_code == 0:
                self.success_count += 1
            
        except Exception as e:
            self.installations_completed += 1
            if process in self.currently_installing:
                self.currently_installing.remove(process)
   
    def finalize_installation(self):
        """所有安装完成后调用"""
        # 更新进度显示
        success_message = f"成功安装 {self.success_count} 个软件"
        self.update_progress(100, success_message)
        
        # 2秒后重置界面
        self.master.after(2000, self.reset_interface)
   
    def reset_interface(self):
        """重置界面状态"""
        # 取消选中所有已安装程序的复选框
        for index in self.selected_indices:
            self.check_vars[index].set(False)
        
        # 更新已选安装计数
        self.selected_count = 0
        self.update_selected_count()
        
        # 重新显示"已选安装"标签
        self.selected_label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)
        
        # 启用所有复选框
        for cb in self.check_buttons:
            cb.config(state=tk.NORMAL)
        
        # 重新显示安装按钮
        self.install_btn.pack(side=tk.RIGHT, padx=(0, 15))
        
        # 重置进度显示
        self.progress_frame.pack_forget()
        self.progress_bar["value"] = 0
        self.progress_text.config(text="")
        self.current_label.config(text="")
        self.installing_label.config(text="")  # 清空正在安装标签
        self.current_program = ""
        
        # 重置计数器
        self.total_to_install = 0
        self.installations_completed = 0
        self.success_count = 0
        
        # 恢复状态标签为"就绪"
        self.update_status("就绪", "#2ecc71")  # 使用辅助色

if __name__ == "__main__":
    try:
        root = tk.Tk()
        app = InstallManager(root)
        root.mainloop()
    except Exception as e:
        # 捕获并显示未处理的异常
        error_msg = f"程序崩溃: {str(e)}\n\n请检查配置文件是否存在且格式正确。"
        messagebox.showerror("致命错误", error_msg)
        sys.exit(1)
回复

使用道具 举报

28#
发表于 5 天前 来自手机 | 只看该作者
感谢楼主分享
回复

使用道具 举报

29#
发表于 5 天前 | 只看该作者
什么都不说吧 发表于 2025-8-15 13:48
呵,这么快就反翻译出来了。。不过做程序最关键就是思路的问题,我不发源代码也没有其他意思,只是自用的 ...

我没有反翻译你的啊。 只是看的你发了。修改完善了一下原来的代码、。

点评

好的,为了论坛和广大的网友,大家都多多奉献。  详情 回复 发表于 5 天前
回复

使用道具 举报

30#
 楼主| 发表于 5 天前 | 只看该作者
piaomusic 发表于 2025-8-15 12:42
[软件列表]
# 格式:软件名称 = 安装程序 参数 | 默认选中(1/0)
# 示例:

我试了好些颜色,都觉得没有你这种 颜色舒服。要么太亮,要么太暗。最终还是用了你的代码里的颜色。
回复

使用道具 举报

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

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2025-8-20 20:36

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

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