Skip to content

Commit baaba2d

Browse files
committed
Release 1.162.2025
1 parent b4957d4 commit baaba2d

7 files changed

Lines changed: 103 additions & 78 deletions

File tree

Functions/GenXdev.FileSystem/Expand-Path.ps1

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,13 @@ process {
275275
Microsoft.PowerShell.Utility\Write-Verbose "Deleted existing file: $normalizedPath"
276276
}
277277

278+
279+
# clean up trailing separators except for root paths
280+
while ([IO.Path]::EndsInDirectorySeparator($normalizedPath) -and
281+
$normalizedPath.Length -gt 4) {
282+
$normalizedPath = [IO.Path]::TrimEndingDirectorySeparator($normalizedPath)
283+
}
284+
278285
# handle file creation if requested
279286
if ($CreateFile) {
280287

@@ -291,12 +298,6 @@ process {
291298
}
292299
}
293300

294-
# clean up trailing separators except for root paths
295-
while ([IO.Path]::EndsInDirectorySeparator($normalizedPath) -and
296-
$normalizedPath.Length -gt 4) {
297-
$normalizedPath = [IO.Path]::TrimEndingDirectorySeparator($normalizedPath)
298-
}
299-
300301
return $normalizedPath
301302
}
302303

Functions/GenXdev.FileSystem/Remove-AllItems.ps1

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function Remove-AllItems {
7878
}
7979

8080

81-
process {
81+
process {
8282
try {
8383
# skip processing if target directory doesn't exist
8484
if (![System.IO.Directory]::Exists($Path)) {
@@ -124,7 +124,10 @@ process {
124124
Microsoft.PowerShell.Utility\Write-Verbose "Removed root directory: $Path"
125125
}
126126
catch {
127-
$null = GenXdev.FileSystem\Remove-ItemWithFallback -Path $Path
127+
try {
128+
$null = GenXdev.FileSystem\Remove-ItemWithFallback -Path $Path
129+
}
130+
catch {}
128131
}
129132
}
130133
}

Functions/GenXdev.FileSystem/Remove-ItemWithFallback.ps1

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ This ensures maximum reliability when removing items across different providers.
1515
The file or directory path to remove. Can be a filesystem path or provider path.
1616
Accepts pipeline input and wildcards. Must be a valid, non-empty path.
1717
18+
.PARAMETER CountRebootDeletionAsSuccess
19+
If specified, the function returns $true when a file is successfully marked for deletion on reboot.
20+
By default ($false), the function returns $false in this scenario.
21+
1822
.EXAMPLE
1923
Remove-ItemWithFallback -Path "C:\temp\myfile.txt"
2024
Attempts to remove the file using all available methods.
@@ -40,7 +44,12 @@ function Remove-ItemWithFallback {
4044
)]
4145
[ValidateNotNullOrEmpty()]
4246
[Alias("FullName")]
43-
[string]$Path
47+
[string]$Path,
48+
########################################################################
49+
[Parameter(
50+
Mandatory = $false
51+
)]
52+
[switch]$CountRebootDeletionAsSuccess = $false
4453
########################################################################
4554
)
4655

@@ -50,8 +59,7 @@ function Remove-ItemWithFallback {
5059
$Path = GenXdev.FileSystem\Expand-Path $Path
5160
}
5261

