编辑
2025-12-22
技术漫谈
00
请注意,本文编写于 69 天前,最后修改于 27 天前,其中某些信息可能已经过时。

目录

(下载地址在文末)
1. 背景与需求
2. 核心技术实现
2.1 混合数据源架构
2.2 基于注册表的“幂等性”检测 (查重)
2.3 进程熔断机制 (Timeout)
2.4 动态说明映射
3. 脚本目录规范
4. 异常处理策略
5. 使用说明

(下载地址在文末)

1. 背景与需求

在 Windows 环境下进行批量装机或重装系统后,软件部署通常面临以下痛点:

  • Winget 的局限性:官方源虽然方便,但部分软件版本滞后,或缺少特定版本(如去广告版、绿色版)。
  • 本地安装的繁琐:传统的批处理安装(.bat)难以处理静默参数不统一、进程卡死等异常情况。
  • 重复安装问题:脚本若重复运行,可能会覆盖已配置好的软件。

基于此,编写了一个 PowerShell 脚本 (AutoInstall.ps1),采用 “Winget 在线 + Local 离线” 的混合部署策略,并加入了进程监控和注册表查重机制。

2. 核心技术实现

2.1 混合数据源架构

脚本将部署流程分为两个阶段,逻辑解耦:

  1. 在线阶段:解析 my_apps.txt 配置文件,调用系统内置 winget 部署常用软件(Chrome, VSCode 等)。支持通过标签 # [SOURCE: msstore] 动态切换下载源。
  2. 离线阶段:遍历 Local_Apps 目录,根据文件后缀(.exe/.msi/文件夹)自动匹配安装策略。

2.2 基于注册表的“幂等性”检测 (查重)

为了防止重复安装,脚本在本地部署阶段引入了预检查机制。

  • 原理:通过读取 HKLMHKCU 下的 Uninstall 注册表项,构建已安装软件名称列表。
  • 匹配:将待安装文件名与已安装列表进行模糊匹配(Regex)。
powershell
# 获取系统已安装软件列表 function Get-InstalledAppNames { $paths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" ) $names = @() foreach ($path in $paths) { Get-ItemProperty $path -ErrorAction SilentlyContinue | ForEach-Object { if ($_.DisplayName) { $names += $_.DisplayName } } } return $names }

2.3 进程熔断机制 (Timeout)

在使用 winget 或调用外部 exe 时,可能会出现网络挂起或安装程序卡死的情况。 脚本放弃了简单的 Wait-Process,改用循环轮询的方式监控进程运行时间。一旦超过阈值(默认 10 分钟),强制终止进程。

powershell
# 启动进程并获取对象 $proc = Start-Process -FilePath $exe -ArgumentList $args -PassThru -NoNewWindow $startTime = Get-Date while (-not $proc.HasExited) { Start-Sleep -Seconds 2 # 计算运行时长 if (((Get-Date)-$startTime).TotalMinutes -ge $TimeLimitMinutes) { Stop-Process -Id $proc.Id -Force -ErrorAction SilentlyContinue Write-Host " [!] 任务超时,强制熔断。" -ForegroundColor Red break } }

2.4 动态说明映射

本地文件通常只有英文文件名(如 SoftCnKiller.exe)。脚本内置了一个哈希表(HashTable)字典,在运行时动态匹配文件名并输出中文说明,提升日志可读性。

powershell
$AppDict = @{ "finalshell" = "SSH连接/服务器管理" "softcnkiller" = "流氓软件清理工具" "wiztree" = "磁盘空间分析" # ... }

3. 脚本目录规范

为了保证脚本的可移植性(Portable),采用相对路径结构:

text
Deploy_Tool_V33/ │ ├── 一键启动.bat # 引导层:负责提权和绕过执行策略 ├── AutoInstall.ps1 # 逻辑层:PowerShell 核心代码 ├── my_apps.txt # 配置层:Winget 软件清单 │ └── Local_Apps/ # 数据层:存放本地安装包 ├── setup_v1.0.exe └── PortableTool/ # 支持直接复制绿色软件目录

4. 异常处理策略

脚本针对几种常见的安装失败场景做了处理:

  1. Winget 找不到包:捕获 ExitCode,若非 0 或 3010(重启),则输出错误代码供排查。
  2. 静默安装失败:本地 EXE 默认尝试 /S/silent 参数。如果进程快速退出且未成功(依据返回码),脚本会提示用户可能需要手动介入,但不会中断整个流程。
  3. UI 对齐:针对中英文混合输出导致的控制台对齐问题,编写了 Show-Header 函数,基于字符字节宽度计算 Padding,确保日志输出整洁。

5. 使用说明

  1. 配置:修改 my_apps.txt 添加需要的 Winget ID;将离线包放入 Local_Apps
  2. 运行:直接运行 一键启动.bat
  3. 交互:脚本启动后会要求输入“部署路径”(针对绿色软件)和“超时时间”,随后自动执行。

下载地址整合包下载地址

本文作者:小转圈

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!