首页 > 其他分享 >使用Chocolatey打包MSI软件包的完整解决方案及技术总结

使用Chocolatey打包MSI软件包的完整解决方案及技术总结

时间:2024-12-05 22:30:05浏览次数:8  
标签:Chocolatey Get 软件包 arguments MSI 卸载 旧版本

使用Chocolatey打包MSI软件包的完整解决方案及技术总结

在Windows系统上使用Chocolatey管理软件包是一种高效且自动化的方式,尤其是针对MSI格式的软件包。然而,在实际操作中,我们可能会遇到各种问题,例如检测旧版本、卸载旧版本以及处理多个匹配记录等。本文将详细记录从问题发现到最终解决的全过程,并分享最终的Chocolatey打包脚本,希望能为软件仓库维护人员解决类似问题提供启发。


问题背景

我们希望通过Chocolatey将一个MSI软件包打包成可安装的Chocolatey包,并实现以下功能:

  1. 检测是否存在旧版本。
  2. 如果存在旧版本,先卸载旧版本。
  3. 安装新版本的MSI软件包。
  4. 确保整个过程自动化且无用户干预。

问题与解决过程

1. 检测旧版本耗时过长

问题
起初,我们尝试使用以下命令检测是否存在已安装的软件:

Get-WmiObject -Class Win32_Product | Where-Object { $_.Name -like "*Your Software Name*" }

然而,这个命令会触发所有已安装MSI软件的一致性检查,导致系统卡顿甚至长时间无响应。

解决方案
改用注册表查询的方式,通过以下路径快速检索已安装的软件信息:

  • 64位应用程序路径:HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
  • 32位应用程序路径:HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall

优化后的查询命令如下:

Get-ChildItem -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | 
Get-ItemProperty | 
Where-Object { $_.DisplayName -like "*Your Software Name*" }

2. 检测到多个匹配记录

问题
在注册表中查询时,可能会返回多个匹配记录(例如同一软件的不同版本或不同语言包)。这可能导致脚本只处理第一个匹配项,而忽略其他记录。

解决方案
通过遍历所有匹配记录,逐一处理每个已安装的软件。具体实现如下:

$installedSoftwareList = Get-ChildItem -Path $path | 
                         Get-ItemProperty | 
                         Where-Object { $_.DisplayName -like "*Your Software Name*" }

foreach ($installedSoftware in $installedSoftwareList) {
    # 针对每个匹配的软件进行处理
}

3. 卸载旧版本失败

问题
在尝试卸载旧版本时,我们直接使用 UninstallString 作为 Start-Process-FilePath 参数,但由于 UninstallString 包含了路径和参数,导致报错 InvalidOperationException

例如:

MsiExec.exe /X{GUID}

解决方案
UninstallString 拆分为可执行文件路径和参数,然后分别传递给 Start-Process-FilePath-ArgumentList 参数。具体实现如下:

if ($uninstallString -match '^(.*\.exe)(.*)$') {
    $exePath = $matches[1]
    $arguments = $matches[2].Trim()
    $arguments = $arguments -replace '/I', '/X'  # 替换为卸载参数
    $arguments += ' /qn'  # 添加静默卸载参数

    Start-Process -FilePath $exePath -ArgumentList $arguments -Wait -NoNewWindow
}

最终完整的Chocolatey打包脚本

以下是经过优化后的完整脚本,能够检测并卸载旧版本,然后静默安装新版本的MSI软件包:

$ErrorActionPreference = 'Stop'

# 定义软件名称和新版本号
$softwareName = 'Your Software Name'  # 替换为实际的软件名称
$newVersion = '1.2.3'  # 替换为新版本号

