14 min read
Der Schlüssel zu produktiver Softwareverwaltung: winget & PowerShell
Steigere die IT-Effizienz mit Winget und PowerShell! Lies, wie du Installationen, Updates und die Verwaltung von...
ScriptRunner Blog
Steigere die IT-Effizienz mit Winget und PowerShell! Lies, wie du Installationen, Updates und die Verwaltung von Anwendungen nahtlos automatisieren kannst.
In den letzten Jahren hat Microsoft Ressourcen in seinen Paketmanager winget.exe investiert. Winget ist ein Befehlszeilen-Paketmanager, mit dem du deine Lieblingsanwendungen mit einem einzigen Befehl installieren kannst. Ohne in eine unattraktive Hintergrundgeschichte einzusteigen, kannst du Winget jetzt mit PowerShell verwalten. In diesem Beitrag zeige ich, wie das Microsoft.Winget.Client Modul verwendet wird, um Winget mit PowerShell auf dem Desktop zu verwalten.
Natürlich muss Winget auf dem Rechner installiert sein. Die Anwendung ist ein Microsoft Open-Source-Projekt. Winget sollte in neueren Windows 11-Installationen enthalten sein. Allerdings muss es höchstwahrscheinlich aktualisiert werden. Führe winget -v aus, um die installierte Version zu überprüfen und sie mit der neuesten stabilen Version auf GitHub zu vergleichen.
Wenn es es nicht installiert ist, kannst du es aus dem Microsoft Store, der GitHub-Release-Seite oder über PowerShell herunterladen.
Invoke-WebRequest -Uri https://aka.ms/getwinget -OutFile Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle
Invoke-WebRequest -Uri https://aka.ms/Microsoft.VCLibs.x64.14.00.Desktop.appx -OutFile Microsoft.VCLibs.x64.14.00.Desktop.appx
Invoke-WebRequest -Uri https://github.com/microsoft/microsoft-uixaml/releases/download/v2.8.6/Microsoft.UI.Xaml.2.8.x64.appx -OutFile Microsoft.UI.Xaml.2.8.x64.appx
Add-AppxPackage Microsoft.VCLibs.x64.14.00.Desktop.appx
Add-AppxPackage Microsoft.UI.Xaml.2.8.x64.appx
Add-AppxPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle
Du kannst dieselben Befehle unter Windows 11 ausführen, um winget auf die neueste Version zu aktualisieren. Die Pakete VCLibs und Ui.Xaml sind Abhängigkeiten, die möglicherweise nicht aktualisiert werden müssen. Wenn du die Fehlermeldung erhältst, dass sie bereits auf der neuesten Version sind, mach dir keine Sorgen.
Für den Moment sollte winget als ein interaktives Desktop-Paketmanagement-Tool betrachtet werden. Du benötigst mindestens Windows 10 1809. Die einzige Serverunterstützung gibt es unter Windows Server 2022 und selbst das gilt als experimentell.
Ich empfehle, einige Zeit mit dem nativen winget Kommandozeilen-Tool zu verbringen. Das PowerShell-Modul ist ein Wrapper um die zugrundeliegenden winget APIs, und wenn du nicht verstehst, wie winget arbeitet, kann das PowerShell-Modul etwas verwirrend sein. Dieser Ratschlag gilt für alles, was eine PowerShell-Verwaltungsebene hat. Mache dich mit der Verwendung nativer Tools vertraut, bevor du beginnst PowerShell-äquivalenten Befehle zu verwenden.
Das PowerShell-Modul für den winget Client ist ebenfalls ein Open-Source-Projekt. Du kannst das Modul in der PowerShell-Galerie finden und installieren.
Find-Module Microsoft.winget.Client
Wenn du neu mit PowerShell umgehst, wirst du möglicherweise aufgefordert, den NuGet-Anbieter zu aktualisieren. Mache das ruhig.
Anmerkung: Das Modul wird auf Windows PowerShell und PowerShell 7 unterstützt.
Installiere das Modul:
Install-Module Microsoft.winget.Client -Scope CurrentUser
Konzeptionell ist winget ein benutzerspezifisches Tool, daher verwende ich den Bereich CurrentUser, aber das macht keinen Unterschied. Nochmals, wenn du neu in PowerShell bist, antworte mit Ja, wenn du aufgefordert wirst, aus einem nicht vertrauenswürdigen Repository zu installieren.
Das Modul enthält viele Befehle.
PS C:\> Get-Command -Module Microsoft.`winget`.Client | Select Name
Name
----
Add-WinGetSource
Assert-WinGetPackageManager
Deaktivieren-WinGetSetting
Aktivieren-WinGetSetting
Exportieren-WinGetPackage Finden-WinGetPackage
Get-WinGetPackage
Get-WinGetSettings
Hole-WinGetQuelle
Get-WinGetUserSettings
Get-WinGetVersion
Installieren-WinGetPackage
Entfernen-WinGetSource
Reparieren-WinGetPackageManager
Zurücksetzen-WinGetSource
Setzen-WinGetUserSettings
Test-WinGetUserSettings
Deinstallieren-WinGetPackage
Update-WinGetPackage
Ich werde nicht alle davon durchgehen, aber ich werde Ihnen einige der nützlichsten zeigen.
Eine Sache, der man sich bewusst sein sollte, zumindest zu dem Zeitpunkt, an dem ich dies schreibe, ist, dass die Hilfedokumentation des Moduls minimal ist.
Ich weiß, dass das Team hinter dem Modul eine Cmdlet-Hilfe schreibt, die hoffentlich Teil der nächsten Version sein wird. Zumindest sind die Befehlsnamen aussagekräftig und folgen der PowerShell Verb-Nomen-Namenskonvention.
PS C:\> Get-WingetVersion
v1.8.1911
PS C:\> winget -v
v1.8.1911
Denke daran, dass die PowerShell-Befehle Wrapper für das zugrunde liegende winget-Kommandozeilenwerkzeug sind. Das PowerShell-Modul fügt keine Funktionen hinzu, die du nicht mit winget ausführen kannst. Was man erhält, sind PowerShell-Funktionen wie Pipeline-Unterstützung und WhatIf.
Das bedeutet auch, dass alle Unzulänglichkeiten des Befehlszeilentools sich im PowerShell-Modul widerspiegeln werden.
Du kannst winget so konfigurieren, dass es mehrere Quellen verwendet, darunter auch den Microsoft Store. Für meine Demonstrationen werde ich die Standard-winget Quelle verwenden. Verwende den Befehl Find-WinGetPackage, um nach einem Paket zu suchen. Ich möchte die neueste PowerShell 7-Vorschau installieren. Es gibt mehrere Parameter, mit denen sich die Ergebnisse filtern lassen, wie -Tag oder -Id. Oder mach es so, was ich normalerweise tue, und verwenden einen allgemeinen Namen wie PowerShell.
Von hier aus kann ich meine Suche eingrenzen und das Paket bestätigen, das ich installieren möchte.
Find-WinGetPackage -id Microsoft.PowerShell.Preview -Source winget
Im Gegensatz zu winget, das Ihnen Text liefert, gibt das PowerShell-Modul Objekte mit definierten Eigenschaften zurück.
PS C:\> Find-WinGetPackage -id Microsoft.PowerShell.Preview -Source winget | Select *
Version : 7.5.0.3
Name : PowerShell-Vorschau
Kennung : Microsoft.PowerShell.Preview
IsUpdateAvailable : False
Quelle : winget
AvailableVersions : {7.5.0.3, 7.5.0.2, 7.5.0.1, 7.4.0.101...}
Bei der Suche nach Paketen muss man vorsichtig sein. Auch wenn PowerShell standardmäßig nicht zwischen Groß- und Kleinschreibung unterscheidet, kann winget heikel sein. Mit dem nativen Befehl kannst du Folgendes versuchen:
PS C:\> winget find --id microsoft.windowsterminal --source winget
Name Id Version
-----------------------------------------------------------------------
Windows-Terminal Microsoft.WindowsTerminal 1.20.11781.0
Windows Terminal Vorschau Microsoft.WindowsTerminal.Preview 1.21.1772.0
Die Vorschau-Version will man nicht haben, versuche es mit PowerShell zu finden:
PS C:\> Find-WinGetPackage -id Microsoft.WindowsTerminal
Name Id Version Quelle
---- -- ------- ------
Windows Terminal Microsoft.WindowsTerminal 1.20.11781.0 winget
Windows Terminal Vorschau Microsoft.WindowsTerminal.Preview 1.21.1772.0 winget
Dies ist nicht so spezifisch, wie du vielleicht denkst.Du musst den Parameter Equal einschließen, wie du es im nativen Befehl tun würdest.
PS C:\> winget find --id microsoft.windowsterminal --source winget --exact No package found matching input criteria.
PS C:\> winget find --id Microsoft.WindowsTerminal --source winget --exact Name Id Version
-------------------------------------------------------
Windows Terminal Microsoft.WindowsTerminal 1.20.11781.0
Beachte, dass die Groß- und Kleinschreibung eine Rolle spielt.
PS C:\> Find-WinGetPackage -id Microsoft.WindowsTerminal -MatchOption Equals
Name Id Version Quelle
---- -- ------- ------
Windows Terminal Microsoft.WindowsTerminal 1.20.11781.0 winget
Auch in der Welt von winget wird zwischen dem zu installierenden Paket und seinem Manifest unterschieden. Mit dem show-Befehl kann man mehr über das Paket aus seinem Manifest erfahren.
winget show --id Microsoft.PowerShell.Preview --source winget
Wenn du das gewünschte Paket gefunden hast, rufe den Find-Befehl erneut auf und leiten ihn über die Pipeline an Install-WinGetPackage weiter.
Find-WinGetPackage -id Microsoft.PowerShell.Preview -Source winget | InstallWinGetPackage
Ich finde es am besten, bei der Installation so spezifisch wie möglich zu sein. Ich verwende gerne den Parameter -Id, um das zu installierende Paket anzugeben. Auf diese Weise kann ich sicher sein, dass ich das gewünschte Paket erhalte.
Install-WinGetPackage -Id Dropbox.Dropbox -Source winget
Warnung
Es gibt ein großes Problem mit dem Install-WinGetPackage Befehl, das als GitHub-Problem abgelegt wurde. Obwohl der Befehl sagt, dass er -WhatIf unterstützt, tut er das nicht. Wenn ich versuche, Install-WinGetPackage -Id Dropbox.Dropbox -Source winget -Verbose -WhatIf auszuführen, installiert der Befehl das Paket. Ich muss davon ausgehen, dass dies in einer zukünftigen Version behoben wird, da es für das PowerShell-Paradigma grundlegend ist.
Get-WinGetPackage zeigt bekanntlich alle installierten Pakete an. Allerdings zeigt der Befehl standardmäßig auch installierte AppX-Pakete wie "Phone Link" und "Notepad" an. Obwohl es einen -Source Parameter gibt, scheint dieser nicht zu funktionieren. Mit Where-Object lassen sich die Ergebnisse filtern.
Get-WinGetPackage | Where Source -eq 'winget' | Select Name,ID,InstalledVersion
Wenn du ein bestimmtes Paket wünschst, musst du wie zuvor auf die Groß- und Kleinschreibung achten.
PS C:\> Get-WinGetPackage -Name PowerShell -MatchOption Equals
Name Id Version Verfügbar Quelle
---- -- ------- --------- ------
PowerShell Microsoft.PowerShell 7.4.4.0 winget
Im Laufe der Zeit müssen Pakete aktualisiert werden. Die Ausgabe von Get-WinGetPackage hat eine praktische Eigenschaft, die man hier nutzen kann.
PS C:\> Get-WinGetPackage | Where {$_.Source -eq 'WinGet' -AND $_.IsUpdateAvailable}
Name Id Version Available Source
---- -- ------- --------- ------
GitHub CLI GitHub.cli 2.52.0 2.54.0 winget
Dev Home (Vorschau) Microsoft.DevHome 0.1600.561.0 0.1601.561.0 winget
Windows Terminal Microsoft.WindowsTerminal 1.12.10983.0 1.20.11781.0 winget
Nur einfach Update-WinGetPackage auszuführen reicht allerdings nicht, es aktualisiert nicht automatisch alles, du musst genauere Vorgaben machen.
Get-WinGetPackage | Where {$_.Source -eq 'WinGet' -AND $_.IsUpdateAvailable}
Die Paketaktualisierungen sollten still und unbeaufsichtigt erfolgen. Am Ende des Prozesses gibt der Befehl ein zusammenfassendes Ergebnis aus.
Vorsicht
Unglücklicherweise leidet der Update-WinGetPackage-Befehl unter dem gleichen Fehler wie Install-WingetPackage.
Die Syntax deutet darauf hin, dass er -WhatIf unterstützt, aber das tut er nicht.
Um ein Paket zu entfernen, verwendest du den Befehl Uninstall-WinGetPackage. Um das Paket zu finden, das du entfernen möchtest, kannst du den Befehl Get-WinGetPackage verwenden. Wie bei den anderen Befehlen, muss der Befehl spezifisch sein.
PS C:\> Uninstall-WinGetPackage -id Git.Git -MatchOption Equals
Id Name Quelle UninstallerErrorCode Status RebootRequired ExtendedErrorCode CorrelationData
-- ---- ------ -------------------- ------ -------------- ----------------- --- ------------
Git.Git Git winget 0 Ok False
Wenn bei der Deinstallation ein Fehler auftritt, wird kein PowerShell-Fehler angezeigt, sondern ein oder mehrere Fehler in der Ausgabe. PowerShell gibt eine Ausnahme aus, wenn der Befehl Uninstall-WinGetPackage fehlschlägt, z. B. wenn das Paket nicht gefunden werden kann.
Wo sich dieses Modul trotz der Unzulänglichkeiten lohnt, ist bei der Skripterstellung. Verwende das Modul, um die Verwaltung deiner Desktop-Anwendungen zu automatisieren. Dies ist beim Aufbau von Testsystemen nützlich. Oder wenn du sicherstellen willst, dass dein Desktop so konfiguriert ist, wie du es brauchst. Es ist viel einfacher, Skripte mit PowerShell zu erstellen, als das native winget-Befehlszeilentool zu verwenden.
Hier kommen ein paar Beispiele dazu. Zunächst habe ich eine JSON-Datei mit den Paketen erstellt, von denen ich sicherstellen möchte, dass sie installiert und auf dem neuesten Stand sind. Ich führe einen Befehl wie den folgenden aus, um die Datei zu erstellen.
Get-WingetPackage | Where-Object { $_.Source -eq 'winget' } |
Select-Object Name,ID | ConvertTo-Json |
Out-File -FilePath D:\temp\winget.json -Encoding utf8
Dann wird die Datei so bearbeitet, dass sie nur die Pakete enthält, die installiert werden sollen.
Ich verwende JSON, aber du kannst jedes Format verwenden, das dir zusagt.
[
{
"Name": "Git",
"Id": "Git.Git"
},
{
"Name": "Mozilla Firefox",
"Id": "Mozilla.Firefox"
},
{
"Name": "Mozilla Thunderbird",
"Id": "Mozilla.Thunderbird"
},
...
Ich nutze dieses Skript, das die JSON-Datei liest und die Pakete installiert, wenn sie nicht bereits installiert sind. Wenn das Paket installiert ist, dann wird es nach Updates suchen.
#requires -Version 5.1
#requires -RunAsAdministrator
#requires -module Microsoft.Winget.Client
#WingetMaster.ps1
[cmdletbinding(SupportsShouldProcess)]
Param(
[Parameter(HelpMessage = 'Pfad zur winget.json Datei')]
[ValidateScript({ Test-Path $_ })]
[string]$Path = '.winget.json'
)
#Piping konvertierte Ausgabe, um einen Formatierungsfehler in Windows PowerShell zu beheben
$find = Get-Content -Path $Path -Encoding utf8 |
ConvertFrom-Json |
foreach { $_ } |
Find-WinGetPackage -Source winget -match Equals
foreach ($pkg in $find) {
$r = Get-WinGetPackage -Id $pkg.Id -MatchOption Equals
if ($null -eq $r) {
#Installiere das Paket, wenn es nicht bereits installiert ist
Write-Host "Installing $($pkg.Id)" -ForegroundColor Cyan
#verwendet meinen eigenen WhatIf-Code
if ($PSCmdlet.ShouldProcess($pkg.Id, 'Install-WinGetPackage')) {
Install-WinGetPackage -Id $pkg.Id
}
}
elseif ($r.IsUpdateAvailable) {
#Update des Pakets, wenn eine neue Version verfügbar ist
Write-Host "Updating $($pkg.Id)" -ForegroundColor Yellow
if ($PSCmdlet.ShouldProcess($pkg.Id, 'Update-WinGetPackage')) {
Update-WinGetPackage -Id $pkg.Id
}
}
else {
Write-Host "$($pkg.Id) is already installed" -ForegroundColor Green
}
} #foreach
Write-Host "$($MyInvocation.MyCommand) completed" -ForegroundColor Green
Mein Code fügt Unterstützung für WhatIf hinzu, die funktioniert.
Das kannst du so oft ausführen, wie du möchtest. Es installiert nichts, was bereits installiert oder aktuell ist.
Ich habe auch ein Tool, mit dem ich ausgewählte Pakete aktualisieren kann. Dieses Skript benötigt PowerShell 7 und das Microsoft.PowerShell.ConsoleGuiTools Modul.
#requires -version 7.3
#requires -Module Microsoft.Winget.Client
#requires -Module Microsoft.PowerShell.ConsoleGuiTools
#UpdateWingetPackages.ps1
[CmdletBinding()]
Param()
#17 Jan 2024 Ausnahmen in eine externe Datei verschoben
[string]$Exclude = (Get-Content $PSScriptRoot\WingetExclude.txt | Where-Object {$_ -notMatch "^#" -AND $_ -match "\w+"}) -join "|"
#10 Jan 2024 Updates parallel aufrufen
$sb = {
Param($MyExclude)
Write-Progress "[$((Get-Date).TimeOfDay)] Checking for Winget package updates"
Get-WinGetPackage -Source Winget |
Where-Object {$_.Source -eq 'winget' -AND
$_.IsUpdateAvailable -AND ($_.InstalledVersion -notMatch "unknown|\<") -AND ($_.Name -notMatch $myExclude)} |
Out-ConsoleGridView -Title "Select Winget packages to upgrade" -OutputMode Multiple |
Foreach-Object -Parallel {
$Name = $_.Name
Write-Host "[$((Get-Date).TimeOfDay)] Updating $($_.Name)" -ForegroundColor Green
# 22. April 2024 Fehlerbehandlung hinzugefügt, um eine sinnvolle Ausnahmemeldung zu schreiben
Try {
Update-WinGetPackage -mode Silent -ID $_.ID -Source Winget -ErrorAction Stop |
Select-Object @{Name="Package";Expression= {$Name}},RebootRequired,InstallerErrorCode,Status
}
Catch {
Write-Warning "Failed to update $Name. $($_.Exception.Message)"
}
}
}
Try {
#Überprüfe, ob die Befehle des Winget-Moduls ausgeführt werden. Es kann Assembly-Konflikte mit dem ConsoleGuiTools-Modul geben
$null = Get-WinGetVersion -ErrorAction stop
Invoke-Command -ScriptBlock $sb -ArgumentList $Exclude
}
Catch {
#write-warning $_.Exception.message
#Ausführen der Aufgabe in einer sauberen PowerShell-Sitzung, um Assembly-Konflikte zu vermeiden
pwsh -NoLogo -NoProfile -command $sb -args $Exclude
}
Ich habe mehrere Pakete, die ich entweder auf einer bestimmten Version halten möchte, wegen Kompatibilitätsproblemen nicht aktualisieren möchte oder es vorziehe, Aktualisierungen mit anderen Mitteln zu verwalten. Mein Skript verwendet eine exclude-Datei, um diese Pakete zu definieren.
#wingetexclude.txt
#Winget-Pakete, die von UpdateWingetPackages.ps1 auszuschließen sind
#Diese Datei muss sich im selben Verzeichnis wie das Update-Skript befinden
#Paketnamen werden in einem Regex-Muster verwendet
MuseScore
Python
ESET
Discord
Camtasia
Dymo
Spotify
PowerShell
FoxIt
Wenn ich das Skript ausführe, werden die Pakete mit verfügbaren Updates über Out-ConsoleGridView angezeigt.
Ich kann die Pakete auswählen, die ich aktualisieren möchte, und auf OK klicken. Der andere Grund, warum ich PowerShell 7 verwende, ist, dass ich die Updates parallel ausführen kann. So lassen sich mehrere Pakete schnell aktualisieren.
Ich hoffe, dass die nächste Version des Moduls Microsoft.Winget.Client eine solidere Hilfedokumentation enthält und einige Bugs behebt. Das Modul ist eine großartige Möglichkeit, die Verwaltung deiner Desktop-Anwendungen zu automatisieren, wenn du ein Winget-Benutzer bist. Du kannst es verwenden, um sicherzustellen, dass dein Desktop so konfiguriert ist, wie du es brauchst, oder du kannst es verwenden, um Labor- oder Testmaschinen schnell zu konfigurieren. Winget ist immer noch in erster Linie ein Desktop-Tool. Ich weiß, dass eine Winget DSC-Ressource in Arbeit ist, die Serverbedürfnisse ansprechen könnte, aber das ist ein Thema für einen anderen Beitrag.
Ich möchte dich ermutigen, das Modul auszuprobieren und es zu testen. Meldet Probleme und startet Diskussionen im GitHub-Repository. Je mehr Feedback das Team bekommt, desto besser wird das Modul werden und wir werden alle davon profitieren.
Entfessele das volle Potenzial von PowerShell mit unserem praktischen Poster. Egal, ob frischer Einsteiger oder erfahrener Profi, dieser Spickzettel ist so konzipiert, dass du schnell die wichtigsten und am häufigsten verwendeten Cmdlets findest.
Das Poster ist zum Download und in Papierform erhältlich.
Dez 19, 2024 by Jeffery Hicks
Steigere die IT-Effizienz mit Winget und PowerShell! Lies, wie du Installationen, Updates und die Verwaltung von...
Dez 19, 2024 by Damian Scoles
Mit Microsoft Purview verstehst und verwaltest du Daten in deinem gesamten Datenbestand – wie kannst du PowerShell...
Okt 30, 2024 by Damian Scoles
MVP Damien Scoles berichtet über seine Erfahrungen mit Microsoft Graph. In seinem dritten Artikel geht er näher auf...
Jeffery Hicks ist ein IT-Veteran mit fast 35 Jahren Erfahrung, davon die meiste Zeit als IT-Infrastrukturberater, spezialisiert auf Microsoft-Servertechnologien mit Schwerpunkt Automatisierung und Effizienz. Er ist mehrfacher Gewinner des Microsoft MVP Awards. Jeff ist ein angesehener und bekannter Autor, Dozent und Berater. In den letzten 20 Jahren hat Jeff PowerShell-Inhalte und die Vorteile der Automatisierung für IT-Profis auf der ganzen Welt gelehrt und präsentiert. Jeff ist Autor bei Pluralsight und tritt häufig als Redner bei Technologiekonferenzen und Anwendergruppen auf. Bleib auf dem Laufenden mit Jeff unter https://jdhitsolutions.github.io