Windows Server 2025 上的 WinGet:PowerShell 自动化和设置指南

Avilas

Windows Server 2025 的到来标志着服务器管理的关键转变,最终带来了WinGet作为本机的第一方包管理器纳入其中。对于厌倦了手动安装和不一致的服务器构建的管理员来说,这就是我们一直在等待的时刻。本指南是您超越基本命令以掌握完整的端到端工作流程的权威资源。我们将深入探讨从初始验证和组策略锁定到构建强大的离线存储库以及为全自动软件生命周期管理创建智能、幂等 PowerShell 脚本的所有内容。

Windows Server 2025 上的 WinGet 权威指南 | GigXP.com

GigXP.com

指南
自动化
开发运营
服务器操作

Server 2025 深入探讨

从初始设置和离线部署到高级自动化和日志记录,这是您掌握服务器包管理的端到端指南。

1. 掌握WinGet环境

Windows Server 2025 附带 WinGet,但掌握它意味着了解其接口并将其锁定供企业使用。我们将介绍验证、CLI 和 PowerShell 模块之间的关键选择,以及使用组策略进行集中控制。

初始验证和配置

与以前的版本不同,Windows Server 2025 包含开箱即用的 WinGet。然而,第一步始终是验证。使用这些命令来确认 WinGet 是否正常工作并获取其配置的快照,这对于故障排除非常有用。


# Check the installed version of the WinGet client
winget --version

# Display detailed information, including log locations and configured sources
winget --info
                    

在某些自动化部署场景中,“winget”命令可能无法立即可用。如果是这样,您可以在提升的 PowerShell 提示符中使用以下命令手动触发其注册:


# Manually register the App Installer package family to make winget.exe available
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
                    

CLI 与 PowerShell 模块:战略选择

为工作选择正确的工具至关重要。 “winget.exe” CLI 非常适合快速交互式任务,但对于任何严肃的自动化,“Microsoft.WinGet.Client” PowerShell 模块是唯一可靠的选择。

特征 winget.exe (CLI)。 Microsoft.WinGet.Client(PowerShell) 推荐
输出类型 纯文本(字符串) PowerShell 对象 对象为脚本编写提供结构化、可靠的数据。
脚本可靠性 强壮的 显示格式更改时对象属性不会中断。
错误处理 退出代码、错误字符串 异常对象、状态属性 允许精确的、程序化的错误处理。
使用案例 交互式管理任务 自动化系统、CI/CD 使用适合工作的正确工具。

通过组策略进行集中控制

对于企业环境,集中管理是不容协商的。 WinGet 的组策略模板允许您在整个服务器群中实施安全性和配置,将其转​​变为可管理的安全平台。

  • 启用应用程序安装程序允许的来源

    最关键的安全策略。使用它来创建批准的内部存储库的白名单,有效地阻止对所有公共资源的访问并防止未经审查的软件安装。

  • 禁用默认和 Microsoft Store 源

    在服务器环境中,通常不希望访问公共存储库。显式禁用默认的“winget”社区存储库和“msstore”源以加强安全性。

  • 设置源自动更新间隔

    控制客户端刷新其包元数据缓存的频率。在大型环境中,将此间隔从默认的 5 分钟增加可以显着减少内部存储库的网络流量。

2. 构建离线和气隙部署

许多服务器环境都限制互联网访问。 WinGet 为这些场景提供了强大的工作流程,从简单的安装程序缓存到功能齐全的私有 REST 存储库。对于任何离线环境来说,它们之间的选择都是一个关键的架构决策。

离线部署模型

第 1 级:本地包缓存

在临时计算机上使用“winget download”来创建安装程序的文件共享。设置简单,但离线客户端的功能有限。

级别 2:私有 REST 源

托管您自己的存储库。这提供了完整的“搜索”、“安装”和“升级”功能,以实现真正托管的离线体验。

编写离线安装脚本

如何在离线服务器上安装软件取决于您选择的型号。私有 REST 源允许优雅的本机 WinGet 命令,而文件缓存则需要更多手动脚本。

来自私有 REST 源(推荐)
来自文件缓存

从 REST-Source 安装.ps1


# First, ensure the private source is added (typically done once via GPO or script)
# winget source add --name "InternalRepo" -a "https://internal-repo.corp.local/api"

# List of application IDs to install from the internal repository
$packagesToInstall = @("7zip.7zip", "Internal.App.LegacyWrapper")