# 定义注册表路径
$registryPaths = @(
    "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
    "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)

# 检查是否存在旧版本并卸载
foreach ($path in $registryPaths) {
    $installedSoftwareList = Get-ChildItem -Path $path | 
                             Get-ItemProperty | 
                             Where-Object { $_.DisplayName -like "*$softwareName*" }

    foreach ($installedSoftware in $installedSoftwareList) {
        $oldVersion = $installedSoftware.DisplayVersion
        Write-Host "Found installed version: $oldVersion"

        if ([version]$oldVersion -lt [version]$newVersion) {
            $uninstallString = $installedSoftware.UninstallString
            if ($uninstallString -match '^(.*\.exe)(.*)$') {
                $exePath = $matches[1]
                $arguments = $matches[2].Trim()
                $arguments = $arguments -replace '/I', '/X'  # 替换为卸载参数
                $arguments += ' /qn'  # 添加静默卸载参数

                Write-Host "Uninstalling version $oldVersion..."
                try {
                    Start-Process -FilePath $exePath -ArgumentList $arguments -Wait -NoNewWindow
                }
                catch {
                    Write-Host "Error uninstalling version $oldVersion: $_"
                    continue  # 继续处理下一个版本
                }
            }
        }
        else {
            Write-Host "Version $oldVersion is up to date. No action needed."
        }
    }
}

# 安装新版本的MSI
$packageArgs = @{
    packageName    = $env:ChocolateyPackageName
    fileType       = 'MSI'
    url            = 'https://example.com/your-software.msi'  # 替换为实际的下载URL
    softwareName   = $softwareName
    checksum       = '1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF'  # 替换为实际的checksum值
    checksumType   = 'sha256'
    silentArgs     = "/qn /norestart ALLUSERS=1"  # 添加ALLUSERS=1以确保所有用户都能访问
    validExitCodes = @(0, 3010, 1641)
}

Install-ChocolateyPackage @packageArgs

总结与思考

  1. 问题分解与逐步解决
    在面对复杂的问题时,将其分解为小问题逐一解决。例如,本案例中我们分别处理了检测、卸载和安装三个步骤。

  2. 选择合适的方法
    遇到性能瓶颈时(如使用 Get-WmiObject),及时切换到更高效的方法(如注册表查询)。

  3. 处理异常情况
    考虑到可能出现多个匹配项或卸载失败等情况,通过循环和异常捕获机制提高脚本的健壮性。

  4. 自动化与可维护性
    脚本设计时注重自动化和通用性,使其能够适应不同的软件和场景需求。

通过这个案例,我们不仅完成了具体任务,还锻炼了分析和解决问题的能力。希望这篇文章能为您在技术实践中提供启发!

标签:Chocolatey,Get,软件包,arguments,MSI,卸载,旧版本
From: https://blog.csdn.net/zhlh_xt/article/details/144277163

相关文章

  • msiscan:一款针对msi文件的漏洞检测与识别工具
    关于msiscanmsiscan是一款针对MicrosoftWindows*.msi安装程序文件的漏洞检测与识别工具,该工具基于Python开发,可以用于获取安装程序的概述并识别潜在的安全问题。需要注意的是,当前版本的msiscan正处于积极开发中,可能会存在假阳性和假阴性问题。工具要求Pythontermcolorm......
  • Ubuntu虚拟机&conda虚拟环境运行和打包引入SimNIBS软件包的python项目文件
    项目背景:项目是python代码写的,其中有一个模块SimNIBS不能通过pip安装,需要自己下载软件包,在Ubuntu虚拟机的虚拟环境中运行和打包。下面是整个流程和遇到的一些问题,写下来做个记录。(默认此时SimNIBS已经安装好了,还没安装好的话,参见文章Ubuntu虚拟机安装医学影像软件包SimNIBS及报......
  • ComfyUI-Flux-PuLID-定制写真生成工作流整合包,含提示词反推,相关软件包及工作流均已打
    本期本期带来基于PuLID-for-FLUX的ComfyUI定制写真工作流,通过一张面部参考图像生成真实感十足的高保真写真图像,基于Flux底层模型,更为写实。**其中包含“输入提示词生成图像”和“参考图像反推提示词生成图像”两套工作流,**工作流操作较简单,相关ComfyUI软件包、模型、节点、......
  • Android反编译APK与解析软件包img
    1,Jadx反编译APK下载JadxJADX相当于是apktool+dex2jar+jd-gui的结合体,既能反编译代码也能反编译资源支持的文件有:(apk,dex,jar,class,smali,zip,xapk,aar,arsc,jadx,aab)等。打开之后界面如下,点击打开文件,再选择对应所需要反编译的apk(或者直接拖入apk)等......
  • 43 C 程序动态内存分配:内存区域划分、void 指针、内存分配相关函数(malloc、calloc、re
    目录1 C程序内存区域划分1.1代码区(CodeSection)1.2全局/静态区(Global/StaticSection)1.3栈区(StackSection)1.4 堆区(HeapSection)1.5动态内存分配2void指针(无类型指针)2.1void指针介绍2.2void指针的作用2.3void指针的特点2.4 void指针类......
  • 源码包和 RPM 包是两种常见的 Linux 软件包形式,它们各有特点和适用场景。下面是这两种
    概念源码包:定义:源码包包含了软件的源代码,用户需要自己下载源码包,然后进行编译和安装。优点:用户可以根据自己的需求定制编译选项,选择安装哪些功能模块,还可以查看和修改源代码。缺点:安装过程较为复杂,需要一定的技术知识,而且安装速度相对较慢。RPM包:定义:RPM(RedHatPackageManager)是......
  • 统信uos安装软件包提示“failed the verification”无法安装软件
    问题描述:uos-专业版-1070,需要安装第三方云桌面软件,如open-ssh等,将软件上传至桌面,使用以下命令安装open-ssh,提示需要root用户才安装,当sudosu切换root用户时,提示“需要进入开发者模式”,另外进入开发者模式后,安装离线deb包,提示“failedtheverificationpleasegotoSecurity......
  • ae软件_ae软件下载_完整版下载-AE模板 - AE2020软件包下载
    ae软件_ae软件下载_完整版下载-AE模板 - AE2020软件包下载...AE软件:从下载到精通的完全指南AdobeAfterEffects(简称AE)是一款功能强大的动态图形和视觉效果软件,广泛应用于电影、电视、广告等领域。无论你是初学者还是专业人士,掌握AE都能为你的创意作品增添无限可能。本文将为你详......
  • AE软件安装包下载 AE软件包所有版本_(视频特效软件)
    AE软件安装包下载 AE软件包所有版本_(视频特效软件)AE软件安装包下载AE软件包所有版本_(视频特效软件)引言AdobeAfterEffects(简称AE)是一款由AdobeSystems开发的专业视频特效和动态图形设计软件。自1993年首次发布以来,AE已经成为影视制作、广告、动画和多媒体设计领域的重要工......
  • MSI Afterburner 使用
    MSIAfterburner是一款显卡超频软件。与其捆绑安装的RivaTunerStatisticsServer(RTSS)可以用来监测硬件运行情况(CPU温度、GPU温度、帧率、帧响应时间等)。首先安装MSIAfterburner。在ChooseComponents处记得选中RivaTunerStatisticsServer。打开MSIAfterbu......