【问题标题】:Install Chocolatey package if software is not installed, but skip install if newer version of software is already installed?如果未安装软件,请安装 Chocolatey 软件包,但如果已安装较新版本的软件,则跳过安装?
【发布时间】:2017-11-27 22:20:51
【问题描述】:

我正在使用以下 PowerShell 脚本通过 Octopus Deploy 步骤安装 dotnetcore-windowshosting 1.1.1 版。

ChocolateyPackageId 等于“dotnetcore-windowshosting”并且 $ChocolateyPackageVersion 等于“1.1.1”。

但是,目标计算机安装了新版本的 DotNetCore.1.0.4_1.1.1-WindowsHosting.exe,而不是 Chocolatey 包安装的版本。结果,引发了一个错误,提醒我目标机器已经安装了更新的版本。

如何像在脚本中一样使用cinst 安装包,但是,如果正在安装的包(或更新版本)已经安装,请忽略并且不会引发错误?

$chocolateyBin = [Environment]::GetEnvironmentVariable("ChocolateyInstall", "Machine") + "\bin"
if(-not (Test-Path $chocolateyBin)) {
    Write-Output "Environment variable 'ChocolateyInstall' was not found in the system variables. Attempting to find it in the user variables..."
    $chocolateyBin = [Environment]::GetEnvironmentVariable("ChocolateyInstall", "User") + "\bin"
}

$cinst = "$chocolateyBin\cinst.exe"
$choco = "$chocolateyBin\choco.exe"

if (-not (Test-Path $cinst) -or -not (Test-Path $choco)) {
    throw "Chocolatey was not found at $chocolateyBin."
}

if (-not $ChocolateyPackageId) {
    throw "Please specify the ID of an application package to install."
}

$chocoVersion = & $choco --version
Write-Output "Running Chocolatey version $chocoVersion"

$chocoArgs = @()
if([System.Version]::Parse($chocoVersion) -ge
   [System.Version]::Parse("0.9.8.33")) {
    Write-Output "Adding --confirm to arguments passed to Chocolatey"
    $chocoArgs += @("-y", "")
}

if (-not $ChocolateyPackageVersion) {
    Write-Output "Installing package $ChocolateyPackageId from the Chocolatey package repository..."
    & $cinst $ChocolateyPackageId $($chocoArgs)
}
else {
    Write-Output "Installing package $ChocolateyPackageId version $ChocolateyPackageVersion from the Chocolatey package repository..." & $cinst $ChocolateyPackageId -Version $ChocolateyPackageVersion $($chocoArgs)
}

【问题讨论】:

  • 新版本的应用程序是通过 Chocolatey 安装的,还是手动安装的?
  • 嘿...虽然我想强制应用程序始终通过 Chocolatey 安装,但在现实世界中这是不可能的。所以是的,它可以手动安装。
  • 当您说安装过程中出现错误时,您能确认一下您的意思吗?例如,如果它返回标准错误代码,则可能是 Chocolatey 包本身需要更新以将其包含为有效的退出代码。
  • 我从 powershell 得到以下输出... 失败 - dotnetcore-windowshosting(退出 1638) - 运行“C:\ ps1'。有关详细信息,请参阅日志。并且错误日志包含以下内容... [2014:2618][2017-11-28T22:58:09]i199:检测完成,结果:0x0 [2014:3CF0][2017-11-28T22:58:09] e000:错误 0x80070666:安装较新版本时无法安装产品。 [2014:2618][2017-11-28T22:58:09]i500:关机,退出代码:0x666
  • 查看完整日志会很有趣,此外,如果您运行 choco install 命令并传入 -dv,您将获得更完整的信息。理想情况下,我们会从安装尝试中获取退出代码,并将其推送回包的 validExitCodes 中。

标签: powershell octopus-deploy chocolatey


【解决方案1】:

开源

继续使用您正在处理的脚本,但请检查您正在安装的脚本的退出代码,它可能有一个有效的退出代码,表明已安装了较新的版本。

商业

可能已经存在实现您正在寻找的最佳方法。 Chocolatey for Business 具有同步命令和自动同步功能。 https://chocolatey.org/docs/features-synchronize

如果您运行choco sync 然后调用您的安装,您将已经拥有由 Chocolatey 管理的该软件包的更新版本。因此它会忽略你的脚本。

choco sync
choco upgrade <name> -y <options>

如果没有安装包,这里升级实现安装,如果你的源中有更新版本,则升级

【讨论】:

    【解决方案2】:

    感谢所有建议。下面似乎对我有用

    $chocolateyBin = [Environment]::GetEnvironmentVariable("ChocolateyInstall", "Machine") + "\bin"
    if(-not (Test-Path $chocolateyBin)) {
        Write-Output "Environment variable 'ChocolateyInstall' was not found in the system variables. Attempting to find it in the user variables..."
        $chocolateyBin = [Environment]::GetEnvironmentVariable("ChocolateyInstall", "User") + "\bin"
    }
    
    $cinst = "$chocolateyBin\cinst.exe"
    $choco = "$chocolateyBin\choco.exe"
    
    if (-not (Test-Path $cinst) -or -not (Test-Path $choco)) {
        throw "Chocolatey was not found at $chocolateyBin."
    }
    
    if (-not $ChocolateyPackageId) {
        throw "Please specify the ID of an application package to install."
    }
    
    $chocoVersion = & $choco --version
    Write-Output "Running Chocolatey version $chocoVersion"
    
    $chocoArgs = @()
    if([System.Version]::Parse($chocoVersion) -ge [System.Version]::Parse("0.9.8.33")) {
        Write-Output "Adding --confirm to arguments passed to Chocolatey"
        $chocoArgs += @("-y", "")
    }
    
    if (-not $ChocolateyPackageVersion) {
        Write-Output "Installing package $ChocolateyPackageId from the Chocolatey package repository..."
        & $cinst $ChocolateyPackageId $($chocoArgs)
    } else {
        Write-Output "Installing package $ChocolateyPackageId version $ChocolateyPackageVersion from the Chocolatey package repository..."
        & $cinst $ChocolateyPackageId -Version $ChocolateyPackageVersion $($chocoArgs) --force
    }
    
    $codes = $IgnoreExitCodes -split ','
    
    if ($codes -Contains $lastExitCode)
    {
        exit 0
    }
    

    【讨论】:

      【解决方案3】:

      免责声明:这是 hacky。而且不是很好。

      function Test-ChocolateyPackageInstalled {
          Param (
              [ValidateNotNullOrEmpty()]
              [string]
              $Package
          )
      
          Process {
              if (Test-Path -Path $env:ChocolateyInstall) {
                  $packageInstalled = Test-Path -Path $env:ChocolateyInstall\lib\$Package
              }
              else {
                  Write-Warning "Can't find a chocolatey install directory..."
              }
      
              return $packageInstalled
          }
      }
      
      $package = "dotnetcore-windowshosting"
      
      
      if (Test-ChocolateyPackageInstalled -Package $package) {
          Write-Warning "Package is already installed"
      }
      else {
          choco install $package -confirm
      }
      

      我只通过 Chocolatey 安装过这个,所以当其他人手动安装时,我将很难测试你的场景,但该方法可能有腿。

      因此还要注意,这可能无法完全解决您的问题;但它可以帮助未来的读者。

      【讨论】:

      • 我不确定这是否与 OP 所说的相同 - 我澄清了标题,您可能希望编辑您的答案。
      猜你喜欢
      • 1970-01-01
      • 2021-10-13
      • 2020-05-19
      • 2020-11-24
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      相关资源
      最近更新 更多