Skip to content

Commit 99170ab

Browse files
committed
Release 1.288.2025
1 parent 979e32a commit 99170ab

27 files changed

+505
-59
lines changed
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
##############################################################################
2+
# Part of PowerShell module : GenXdev.Helpers
3+
# Cmdlet filename : Confirm-InstallationConsent.ps1
4+
# Author : René Vaessen / GenXdev (with AI assistance)
5+
# Version : 1.0.0
6+
################################################################################
7+
# MIT License
8+
#
9+
# Copyright 2021-2025 GenXdev
10+
#
11+
# Permission is hereby granted, free of charge, to any person obtaining a copy
12+
# of this software and associated documentation files (the "Software"), to deal
13+
# in the Software without restriction, including without limitation the rights
14+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
# copies of the Software, and to permit persons to whom the Software is
16+
# furnished to do so, subject to the following conditions:
17+
#
18+
# The above copyright notice and this permission notice shall be included in all
19+
# copies or substantial portions of the Software.
20+
#
21+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
# SOFTWARE.
28+
################################################################################
29+
<#
30+
.SYNOPSIS
31+
Confirms user consent for installing third-party software, using preferences for persistent choices.
32+
33+
.DESCRIPTION
34+
This function acts as a custom ShouldProcess mechanism specifically for software installations.
35+
It checks a user preference (via Get-GenXdevPreference) to determine if automatic installation
36+
is allowed for the specified application. If no preference is set, it prompts the user with
37+
a clear explanation of what will be installed, the source, potential risks, and options to
38+
allow or deny the installation (with options for one-time or persistent choices).
39+
40+
This ensures explicit user consent before proceeding with any installation, helping to
41+
mitigate potential legal risks by requiring affirmative action from the user. The prompt
42+
clearly states that the module author (GenXdev) is not responsible for third-party software,
43+
and that the user is consenting to the installation at their own risk.
44+
45+
Preferences are stored using Set-GenXdevPreference, allowing users to set "always allow"
46+
or "always deny" for specific applications, making it convenient while remaining legally sound.
47+
48+
If consent is denied (or preference is set to deny), the function returns $false and does not
49+
proceed with installation. If allowed, it returns $true.
50+
51+
.PARAMETER ApplicationName
52+
The name of the application or software being installed (e.g., "Docker Desktop", "Sysinternals Suite").
53+
This is used to create a unique preference key like "AllowInstall_DockerDesktop".
54+
55+
.PARAMETER Source
56+
The source of the installation (e.g., "Winget", "PowerShell Gallery", "apt-get in WSL", "dotnet CLI").
57+
This is included in the explanation prompt for transparency.
58+
59+
.PARAMETER Description
60+
Optional detailed description of what the software does and why it's being installed.
61+
If not provided, a generic message is used.
62+
63+
.PARAMETER Publisher
64+
Optional publisher or vendor of the software (e.g., "Microsoft", "Docker Inc.").
65+
Included in the prompt for clarity.
66+
67+
.PARAMETER ForcePrompt
68+
Forces a prompt even if a preference is already set (useful for re-confirmation).
69+
70+
.EXAMPLE
71+
if (Confirm-InstallationConsent -ApplicationName "Docker Desktop" -Source "Winget") {
72+
# Proceed with installation
73+
Microsoft.WinGet.Client\Install-WinGetPackage -Id "Docker.DockerDesktop"
74+
}
75+
76+
This checks consent before installing Docker Desktop via Winget.
77+
78+
.EXAMPLE
79+
Confirm-InstallationConsent -ApplicationName "Pester" -Source "PowerShell Gallery" -Publisher "Pester Team" -Description "Required for unit testing in PowerShell modules."
80+
81+
Prompts with detailed information before installing the Pester module.
82+
83+
.NOTES
84+
- Preference keys are formatted as "AllowInstall_<ApplicationName>" (spaces removed for simplicity).
85+
- Preferences are stored in JSON format at: $Env:LOCALAPPDATA\GenXdev.PowerShell\SoftwareConsent.json
86+
- If denied, no installation occurs, and the function returns $false.
87+
- For legal soundness: The prompt explicitly requires user consent, disclaims liability, and explains risks (e.g., third-party software may have its own terms, potential security implications).
88+
- Integrate this into your Ensure* functions by replacing automatic installations with a check like: if (-not (Confirm-InstallationConsent ...)) { throw "Installation consent denied." }
89+
- For non-Winget installs (e.g., apt-get in EnsureYtdlp, dotnet in EnsureNuGetAssembly), still use this function for consistency.
90+
- This function does not perform the installation itself—it's purely for consent checking.
91+
#>
92+
function Confirm-InstallationConsent {
93+
94+
[CmdletBinding()]
95+
[OutputType([System.Boolean])]
96+
97+
param(
98+
[Parameter(Mandatory = $true, Position = 0,
99+
HelpMessage = "The name of the application or software being installed.")]
100+
[ValidateNotNullOrEmpty()]
101+
[string] $ApplicationName,
102+
103+
[Parameter(Mandatory = $true, Position = 1,
104+
HelpMessage = "The source of the installation (e.g., Winget, PowerShell Gallery).")]
105+
[ValidateNotNullOrEmpty()]
106+
[string] $Source,
107+
108+
[Parameter(Mandatory = $false,
109+
HelpMessage = "Optional description of the software and its purpose.")]
110+
[string] $Description = "This software is required for certain features in the GenXdev modules.",
111+
112+
[Parameter(Mandatory = $false,
113+
HelpMessage = "Optional publisher or vendor of the software.")]
114+
[string] $Publisher = "Third-party vendor",
115+
116+
[Parameter(Mandatory = $false,
117+
HelpMessage = "Force a prompt even if preference is set.")]
118+
[switch] $ForcePrompt
119+
)
120+
121+
begin {
122+
# Normalize ApplicationName for preference key (remove spaces, make it safe)
123+
$safeAppName = $ApplicationName -replace '\s+', ''
124+
$preferenceKey = "AllowInstall_$safeAppName"
125+
126+
# Setup JSON file path for storing consent preferences
127+
$consentDir = Microsoft.PowerShell.Management\Join-Path $Env:LOCALAPPDATA "GenXdev.PowerShell"
128+
$consentFile = Microsoft.PowerShell.Management\Join-Path $consentDir "SoftwareConsent.json"
129+
130+
Microsoft.PowerShell.Utility\Write-Verbose "Checking consent for installing '$ApplicationName' from '$Source'."
131+
}
132+
133+
process {
134+
# Check existing preference from JSON file
135+
$existingPref = $null
136+
try {
137+
if (Microsoft.PowerShell.Management\Test-Path $consentFile) {
138+
$consentData = Microsoft.PowerShell.Management\Get-Content $consentFile -Raw | Microsoft.PowerShell.Utility\ConvertFrom-Json -ErrorAction SilentlyContinue
139+
if ($consentData -and $consentData.PSObject.Properties.Name -contains $preferenceKey) {
140+
$existingPref = $consentData.$preferenceKey
141+
}
142+
}
143+
} catch {
144+
Microsoft.PowerShell.Utility\Write-Verbose "Could not read consent file: $_"
145+
}
146+
147+
if ($existingPref -and -not $ForcePrompt) {
148+
if ($existingPref -eq 'true') {
149+
Microsoft.PowerShell.Utility\Write-Verbose "Existing preference allows installation of '$ApplicationName'."
150+
return $true
151+
} elseif ($existingPref -eq 'false') {
152+
Microsoft.PowerShell.Utility\Write-Warning "Installation of '$ApplicationName' denied by user preference."
153+
return $false
154+
}
155+
}
156+
157+
# If no preference or ForcePrompt, explain and prompt
158+
$promptMessage = @"
159+
`n### Installation Consent Required for '$ApplicationName' ###
160+
161+
This PowerShell module (GenXdev) needs to install third-party software: '$ApplicationName'.
162+
- Publisher: $Publisher
163+
- Source: $Source
164+
- Purpose: $Description
165+
166+
Important Legal and Safety Notes:
167+
- This software is provided by a third party ($Publisher), not by GenXdev or its author (René Vaessen).
168+
- By consenting, you agree to download and install this software at your own risk.
169+
- GenXdev makes no warranties about the software's safety, functionality, or compliance with laws.
170+
- Third-party software may have its own license terms, privacy policies, and potential risks (e.g., security vulnerabilities, data collection).
171+
- You are responsible for reviewing the software's terms and ensuring it meets your needs and legal requirements.
172+
- No liability: The author of GenXdev (René Vaessen) assumes no responsibility for any issues arising from this installation.
173+
174+
Do you consent to install '$ApplicationName'?
175+
- [Y] Yes (this time only)
176+
- [A] Always allow (set persistent preference)
177+
- [N] No (this time only)
178+
- [D] Always deny (set persistent preference)
179+
- [?] Help (more info)
180+
181+
Your choice:
182+
"@
183+
184+
# Display the prompt
185+
Microsoft.PowerShell.Utility\Write-Host $promptMessage -ForegroundColor Yellow
186+
187+
# Get user input
188+
$choice = Microsoft.PowerShell.Utility\Read-Host
189+
$choice = $choice.ToUpper()
190+
191+
switch ($choice) {
192+
'Y' {
193+
Microsoft.PowerShell.Utility\Write-Verbose "User consented for this installation only."
194+
return $true
195+
}
196+
'A' {
197+
try {
198+
# Ensure directory exists
199+
if (-not (Microsoft.PowerShell.Management\Test-Path $consentDir)) {
200+
Microsoft.PowerShell.Management\New-Item -Path $consentDir -ItemType Directory -Force | Microsoft.PowerShell.Core\Out-Null
201+
}
202+
203+
# Load existing data or create new
204+
$consentData = @{}
205+
if (Microsoft.PowerShell.Management\Test-Path $consentFile) {
206+
$consentData = Microsoft.PowerShell.Management\Get-Content $consentFile -Raw | Microsoft.PowerShell.Utility\ConvertFrom-Json -AsHashtable -ErrorAction SilentlyContinue
207+
if (-not $consentData) { $consentData = @{} }
208+
}
209+
210+
# Update and save
211+
$consentData[$preferenceKey] = 'true'
212+
$consentData | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 10 | Microsoft.PowerShell.Management\Set-Content $consentFile -Encoding UTF8
213+
Microsoft.PowerShell.Utility\Write-Verbose "User set persistent allowance for '$ApplicationName'."
214+
} catch {
215+
Microsoft.PowerShell.Utility\Write-Warning "Could not save consent preference: $_"
216+
}
217+
return $true
218+
}
219+
'N' {
220+
Microsoft.PowerShell.Utility\Write-Warning "User denied installation for this time."
221+
return $false
222+
}
223+
'D' {
224+
try {
225+
# Ensure directory exists
226+
if (-not (Microsoft.PowerShell.Management\Test-Path $consentDir)) {
227+
Microsoft.PowerShell.Management\New-Item -Path $consentDir -ItemType Directory -Force | Microsoft.PowerShell.Core\Out-Null
228+
}
229+
230+
# Load existing data or create new
231+
$consentData = @{}
232+
if (Microsoft.PowerShell.Management\Test-Path $consentFile) {
233+
$consentData = Microsoft.PowerShell.Management\Get-Content $consentFile -Raw | Microsoft.PowerShell.Utility\ConvertFrom-Json -AsHashtable -ErrorAction SilentlyContinue
234+
if (-not $consentData) { $consentData = @{} }
235+
}
236+
237+
# Update and save
238+
$consentData[$preferenceKey] = 'false'
239+
$consentData | Microsoft.PowerShell.Utility\ConvertTo-Json -Depth 10 | Microsoft.PowerShell.Management\Set-Content $consentFile -Encoding UTF8
240+
Microsoft.PowerShell.Utility\Write-Warning "User set persistent denial for '$ApplicationName'."
241+
} catch {
242+
Microsoft.PowerShell.Utility\Write-Warning "Could not save consent preference: $_"
243+
}
244+
return $false
245+
}
246+
'?' {
247+
Microsoft.PowerShell.Utility\Write-Host @"
248+
Additional Help:
249+
- Choosing 'Always' options saves your preference to: $consentFile
250+
- You can manually edit the JSON file or delete it to reset all preferences.
251+
- This prompt ensures your explicit consent to avoid any automatic installations.
252+
- The preference key for this application is: $preferenceKey
253+
"@ -ForegroundColor Cyan
254+
255+
# Re-prompt after help
256+
return GenXdev.FileSystem\Confirm-InstallationConsent @PSBoundParameters
257+
}
258+
default {
259+
Microsoft.PowerShell.Utility\Write-Warning "Invalid choice. Treating as denial."
260+
return $false
261+
}
262+
}
263+
}
264+
}

Functions/GenXdev.FileSystem/EnsurePester.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Part of PowerShell module : GenXdev.FileSystem
33
Original cmdlet filename : EnsurePester.ps1
44
Original author : René Vaessen / GenXdev
5-
Version : 1.286.2025
5+
Version : 1.288.2025
66
################################################################################
77
MIT License
88

Functions/GenXdev.FileSystem/Expand-Path.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Part of PowerShell module : GenXdev.FileSystem
33
Original cmdlet filename : Expand-Path.ps1
44
Original author : René Vaessen / GenXdev
5-
Version : 1.286.2025
5+
Version : 1.288.2025
66
################################################################################
77
MIT License
88

Functions/GenXdev.FileSystem/FileExtensionGroups.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,34 @@
1+
// ################################################################################
2+
// Part of PowerShell module : GenXdev.FileSystem
3+
// Original cmdlet filename : FileExtensionGroups.cs
4+
// Original author : René Vaessen / GenXdev
5+
// Version : 1.288.2025
6+
// ################################################################################
7+
// MIT License
8+
//
9+
// Copyright 2021-2025 GenXdev
10+
//
11+
// Permission is hereby granted, free of charge, to any person obtaining a copy
12+
// of this software and associated documentation files (the "Software"), to deal
13+
// in the Software without restriction, including without limitation the rights
14+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15+
// copies of the Software, and to permit persons to whom the Software is
16+
// furnished to do so, subject to the following conditions:
17+
//
18+
// The above copyright notice and this permission notice shall be included in all
19+
// copies or substantial portions of the Software.
20+
//
21+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27+
// SOFTWARE.
28+
// ################################################################################
29+
30+
31+
132
namespace GenXdev.FileSystem
233
{
334
public static class FileGroups

Functions/GenXdev.FileSystem/Find-DuplicateFiles.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Part of PowerShell module : GenXdev.FileSystem
33
Original cmdlet filename : Find-DuplicateFiles.ps1
44
Original author : René Vaessen / GenXdev
5-
Version : 1.286.2025
5+
Version : 1.288.2025
66
################################################################################
77
MIT License
88

Functions/GenXdev.FileSystem/Find-Item.Cmdlet.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Part of PowerShell module : GenXdev.FileSystem
33
// Original cmdlet filename : Find-Item.Cmdlet.cs
44
// Original author : René Vaessen / GenXdev
5-
// Version : 1.286.2025
5+
// Version : 1.288.2025
66
// ################################################################################
77
// MIT License
88
//
@@ -952,16 +952,18 @@ protected override void ProcessRecord()
952952
{
953953
if (string.IsNullOrEmpty(Input)) return;
954954

955-
// add to visited if new and initialize search
956-
if (VisitedNodes.TryAdd("start;" + Input, true))
955+
foreach (var namePart in Input.Split(";"))
957956
{
958-
InitializeSearchDirectory(Input);
959-
}
960-
else if (UseVerboseOutput)
961-
{
962-
963-
// log skipping duplicate mask
964-
WriteWarning($"Skipping duplicate name: {Input}");
957+
// add to visited if new and initialize search
958+
if (VisitedNodes.TryAdd("start;" + namePart, true))
959+
{
960+
InitializeSearchDirectory(namePart);
961+
}
962+
else if (UseVerboseOutput)
963+
{
964+
// log skipping duplicate mask
965+
WriteWarning($"Skipping duplicate name: {namePart}");
966+
}
965967
}
966968
}
967969

Functions/GenXdev.FileSystem/Find-Item.Fields.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Part of PowerShell module : GenXdev.FileSystem
33
// Original cmdlet filename : Find-Item.Fields.cs
44
// Original author : René Vaessen / GenXdev
5-
// Version : 1.286.2025
5+
// Version : 1.288.2025
66
// ################################################################################
77
// MIT License
88
//

0 commit comments

Comments
 (0)