Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 85 additions & 72 deletions src/prototype/WingetCreateMakeDSC.ps1
Original file line number Diff line number Diff line change
@@ -1,110 +1,123 @@
# This script is a prototype for quickly creating DSC files.

#Powershell 7 Required
$hostdata=host
if ($hostdata.version.major -lt 7) {
Write-host "This script requires powershell 7. You can update powershell by typing winget install Microsoft.Powershell." -ForegroundColor red
[Environment]::Exit(1)
if ($(Get-Host).version.major -lt 7) {
Write-Host 'This script requires powershell 7. You can update powershell by typing winget install Microsoft.Powershell.' -ForegroundColor red
Exit(1)
}

#Set output encoding to UTF-8
$OutputEncoding = [ System.Text.Encoding]::UTF8
# Create a custom exception type for our dependency management
class UnmetDependencyException : Exception {
UnmetDependencyException([string] $message) : base($message) {}
UnmetDependencyException([string] $message, [Exception] $exception) : base($message, $exception) {}
}

if ($null -eq (Get-InstalledModule -Name Microsoft.Winget.Client))
{
try { Install-Module Microsoft.Winget.Client
# Ensure the Winget PowerShell modules are installed
if (-not(Get-Module -ListAvailable -Name Microsoft.Winget.Client)) {
try {
Install-Module Microsoft.Winget.Client
} catch {
#Pass the exception
throw [System.Net.WebException]::new("Error retrieving powershell module: Microsoft.Winget.Client. Check that you have installed the Windows Package Manager modules correctly.", $_.Exception)
#bugbug is this good enough?
# If there was an exception while installing, pass it as an InternalException for further debugging
throw [UnmetDependencyException]::new("'Microsoft.Winget.Client' was not installed successfully", $_.Exception)
} finally {
# Check to be sure it acutally installed
if (-not(Get-Module -ListAvailable -Name Microsoft.Winget.Client)) {
throw [UnmetDependencyException]::new("`Microsoft.Winget.Client` was not found. Check that you have installed the Windows Package Manager modules correctly.")
}
}
}

if ($null -eq (Get-InstalledModule -Name powershell-yaml))
{
# Ensure the powershell-yaml module is installed
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
try {
Install-Module powershell-yaml
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name powershell-yaml -Force -Repository PSGallery -Scope CurrentUser
} catch {
#Pass the exception
throw [System.Net.WebException]::new("Error retrieving powershell module: powershell-yaml. Check that you have installed the Windows Package Manager modules correctly.", $_.Exception)
#bugbug is this good enough?
# If there was an exception while installing, pass it as an InternalException for further debugging
throw [UnmetDependencyException]::new("'powershell-yaml' was not installed successfully", $_.Exception)
} finally {
# Check to be sure it acutally installed
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
throw [UnmetDependencyException]::new("`powershell-yaml` was not found. Check that you have installed the module correctly.")
}
}
}

[System.Collections.ArrayList]$finalPackages = @()
$configurationVersion = "0.2.0"
$configurationVersion = '0.2.0'
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
$DSCHeader = "# yaml-language-server: `$schema=https://aka.ms/configuration-dsc-schema/$($configurationVersion -Replace '\.0$','')"

$continue = $true
do
{
$appId = Read-Host "What is the Winget ID, or name of the package you want to add to the configuration file?"
$findResult = Find-WinGetPackage $appId
do {
$findResult = Find-WinGetPackage $(Read-Host 'What is the Winget ID, or name of the package you want to add to the configuration file?')

if ($findResult.count -ne 0)
{
$Index=1
foreach ($package in $findResult)
{
$packageDetails = "[$($Index)] $($package.Name) | $($package.Id) | $($package.Version)"
Write-Host $packageDetails
$index++
}
if ($findResult.count -ne 0) {
# Assign an index to each package
$findResult | ForEach-Object { $script:i = 1 } { Add-Member -InputObject $_ -NotePropertyName Index -NotePropertyValue $i; $i++ }
$findResult | Select-Object -Property Index, Name, Id, Version | Format-Table | Out-Host

$selection = -1
$packageSelected = $false
while (-not($packageSelected))
{
write-host
# TODO: We should capture against bad value. "string"
# TODO: We should allow user to skip. Maybe hit S or X.
$selection = [int](Read-Host "Input the number of the package you want to select")
if (($selection -gt $findResult.count) -or ($selection -lt 1))
{
Write-Host "Selection is out of range, try again."
}
else
{
$packageSelected = $true
while (-not($packageSelected)) {
Write-Host
# Prompt user for selection string
$selection = (Read-Host 'Select a package by Index, Name, or Id. Press enter to continue or skip')
$selectedPackage = $null
# If user didn't enter any selection string, set no package as selected and continue
if ( [string]::IsNullOrWhiteSpace($selection) ) {
$packageSelected = $true
} elseif ( $selection -in $findResult.Id ) {
# If the user entered a string which matches the Id, select that package
$selectedPackage = $findResult.Where({ $_.Id -eq $selection })
$packageSelected = $true
} elseif ( $selection -in $findResult.Name ) {
# If the user entered a string which matches the Name, select that package
# Because names could conflict, take the first item in the list to avoid error
$selectedPackage = $findResult.Where({ $_.Name -eq $selection }) | Select-Object -First 1
$packageSelected = $true
} else {
# If the name and ID didn't match, try selecting by index
# This needs to be a try-catch to handle converting strings to integers
try {
$selectedPackage = $findResult.Where({ $_.Index -eq [int]$selection })
# If the user selects an index out of range, don't set no package as selected. Instead, allow for correcting the index
# If the intent is to select no package, the user will be able to skip after being notified the index is out of range
if ($selectedPackage) {
$packageSelected = $true
} else {
Write-Host 'Index out of range, please try again'
}
} catch {
Write-Host 'Invalid entry, please try again'
}
}
}

$selectedPackage = $findResult[$selection - 1]

#Specify Source
#Winget currently has 2 sources. If the ID contains a period, we will assume winget.
#otherwise it is the MSSTORE. We are not accounting for private REPOs at this time.
If ($selectedPackage.Id -like "*.*") {
$source="winget"
} else {
$source="msstore"
# If a package was selected, add it to the package list; Otherwise, continue
if ($selectedPackage) {
$unit = @{'resource' = 'Microsoft.WinGet.DSC/WinGetPackage'; 'directives' = @{'description' = $selectedPackage.Name; 'allowPrerelease' = $true; }; 'settings' = @{'id' = $selectedPackage.Id; 'source' = $selectedPackage.Source } }
[void]$finalPackages.Add($unit)
Write-Host "Added $($selectedPackage.Name)" -ForegroundColor Blue
}

$unit = @{"resource" = "Microsoft.WinGet.DSC/WinGetPackage"; "directives" = @{"description" = $selectedPackage.Name; "allowPrerelease" = $true; }; "settings" = @{"id" = $selectedPackage.Id; "source"=$source }}
$tempvar = $finalPackages.Add($unit)
write-host Added $selectedPackage.Name -ForegroundColor blue


} else {
Write-Host 'No package found matching input criteria.' -ForegroundColor DarkYellow
}
else
{
Write-Host "No package found matching input criteria." -ForegroundColor DarkYellow
}
} while ($(Read-Host "Would you like to add another package? [y/n]") -eq 'y')
} while ($(Read-Host 'Would you like to add another package? [y/n]') -eq 'y')

Write-host
$fileName = Read-Host "Name of the configuration file (without extension)"
Write-Host
$fileName = Read-Host 'Name of the configuration file (without extension)'
$filePath = Join-Path -Path (Get-Location) -ChildPath "$($fileName).winget"

ConvertTo-Yaml @{"properties"= @{"resources"=$finalPackages; "configurationVersion"= $configurationVersion}} -OutFile $filePath -Force
$rawYaml = ConvertTo-Yaml @{'properties' = @{'resources' = $finalPackages; 'configurationVersion' = $configurationVersion } }
[System.IO.File]::WriteAllLines($filePath, @($DSCHeader, '', $rawYaml.trim()), $Utf8NoBomEncoding)

Write-Host
Write-Host Testing resulting file. -ForegroundColor yellow
Write-Host 'Testing resulting file...' -ForegroundColor yellow
(&winget configure --help) > $null

if ($LASTEXITCODE -eq 0) {
winget configure validate --file $filePath
}
else {
} else {
Write-Host "'winget configure' is not available, skipping validation." -ForegroundColor Yellow
}

Expand Down