foreach ($packageId in $packagesToInstall) {
    Write-Host "Installing package: $packageId from InternalRepo..."
    # Use standard winget install, but specify the internal source
    Install-WinGetPackage -Id $packageId -Source "InternalRepo" -AcceptPackageAgreements -Scope Machine
}
                            

从文件缓存安装.ps1


$cachePath = "FileServer01WinGetCache"
$appsToInstall = @{ "Notepad++.Notepad++" = "Notepad++.Notepad++.8.6.5.exe" }

foreach ($app in $appsToInstall.GetEnumerator()) {
    $installerFile = Join-Path -Path $cachePath -ChildPath $app.Value
    if (Test-Path $installerFile) {
        # Silent switches vary by installer and must be known in advance
        $arguments = "/S" 
        Start-Process -FilePath $installerFile -ArgumentList $arguments -Wait
    }
}
                            

3.软件生命周期自动化

这就是 WinGet 的闪光点。我们将探索用于基线服务器构建的幂等脚本,创建强大且智能的更新解决方案,并安排这一切以进行无人值守维护。

智能更新工作流程

1. 查找包

`获取WinGetPackage`

2.检查更新

`Where-Object { $_.IsUpdateAvailable }`

3. 过滤排除项

`Where-Object { $_.Id -notin $exclusionList }`

4. 应用更新

`更新-WinGetPackage`

交互式 PowerShell 脚本

过滤下面的脚本以找到适合您任务的自动化。单击按钮可查看相关代码片段。

所有脚本
基线构建
自动更新
计划任务

建议阅读:PowerShell 代码签名 2025:时间戳、CA 和 Set-AuthenticodeSignature 指南

安装基线.ps1


# Import the PowerShell module for robust automation
Import-Module Microsoft.WinGet.Client -ErrorAction SilentlyContinue

# Path to the CSV file defining the software baseline
$baselineFile = "C:ScriptsServerBaseline.csv"

if (-not (Test-Path $baselineFile)) {
    Write-Error "Baseline definition file not found at $baselineFile"
    return
}

# Import the list of applications from the CSV
$appsToInstall = Import-Csv -Path $baselineFile

# Loop through each application defined in the baseline
foreach ($app in $appsToInstall) {
    # Idempotency Check: Verify if the package is already installed
    $installedPackage = Get-WinGetPackage -Id $app.PackageId -ErrorAction SilentlyContinue
    if ($installedPackage) {
        Write-Host "$($app.PackageId) is already installed. Skipping." -ForegroundColor Yellow
        continue
    }

    # Install the package
    Install-WinGetPackage -Id $app.PackageId -Source $app.Source -Scope Machine -AcceptPackageAgreements
}
                            

执行-WinGet-Updates.ps1


# Import the PowerShell module
Import-Module Microsoft.WinGet.Client -ErrorAction SilentlyContinue

# Define a list of package IDs to exclude from automatic updates
$exclusionList = @(
    "Oracle.MySQL",
    "Microsoft.DotNet.SDK.6"
)

# Find all installed packages that have an update available and are not in the exclusion list
$updatablePackages = Get-WinGetPackage | Where-Object { 
    $_.IsUpdateAvailable -and $_.Id -notin $exclusionList 
}

if ($updatablePackages) {
    # Loop through the filtered list and apply updates
    foreach ($package in $updatablePackages) {
        $package | Update-WinGetPackage -AcceptPackageAgreements -Scope Machine
    }
}
                            

创建更新任务.ps1


# --- Task Configuration ---
$taskName = "Weekly WinGet Application Update"
$scriptPath = "C:ScriptsPerform-WinGet-Updates.ps1"
$principal = "NT AUTHORITYSYSTEM"

# --- Create the Task Action ---
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File `"$scriptPath`""

# --- Create the Task Trigger ---
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Sunday -At 3am

# --- Create the Task Principal ---
$taskPrincipal = New-ScheduledTaskPrincipal -UserId $principal -LogonType ServiceAccount -RunLevel Highest

