Winget ist ein praktisches Kommandozeilenwerkzeug, wenn es darum geht, Software unter Windows schnell zu installieren. Allerdings sind Paketnamen nicht immer selbsterklärend, und die Suche liefert häufig viele Ergebnisse. Dafür habe ich ein kleines PowerShell-Skript erstellt, das die Bedienung deutlich erleichtert.
Das Skript bietet ein Menü, mit dem man nach Programmen suchen kann. Die Suchergebnisse werden anschließend in einer Out-GridView angezeigt, in der man Pakete per Mausklick auswählen und installieren kann. Damit entfällt das manuelle Tippen von Paket-IDs.
Funktionsweise
- Das Skript führt eine Winget-Suche mit normaler Textausgabe aus.
- Die Ausgabe wird gefiltert und in Spalten aufgeteilt, unabhängig von der verwendeten Winget-Version.
- Alle Treffer erscheinen in einer grafischen Tabelle.
- Ausgewählte Einträge lassen sich direkt installieren.
Die Parserlogik basiert auf der Tatsache, dass Winget seine tabellarische Ausgabe mit mehreren Leerzeichen zwischen den Spalten trennt. Dadurch ist das Skript stabiler als Varianten, die die JSON-Ausgabe verwenden.
Bedienung
Nach dem Start erscheint ein kleines Menü. Mit der Option „Nach Programm suchen“ gibt man einen Begriff wie „firefox“ oder „gimp“ ein. Danach öffnet sich ein Fenster mit allen gefundenen Paketen. Nach der Auswahl installiert Winget die Programme automatisch.
Das Skript ist ein einfaches, aber hilfreiches Werkzeug für alle, die mit Winget arbeiten, aber nicht ständig Paketnamen nachschlagen möchten. Es läuft problemlos in der PowerShell ISE und kann leicht erweitert werden, etwa um Update-Funktionen oder Softwarelisten.
Folgendes Skript muss in die PowerShell ISE mit Administratorrechten eingefügt und abgespeichert werden, bevor es ausgeführt wird:
# Prüfen, ob winget verfügbar ist
if (-not (Get-Command winget -ErrorAction SilentlyContinue)) {
Write-Error "winget wurde nicht gefunden. Bitte stelle sicher, dass es installiert und im PATH ist."
return
}
function Search-WingetPackages {
param(
[Parameter(Mandatory = $true)]
[string]$Query
)
Write-Host "Suche nach Paketen für: '$Query' ..." -ForegroundColor Cyan
# Winget-Suche mit normaler Textausgabe
$output = winget search $Query 2>$null
if (-not $output) {
Write-Warning "Keine Ausgabe von winget erhalten."
return @()
}
# Leere Zeilen und Trennlinien rausfiltern
$lines = $output |
Where-Object {
$_.Trim() -ne "" -and
$_ -notmatch '^\s*-{3,}\s*$'
}
if ($lines.Count -lt 2) {
Write-Warning "Zu wenige Zeilen in der winget-Ausgabe."
return @()
}
# Headerzeile suchen (die mit "Name" und "Id")
$headerIndex = -1
for ($i = 0; $i -lt $lines.Count; $i++) {
if ($lines[$i] -match 'Name' -and $lines[$i] -match 'Id') {
$headerIndex = $i
break
}
}
if ($headerIndex -eq -1 -or $headerIndex -ge ($lines.Count - 1)) {
Write-Warning "Konnte die Headerzeile der winget-Tabelle nicht erkennen."
return @()
}
# Alle Zeilen nach dem Header sind Datenzeilen
$dataLines = $lines[($headerIndex + 1)..($lines.Count - 1)]
$packages = foreach ($line in $dataLines) {
# Spalten sind durch mind. zwei Leerzeichen getrennt
$parts = $line -split "\s{2,}"
if ($parts.Length -ge 3) {
[PSCustomObject]@{
Name = $parts[0].Trim()
Id = $parts[1].Trim()
Version = $parts[2].Trim()
Source = if ($parts.Length -ge 4) { $parts[3].Trim() } else { "" }
}
}
}
if (-not $packages -or $packages.Count -eq 0) {
Write-Warning "Keine Pakete aus der Ausgabe parsen können."
return @()
}
return $packages
}
function Install-WingetPackage {
param(
[Parameter(Mandatory = $true)]
$Package
)
$name = $Package.Name
$id = $Package.Id
$source = $Package.Source
Write-Host ""
Write-Host "Installationsbefehl:" -ForegroundColor Yellow
if ($source) {
Write-Host " winget install --id `"$id`" --source `"$source`" --accept-package-agreements --accept-source-agreements"
} else {
Write-Host " winget install --id `"$id`" --accept-package-agreements --accept-source-agreements"
}
Write-Host ""
$confirm = Read-Host "Paket '$name' ($id) wirklich installieren? (j/n)"
if ($confirm -ne 'j' -and $confirm -ne 'J') {
Write-Host "Abgebrochen." -ForegroundColor DarkYellow
return
}
if ($source) {
winget install --id "$id" --source "$source" --accept-package-agreements --accept-source-agreements
} else {
winget install --id "$id" --accept-package-agreements --accept-source-agreements
}
}
function Start-WingetGuiSearch {
do {
Write-Host ""
Write-Host "===== Winget Such- & Installationsmenü =====" -ForegroundColor Green
Write-Host "1) Nach Programm suchen"
Write-Host "0) Beenden"
Write-Host "============================================"
$choice = Read-Host "Auswahl"
switch ($choice) {
'1' {
$query = Read-Host "Bitte Suchbegriff eingeben (z.B. 'firefox' oder 'gimp')"
if ([string]::IsNullOrWhiteSpace($query)) {
Write-Host "Kein Suchbegriff eingegeben." -ForegroundColor DarkYellow
break
}
$packages = Search-WingetPackages -Query $query
if (-not $packages -or $packages.Count -eq 0) {
Write-Host "Keine passenden Pakete gefunden." -ForegroundColor DarkYellow
break
}
# Anzeige in Out-GridView mit Auswahl
$selected = $packages |
Out-GridView -Title "Suchergebnisse für '$query' - wähle Paket(e) zur Installation" -PassThru
if (-not $selected) {
Write-Host "Keine Pakete ausgewählt." -ForegroundColor DarkYellow
break
}
foreach ($pkg in $selected) {
Install-WingetPackage -Package $pkg
}
}
'0' {
Write-Host "Beenden..." -ForegroundColor Green
return
}
default {
Write-Host "Ungültige Auswahl." -ForegroundColor Red
}
}
} while ($true)
}
# Einstiegspunkt
Start-WingetGuiSearch
Hinweis zur Ausführung von PowerShell-Skripten
Falls das Skript bei dir nicht ausgeführt werden kann und eine Fehlermeldung zur Ausführungsrichtlinie erscheint, muss eventuell vorher die PowerShell Execution Policy angepasst werden.
Führe dazu in einer PowerShell mit Administratorrechten folgenden Befehl aus:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
Damit erlaubst du lokal signierte Skripte und selbst erstellte Skripte, ohne die Sicherheit vollständig aufzuheben. Anschließend kannst du das Update-Skript wie beschrieben starten.
Alle Angaben ohne Gewähr.

