From 9801e8d14c6ffba12f9d9d4d0aac17a19cce7e28 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 26 Dec 2025 15:26:25 -0600 Subject: [PATCH 1/3] Let file handles be released before deleting --- Tools/YamlCreate.ps1 | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/Tools/YamlCreate.ps1 b/Tools/YamlCreate.ps1 index b7a9065281698..c6e692593c11d 100644 --- a/Tools/YamlCreate.ps1 +++ b/Tools/YamlCreate.ps1 @@ -236,7 +236,7 @@ if ($Settings) { exit } -$ScriptHeader = '# Created with YamlCreate.ps1 v2.7.0' +$ScriptHeader = '# Created with YamlCreate.ps1 v2.7.1' $ManifestVersion = '1.12.0' $PSDefaultParameterValues = @{ '*:Encoding' = 'UTF8' } $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False @@ -634,6 +634,33 @@ Function Get-InstallerFile { return $_OutFile } +Function SafeRemovePath { + Param( + [Parameter(Mandatory=$true, Position=0)] + [string] $Path, + [int] $Retries = 6, + [int] $DelayMs = 250 + ) + + if (-not (Test-Path -LiteralPath $Path)) { return } + + for ($i = 0; $i -lt $Retries; $i++) { + try { + Remove-Item -LiteralPath $Path -Force -ErrorAction Stop + return + } catch [System.IO.IOException] { + [GC]::Collect() + [GC]::WaitForPendingFinalizers() + Start-Sleep -Milliseconds $DelayMs + $DelayMs = [Math]::Min(5000, $DelayMs * 2) + } catch { + throw + } + } + + Write-Warning "Could not remove file '$Path' after $Retries attempts; it may be in use by another process." +} + Function Get-UserSavePreference { switch ($ScriptSettings.SaveToTemporaryFolder) { 'always' { $_Preference = '0' } @@ -1439,7 +1466,7 @@ Function Read-QuickInstallerEntry { } } # Remove the downloaded files - Remove-Item -Path $script:dest + SafeRemovePath $script:dest Write-Host -ForegroundColor 'Green' "Installer updated!`n" } @@ -3084,7 +3111,7 @@ Switch ($script:Option) { } } # Remove the downloaded files - Remove-Item -Path $script:dest + SafeRemovePath $script:dest $_NewInstallers += Restore-YamlKeyOrder $_Installer $InstallerEntryProperties -NoComments } # Write the new manifests From c5e01243f6454291b1ae7c91bf932f5e9abce475 Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 26 Dec 2025 15:31:08 -0600 Subject: [PATCH 2/3] Fix ScriptAnalyzer warning --- Tools/YamlCreate.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/YamlCreate.ps1 b/Tools/YamlCreate.ps1 index c6e692593c11d..97b16ef320710 100644 --- a/Tools/YamlCreate.ps1 +++ b/Tools/YamlCreate.ps1 @@ -1466,7 +1466,7 @@ Function Read-QuickInstallerEntry { } } # Remove the downloaded files - SafeRemovePath $script:dest + SafeRemovePath -Path $script:dest Write-Host -ForegroundColor 'Green' "Installer updated!`n" } @@ -3111,7 +3111,7 @@ Switch ($script:Option) { } } # Remove the downloaded files - SafeRemovePath $script:dest + SafeRemovePath -Path $script:dest $_NewInstallers += Restore-YamlKeyOrder $_Installer $InstallerEntryProperties -NoComments } # Write the new manifests From b15fda0cec4f0fa16c6a955835b21826fc1179fd Mon Sep 17 00:00:00 2001 From: Kaleb Luedtke Date: Fri, 26 Dec 2025 15:48:36 -0600 Subject: [PATCH 3/3] Fix product code detection --- Tools/YamlCreate.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tools/YamlCreate.ps1 b/Tools/YamlCreate.ps1 index 97b16ef320710..cf1aab8182e05 100644 --- a/Tools/YamlCreate.ps1 +++ b/Tools/YamlCreate.ps1 @@ -1063,7 +1063,7 @@ Function Read-InstallerEntry { Get-UriScope -URI $_Installer['InstallerUrl'] -OutVariable _ | Out-Null if ($_) { $_Installer['Scope'] = $_ | Select-Object -First 1 } if ([System.Environment]::OSVersion.Platform -match 'Win' -and ($script:dest).EndsWith('.msi')) { - $ProductCode = ([string](Get-MSIProperty -Path $script:dest -Property 'ProductCode') | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value + $ProductCode = [string](Get-MSIProperty -Path $script:dest -Property 'ProductCode').Value } elseif ([System.Environment]::OSVersion.Platform -match 'Unix' -and (Get-Item $script:dest).Name.EndsWith('.msi')) { $ProductCode = ([string](file $script:dest) | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value } @@ -1435,7 +1435,7 @@ Function Read-QuickInstallerEntry { # If a new product code doesn't exist, and the installer isn't an `.exe` file, remove the product code if it exists $MSIProductCode = $null if ([System.Environment]::OSVersion.Platform -match 'Win' -and ($script:dest).EndsWith('.msi')) { - $MSIProductCode = ([string](Get-MSIProperty -Path $script:dest -Property 'ProductCode') | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value + $MSIProductCode = [string](Get-MSIProperty -Path $script:dest -Property 'ProductCode').Value } elseif ([System.Environment]::OSVersion.Platform -match 'Unix' -and (Get-Item $script:dest).Name.EndsWith('.msi')) { $MSIProductCode = ([string](file $script:dest) | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value } @@ -3079,7 +3079,7 @@ Switch ($script:Option) { # If a new product code doesn't exist, and the installer isn't an `.exe` file, remove the product code if it exists $MSIProductCode = $null if ([System.Environment]::OSVersion.Platform -match 'Win' -and ($script:dest).EndsWith('.msi')) { - $MSIProductCode = ([string](Get-MSIProperty -Path $script:dest -Property 'ProductCode') | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value + $MSIProductCode = [string](Get-MSIProperty -Path $script:dest -Property 'ProductCode').Value } elseif ([System.Environment]::OSVersion.Platform -match 'Unix' -and (Get-Item $script:dest).Name.EndsWith('.msi')) { $MSIProductCode = ([string](file $script:dest) | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches.Value }