# --- Register the Scheduled Task ---
Register-ScheduledTask -TaskName $taskName `
    -Action $action `
    -Trigger $trigger `
    -Principal $taskPrincipal
                            

4. 未来:使用“winget configure”进行声明式设置

超越命令式脚本,转向声明式模型。在 YAML 文件中定义服务器的*所需状态*,然后让 WinGet 和 PowerShell DSC 处理其余的事情。这就是基础设施即代码(IaC)的本质。

声明式配置流程

1. 在 YAML 中定义状态

`configuration.dsc.yaml`

2.运行`winget配置`

单命令执行

3. 系统合规

幂等且可重复

示例:`configuration.dsc.yaml`

此 YAML 文件定义 Web 服务器所需的状态。它断言操作系统版本,确保安装特定的 WinGet 软件包,并使用 PowerShell DSC 启用 IIS Windows 功能。应用它就像运行“winget configure -f C:PathToFile.yaml”一样简单。


# yaml-language-server: $schema=https://aka.ms/configuration-dsc-schema/0.2
properties:
  resources:
    - resource: Microsoft.WinGet.DSC/WinGetPackage
      directives:
        description: Install Microsoft PowerShell 7.
      settings:
        id: Microsoft.PowerShell
        source: winget
    - resource: Microsoft.WinGet.DSC/WinGetPackage
      directives:
        description: Install Visual Studio Code.
      settings:
        id: Microsoft.VisualStudioCode
        source: winget
    - resource: PSDscResources/WindowsFeature
      directives:
        description: Ensure the IIS Web Server role is installed.
      settings:
        Name: Web-Server
        Ensure: Present
configurationVersion: 0.2.0
                    

5. 高级日志记录和故障排除

在企业环境中,强大的日志记录和有效的故障排除对于安全性、合规性和操作稳定性至关重要。 WinGet 提供了一个全面的日志记录框架,可以实现从被动解决问题到主动、自动修复的转变。

解码诊断日志

WinGet 为每个操作创建一个详细的日志文件,这是诊断故障的主要事实来源。您可以通过附加“-logs”开关在任何命令之后快速打开日志目录。


# Run an installation and immediately open the log directory to view the results.
winget install Microsoft.VisualStudioCode --logs --accept-package-agreements

# For deeper issues, enable verbose logging to see every detail.
winget install Microsoft.PowerShell --verbose-logs --accept-package-agreements
                    

编程错误处理

自动化的真正力量在于处理运行时的错误。 PowerShell 模块返回带有状态和错误代码的对象,使您的脚本能够对特定的故障条件做出智能反应,这是简单文本解析无法实现的功能。


$installResult = Install-WinGetPackage -Id "Some.App" -ErrorAction SilentlyContinue

if ($installResult.Status -ne 'Ok') {
    $errorCode = $installResult.InstallerErrorCode
    Write-Warning "Install failed with code: $errorCode"
    
    # React to specific, known error codes
    switch ($errorCode) {
        # Reboot required
        3010 { Write-Host "Flagging system for a required reboot." }
        # Another install is running
        1618 { 
            Write-Host "Another installation is in progress. Retrying in 5 minutes."
            Start-Sleep -Seconds 300
            # Add retry logic here
        }
        default { Write-Error "Unhandled error. Alerting administrators." }
    }
}
                    

集中日志收集

手动检查各个服务器上的日志无法扩展。每台服务器上的计划任务可以运行脚本来收集最近的 WinGet 日志并将其复制到中央文件共享,以简化审核和整个队列的分析。


# Script to be run as a scheduled task on each server
$centralLogShare = "LogServer01WinGetLogs"
$serverName = $env:COMPUTERNAME
$destinationPath = Join-Path -Path $centralLogShare -ChildPath $serverName

# Find the WinGet log directory dynamically
$logDirectory = (winget --info | Select-String -Pattern "Logs").ToString().Split(' : ')[1].Trim()

# Find logs from the last 24 hours and copy them to the central share
Get-ChildItem -Path $logDirectory -Filter "*.log" | 
    Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-1) } |
    Copy-Item -Destination $destinationPath -Force
                    

6. 结论:整体管理策略

WinGet 与 Windows Server 2025 的集成是一项变革性的发展。掌握它需要一种基于自动化、安全性和运营弹性最佳实践的战略方法。成功的实施取决于标准化 PowerShell 自动化模块、利用组策略实现安全、实施分层离线策略以及构建智能、幂等脚本。

最终,这个基于 WinGet 的自动化框架并不是一个孤立的解决方案。它是一个强大的引擎,可以集成到更广泛的服务器管理策略中,无论是通过 Azure Arc、Microsoft 配置管理器 (SCCM) 还是第三方 RMM 工具。通过采用这些工具,管理员可以显着减少手动工作,改善安全状况,并构建更具弹性、一致性并为未来挑战做好准备的服务器基础架构。

© 2025 GigXP.com。版权所有。

GigXP.com