编辑
2025-12-22
技术漫谈
00

目录

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

image.png

(下载地址在文末)

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 许可协议。转载请注明出处!