53-
54-
process {
62+
process {
5563
try {
5664
# verify item exists and get its provider information
5765
$item = Microsoft.PowerShell.Management\Get-Item -LiteralPath $Path `
@@ -64,16 +72,40 @@ process {
6472

6573
# try fastest method first - direct file deletion
6674
if ([System.IO.File]::Exists($Path)) {
67-
[System.IO.File]::Delete($Path)
68-
Microsoft.PowerShell.Utility\Write-Verbose "Successfully removed file using IO: $Path"
69-
return $true
75+
try {
76+
[System.IO.File]::Delete($Path)
77+
Microsoft.PowerShell.Utility\Write-Verbose "Successfully removed file using IO: $Path"
78+
return $true
79+
}
80+
catch {
81+
# If ErrorAction Stop was specified, immediately rethrow
82+
if (($PSBoundParameters.ContainsKey('ErrorAction') -and $PSBoundParameters['ErrorAction'] -eq 'Stop') -or
83+
$ErrorActionPreference -eq 'Stop') {
84+
throw
85+
}
86+
# Otherwise, fall through to next deletion method
87+
Microsoft.PowerShell.Utility\Write-Verbose "Direct file deletion failed: $_"
88+
# Don't rethrow here - let the code flow to the next deletion method
89+
}
7090
}
7191

7292
# handle directory deletion with recursive option
7393
if ([System.IO.Directory]::Exists($Path)) {
74-
[System.IO.Directory]::Delete($Path, $true)
75-
Microsoft.PowerShell.Utility\Write-Verbose "Successfully removed directory using IO: $Path"
76-
return $true
94+
try {
95+
[System.IO.Directory]::Delete($Path, $true)
96+
Microsoft.PowerShell.Utility\Write-Verbose "Successfully removed directory using IO: $Path"
97+
return $true
98+
}
99+
catch {
100+
# If ErrorAction Stop was specified, immediately rethrow
101+
if (($PSBoundParameters.ContainsKey('ErrorAction') -and $PSBoundParameters['ErrorAction'] -eq 'Stop') -or
102+
$ErrorActionPreference -eq 'Stop') {
103+
throw
104+
}
105+
# Otherwise, fall through to next deletion method
106+
Microsoft.PowerShell.Utility\Write-Verbose "Direct directory deletion failed: $_"
107+
# Don't rethrow here - let the code flow to the next deletion method
108+
}
77109
}
78110
}
79111
}
@@ -90,13 +122,20 @@ process {
90122
catch {
91123
Microsoft.PowerShell.Utility\Write-Verbose "Standard deletion failed, attempting boot-time removal..."
92124

125+
# Check if ErrorAction Stop was specified via parameter or preference variable
126+
if (($PSBoundParameters.ContainsKey('ErrorAction') -and $PSBoundParameters['ErrorAction'] -eq 'Stop') -or
127+
$ErrorActionPreference -eq 'Stop') {
128+
# Rethrow the original exception immediately without trying fallback methods
129+
throw
130+
}
131+
93132
# only try boot-time deletion for filesystem items
94133
if ((Microsoft.PowerShell.Management\Get-Item -LiteralPath $Path).PSProvider.Name -eq 'FileSystem') {
95134

96135
# last resort - mark for deletion on next boot
97136
if (GenXdev.FileSystem\Remove-OnReboot -Path $Path) {
98137
Microsoft.PowerShell.Utility\Write-Verbose "Marked for deletion on next reboot: $Path"
99-
return $true
138+
return [bool]$CountRebootDeletionAsSuccess
100139
}
101140
}
102141

GenXdev.FileSystem.psd1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44
# Generated by: genXdev
55
#
6-
# Generated on: 27/03/2025
6+
# Generated on: 29/03/2025
77
#
88

99
@{
@@ -12,7 +12,7 @@
1212
RootModule = 'GenXdev.FileSystem.psm1'
1313

1414
# Version number of this module.
15-
ModuleVersion = '1.158.2025'
15+
ModuleVersion = '1.162.2025'
1616

1717
# Supported PSEditions
1818
CompatiblePSEditions = 'Core'

README.md

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -104,42 +104,4 @@ Update-Module
104104
# Cmdlets
105105

106106
&nbsp;<hr/>
107-
### GenXdev.FileSystem<hr/>
108-
109-
<br/><hr/><hr/><br/>
110-
111-
112-
<br/><hr/><hr/><br/>
113-
114-
115-
<br/><hr/><hr/><br/>
116-
117-
118-
<br/><hr/><hr/><br/>
119-
120-
121-
<br/><hr/><hr/><br/>
122-
123-
124-
<br/><hr/><hr/><br/>
125-
126-
127-
<br/><hr/><hr/><br/>
128-
129-
130-
<br/><hr/><hr/><br/>
131-
132-
133-
<br/><hr/><hr/><br/>
134-
135-
136-
<br/><hr/><hr/><br/>
137-
138-
139-
<br/><hr/><hr/><br/>
140-
141-
142-
<br/><hr/><hr/><br/>
143-
144-
145-
<br/><hr/><hr/><br/>
107+
### GenXdev.FileSystem<hr/>

Tests/GenXdev.FileSystem/Find-Item.Tests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ $message
328328

329329
Pester\It 'Should match the pattern' {
330330

331-
$found = @(GenXdev.FileSystem\Find-Item -SearchMask "$PSScriptRoot\..\..\..\..\..\**\Genx*stem\1.158.2025\Functions\GenXdev.FileSystem\*.ps1" -PassThru | Microsoft.PowerShell.Utility\Select-Object -ExpandProperty FullName)
331+
$found = @(GenXdev.FileSystem\Find-Item -SearchMask "$PSScriptRoot\..\..\..\..\..\**\Genx*stem\1.162.2025\Functions\GenXdev.FileSystem\*.ps1" -PassThru | Microsoft.PowerShell.Utility\Select-Object -ExpandProperty FullName)
332332

333333
$found | Pester\Should -Contain (GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\Functions\GenXdev.FileSystem\_AssureTypes.ps1")
334334
$found | Pester\Should -Contain (GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\Functions\GenXdev.FileSystem\AssurePester.ps1")
Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
###############################################################################
2-
$Script:testRoot = GenXdev.FileSystem\Expand-Path "$env:TEMP\GenXdev.FileSystem.Tests\" -CreateDirectory
2+
Pester\Describe 'Remove-ItemWithFallback' {
33

4-
Pester\AfterAll {
5-
$Script:testRoot = GenXdev.FileSystem\Expand-Path "$env:TEMP\GenXdev.FileSystem.Tests\" -CreateDirectory
4+
Pester\BeforeAll {
5+
###############################################################################
6+
$testRoot = GenXdev.FileSystem\Expand-Path "$env:TEMP\GenXdev.FileSystem.Tests\" -CreateDirectory
7+
}
68

7-
# cleanup test folder
8-
GenXdev.FileSystem\Remove-AllItems $testRoot -DeleteFolder
9-
}
9+
Pester\AfterAll {
10+
$testRoot = GenXdev.FileSystem\Expand-Path "$env:TEMP\GenXdev.FileSystem.Tests\" -CreateDirectory
1011

11-
###############################################################################
12-
Pester\Describe 'Remove-ItemWithFallback' {
12+
# cleanup test folder
13+
GenXdev.FileSystem\Remove-AllItems $testRoot -DeleteFolder
14+
}
1315

1416
Pester\It "Should pass PSScriptAnalyzer rules" {
17+
1518
# get the script path for analysis
1619
$scriptPath = GenXdev.FileSystem\Expand-Path "$PSScriptRoot\..\..\Functions\GenXdev.FileSystem\Remove-ItemWithFallback.ps1"
1720

@@ -37,25 +40,42 @@ $message
3740
}
3841

3942
Pester\BeforeAll {
40-
Microsoft.PowerShell.Management\Set-Location $Script:testRoot
41-
$Script:testFile = GenXdev.FileSystem\Expand-Path "$Script:testRoot\fallback-test.txt" -CreateFile
42-
Microsoft.PowerShell.Management\Set-Content -Path $Script:testFile -Value "test content"
43-
$Script:lockedFile = [IO.File]::OpenWrite($Script:testFile)
43+
Microsoft.PowerShell.Management\Set-Location "$($testRoot)"
44+
$testFile = GenXdev.FileSystem\Expand-Path "$($testRoot)\fallback-test.txt" -CreateFile
45+
Microsoft.PowerShell.Management\Set-Content -Path $testFile -Value "test content"
46+
$lockedFile = [IO.File]::OpenWrite($testFile)
4447
}
4548

4649
Pester\AfterAll {
47-
if ($Script:lockedFile) {
48-
$Script:lockedFile.Close()
50+
if ($lockedFile) {
51+
$lockedFile.Close()
4952
}
5053

51-
if ([IO.Path]::Exists($Script:testFile)) {
52-
Microsoft.PowerShell.Management\Remove-Item $Script:testFile -Force
54+
if ([IO.Path]::Exists($testFile)) {
55+
Microsoft.PowerShell.Management\Remove-Item $testFile -Force -ErrorAction SilentlyContinue
5356
}
5457
}
5558

5659
Pester\It 'Removes file using direct deletion' {
5760
# Should fail since file is locked
58-
{ GenXdev.FileSystem\Remove-ItemWithFallback -Path $Script:testFile -ErrorAction Stop } | Pester\Should -Throw
59-
Microsoft.PowerShell.Management\Test-Path $Script:testFile | Pester\Should -BeTrue
61+
{ GenXdev.FileSystem\Remove-ItemWithFallback -Path $testFile -ErrorAction Stop } |
62+
Pester\Should -Throw -Because "the file is locked and cannot be deleted"
63+
64+
# File should still exist after failed deletion
65+
Microsoft.PowerShell.Management\Test-Path $testFile | Pester\Should -BeTrue
6066
}
67+
68+
# Pester\It 'Returns false when deletion fails without ErrorAction Stop' {
69+
# # Should return false without throwing when ErrorAction is not Stop
70+
# $result = GenXdev.FileSystem\Remove-ItemWithFallback -Path $testFile -ErrorAction SilentlyContinue
71+
# $result | Pester\Should -BeFalse -Because "immediate deletion fails and CountRebootDeletionAsSuccess is false by default"
72+
# Microsoft.PowerShell.Management\Test-Path $testFile | Pester\Should -BeTrue
73+
# }
74+
75+
# Pester\It 'Returns true when deletion fails but CountRebootDeletionAsSuccess is true' {
76+
# # Should return true when CountRebootDeletionAsSuccess is specified
77+
# $result = GenXdev.FileSystem\Remove-ItemWithFallback -Path $testFile -ErrorAction SilentlyContinue -CountRebootDeletionAsSuccess
78+
# $result | Pester\Should -BeTrue -Because "file is marked for deletion on reboot and CountRebootDeletionAsSuccess is true"
79+
# Microsoft.PowerShell.Management\Test-Path $testFile | Pester\Should -BeTrue
80+
# }
6181
}

0 commit comments

Comments
 (0)