WinDirOps.psm1
#Region './Classes/FolderDeletionResult.ps1' -1 class FolderDeletionResult { [string]$FolderPath [bool]$DeletionSuccess [string]$DeletionMessage [string]$ComputerName # Constructor to initialize the properties FolderDeletionResult([string]$folderPath, [bool]$deletionSuccess, [string]$deletionMessage, [string]$computerName) { $this.FolderPath = $folderPath $this.DeletionSuccess = $deletionSuccess $this.DeletionMessage = $deletionMessage $this.ComputerName = $computerName } } #EndRegion './Classes/FolderDeletionResult.ps1' 15 #Region './Private/Invoke-RoboCopyCommand.ps1' -1 <# .SYNOPSIS Executes the Robocopy command to copy or mirror directories. .DESCRIPTION This function runs the Robocopy utility to mirror or copy files from a source directory to a target directory. You can pass additional Robocopy parameters to customize the operation, with /mir (mirror) being the default. .PARAMETER SourceDirectory The path to the source directory that will be copied or mirrored to the target directory. .PARAMETER TargetDirectory The path to the target directory where the source directory's contents will be copied or mirrored. .PARAMETER AdditionalParams Optional parameters to customize the Robocopy operation. Defaults to /mir (mirror), but you can specify other parameters such as /e, /r:5, /w:10, etc. .EXAMPLE Invoke-RobocopyCommand -SourceDirectory "C:\Source" -TargetDirectory "C:\Target" Mirrors the contents of C:\Source to C:\Target using the default /mir parameter. .EXAMPLE Invoke-RobocopyCommand -SourceDirectory "C:\Source" -TargetDirectory "C:\Target" -AdditionalParams @("/e", "/r:2", "/w:5") Copies all files from C:\Source to C:\Target, including empty directories (/e), with a retry count of 2 (/r:2) and a wait time of 5 seconds between retries (/w:5). .NOTES RoboCopy exit codes: - 0: No files were copied. - 1: One or more files were copied successfully. - 8: Some files or directories could not be copied (failure). - 16: Fatal error (failure). The function returns the exit code from Robocopy. .LINK https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy #> function Invoke-RobocopyCommand { param ( [Parameter(Mandatory = $true)] [string]$SourceDirectory, [Parameter(Mandatory = $true)] [string]$TargetDirectory, [string[]]$AdditionalParams = @() # Default to /mir ) # Build the robocopy command with parameters $robocopyArgs = @($SourceDirectory, $TargetDirectory) + $AdditionalParams # Call robocopy directly $result = robocopy @robocopyArgs return $result } #EndRegion './Private/Invoke-RoboCopyCommand.ps1' 62 #Region './Private/New-FolderDeletionResult.ps1' -1 <# .SYNOPSIS Creates a new FolderDeletionResult object. .DESCRIPTION The `New-FolderDeletionResult` function creates and returns a new `FolderDeletionResult` object, which contains information about the deletion of a directory, including the directory path, whether the deletion was successful, a message about the result, and the computer name on which the deletion took place. .PARAMETER Directory The path of the directory that was being deleted. .PARAMETER DeletionSuccess A boolean value indicating whether the deletion was successful. `$true` if the deletion was successful, `$false` otherwise. .PARAMETER DeletionMessage A message describing the result of the deletion process. .PARAMETER ComputerName The name of the computer where the directory deletion occurred. .EXAMPLE $result = New-FolderDeletionResult -Directory "C:\Temp\OldData" -DeletionSuccess $true -DeletionMessage "Successfully deleted." -ComputerName "LocalHost" This example creates a `FolderDeletionResult` object with information about the successful deletion of the "C:\Temp\OldData" directory on the local computer "LocalHost". .EXAMPLE $result = New-FolderDeletionResult -Directory "D:\RemoteData" -DeletionSuccess $false -DeletionMessage "Failed to delete." -ComputerName "RemotePC" This example creates a `FolderDeletionResult` object with information about the failed deletion of the "D:\RemoteData" directory on the remote computer "RemotePC". .NOTES This function is used to encapsulate the result of a directory deletion operation, providing a structured way to handle and return the outcome of such operations. #> function New-FolderDeletionResult { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseShouldProcessForStateChangingFunctions", "")] param ( [Parameter(Mandatory = $true)] [string]$Directory, [Parameter(Mandatory = $true)] [bool]$DeletionSuccess, [Parameter(Mandatory = $true)] [string]$DeletionMessage, [Parameter(Mandatory = $true)] [string]$ComputerName ) return [FolderDeletionResult]::new( $Directory, $DeletionSuccess, $DeletionMessage, $ComputerName ) } #EndRegion './Private/New-FolderDeletionResult.ps1' 65 #Region './Public/Clear-Directory.ps1' -1 <# .SYNOPSIS Deletes a specified directory on the local or remote computer. .DESCRIPTION This function attempts to delete an entire directory and its contents either on the local or a remote computer. It determines whether the operation is local or remote using the `ComputerName` parameter. Internally, it delegates to `Remove-DirectoryByType` to handle the deletion, making this a high-level function for directory deletion on any machine. .PARAMETER Directory The path of the directory to be deleted. .PARAMETER ComputerName The name of the computer where the directory resides. Defaults to the local computer. .EXAMPLE Clear-Directory -Directory "C:\Temp\Logs" This example deletes the "C:\Temp\Logs" directory on the local machine. .EXAMPLE Clear-Directory -Directory "D:\OldFiles" -ComputerName "RemotePC" This example deletes the "D:\OldFiles" directory on a remote computer named "RemotePC". .NOTES This function determines whether the operation is local or remote and uses the appropriate function (either `Remove-LocalDirectory` or `Remove-RemoteDirectory`) to perform the deletion. It supports `-WhatIf` and `-Confirm` for previewing or confirming the operation. #> function Clear-Directory { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(ValueFromPipeline = $true, Mandatory = $true)] [string]$Directory, [Parameter(ValueFromPipelineByPropertyName = $true)] [string]$ComputerName = $env:COMPUTERNAME # Default to local computer ) process { if ($PSCmdlet.ShouldProcess($Directory, "Delete directory on $ComputerName")) { $result = Remove-DirectoryByType -Directory $Directory -ComputerName $ComputerName -Confirm:$false Write-Information -MessageData $result.DeletionMessage -Tags "DeleteOperation" return $result } } } #EndRegion './Public/Clear-Directory.ps1' 54 #Region './Public/Clear-DirectoryContents.ps1' -1 <# .SYNOPSIS Clears only the contents of a directory without deleting the directory itself. .DESCRIPTION This function clears the contents of a directory by mirroring it with an empty temporary directory. It does not delete the directory itself but removes all files and subfolders within the specified directory. It uses `Invoke-MirRoboCopy` to sync an empty directory with the target directory, effectively clearing it. .PARAMETER Directory The path of the directory whose contents will be cleared. .EXAMPLE Clear-DirectoryContents -Directory "C:\Temp\OldData" Clears the contents in the "C:\Temp\OldData" directory but does not remove the directory itself. .NOTES This function is for clearing the contents of a directory while preserving the directory itself. To delete both the directory and its contents, use `Clear-Directory` or `Remove-DirectoryByType`. #> function Clear-DirectoryContents { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")] [OutputType([System.Boolean])] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$Directory ) try { # Create a temporary empty directory $emptyDir = [System.IO.Path]::GetTempPath() + [System.Guid]::NewGuid().ToString() mkdir $emptyDir | Out-Null if ($PSCmdlet.ShouldProcess($Directory, "Clear directory contents")) { # Use Invoke-MirRoboCopy to fast-delete the directory contents by syncing an empty directory $syncSuccess = Invoke-MirRoboCopy -SourceDirectory $emptyDir -TargetDirectory $Directory -confirm:$false if ($syncSuccess) { # Remove the target directory after clearing its contents Remove-Item -Path $Directory -Recurse -Force -ErrorAction SilentlyContinue Remove-Item -Path $emptyDir -Recurse -Force -ErrorAction SilentlyContinue return $true } else { return $false } } } catch { Write-Error "Failed to clear directory contents for $Directory. Error: $_" return $false } } #EndRegion './Public/Clear-DirectoryContents.ps1' 63 #Region './Public/Invoke-MirRoboCopy.ps1' -1 <# .SYNOPSIS Mirrors the contents of a source directory to a target directory using RoboCopy. .DESCRIPTION This function mirrors the contents of a source directory to a target directory using the RoboCopy utility. It ensures that the contents of the target directory exactly match the source directory by syncing them. .PARAMETER SourceDirectory The path of the source directory whose contents will be mirrored to the target directory. .PARAMETER TargetDirectory The path of the target directory where the source directory contents will be mirrored. .EXAMPLE Invoke-MirRoboCopy -SourceDirectory "C:\SourceFolder" -TargetDirectory "C:\TargetFolder" Mirrors the contents of "C:\SourceFolder" to "C:\TargetFolder". .NOTES This function is a low-level utility used by other functions like `Clear-DirectoryContents` to handle the mirroring operation. RoboCopy exit codes: 0 = No files were copied 1 = One or more files were copied successfully (even if some files were skipped) 8 = Some files or directories could not be copied (failure) 16 = Fatal error (failure) Exit codes 8 and higher are considered failures in this function. #> function Invoke-MirRoboCopy { [OutputType([System.Boolean])] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$SourceDirectory, [Parameter(Mandatory = $true)] [string]$TargetDirectory ) try { # Validate that the source directory exists if (-not (Test-Path -Path $SourceDirectory -PathType Container)) { throw "Source directory '$SourceDirectory' does not exist." } # Validate that the target directory exists if (-not (Test-Path -Path $TargetDirectory -PathType Container)) { throw "Target directory '$TargetDirectory' does not exist." } if ($PSCmdlet.ShouldProcess($TargetDirectory, "Mirror directory from '$SourceDirectory'")) { # Use robocopy to mirror the source directory to the target directory $result = Invoke-RoboCopyCommand -SourceDirectory $SourceDirectory -TargetDirectory $TargetDirectory -AdditionalParams '/mir' # Check robocopy result if ($result -ge 8) { throw "RoboCopy encountered a failure with code $result." } return $true } } catch { Write-Error "RoboCopy failed from '$SourceDirectory' to '$TargetDirectory'. Error: $_" return $false } } #EndRegion './Public/Invoke-MirRoboCopy.ps1' 79 #Region './Public/Remove-DirectoryByType.ps1' -1 <# .SYNOPSIS Deletes a directory either locally or remotely based on the computer name provided. .DESCRIPTION This function deletes a directory either on the local machine or a remote machine depending on the computer name provided. It determines whether the operation is local or remote and calls the appropriate function (either `Remove-LocalDirectory` or `Remove-RemoteDirectory`). It supports `-WhatIf` and `-Confirm` to allow users to preview or confirm the deletion before it is performed. .PARAMETER Directory The path of the directory to be deleted. .PARAMETER ComputerName The name of the computer where the directory resides. Defaults to the local computer. .EXAMPLE Remove-DirectoryByType -Directory "C:\Temp\Logs" Deletes the directory "C:\Temp\Logs" from the local machine. .NOTES This function determines whether the directory is on the local or remote computer and uses the appropriate method to delete it. #> function Remove-DirectoryByType { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$Directory, [Parameter(Mandatory = $false)] [string]$ComputerName = $env:COMPUTERNAME ) $isLocal = $ComputerName -eq $env:COMPUTERNAME if ($PSCmdlet.ShouldProcess("$ComputerName': $Directory", "Delete directory by type")) { if ($isLocal) { return Remove-LocalDirectory -Directory $Directory -confirm:$false } else { return Remove-RemoteDirectory -Directory $Directory -ComputerName $ComputerName -confirm:$false } } } #EndRegion './Public/Remove-DirectoryByType.ps1' 52 #Region './Public/Remove-LocalDirectory.ps1' -1 <# .SYNOPSIS Deletes a local directory and its contents. .DESCRIPTION This function deletes a specified directory on the local computer. It first clears the contents of the directory and then removes the directory itself. .PARAMETER Directory The path of the local directory to be deleted. .EXAMPLE Remove-LocalDirectory -Directory "C:\Temp\OldData" Deletes the "C:\Temp\OldData" directory and its contents on the local machine. .NOTES This function works only on local directories. For remote directories, use `Remove-RemoteDirectory`. #> function Remove-LocalDirectory { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$Directory ) try { if ($PSCmdlet.ShouldProcess($Directory, "Delete local directory")) { $deletionInfo = @{ Directory = $Directory ComputerName = $env:COMPUTERNAME } if (Clear-DirectoryContents -Directory $Directory -Confirm:$false) { $deletionInfo.DeletionSuccess = $true $deletionInfo.DeletionMessage = "Successfully deleted local directory '$Directory'." } else { $deletionInfo.DeletionSuccess = $false $deletionInfo.DeletionMessage = "Failed to delete local directory '$Directory'." } return New-FolderDeletionResult @deletionInfo } } catch { $deletionInfo = @{ Directory = $Directory DeletionSuccess = $false DeletionMessage = "Error occurred while deleting local directory '$Directory'. $_" ComputerName = $env:COMPUTERNAME } return New-FolderDeletionResult @deletionInfo } } #EndRegion './Public/Remove-LocalDirectory.ps1' 63 #Region './Public/Remove-RemoteDirectory.ps1' -1 <# .SYNOPSIS Deletes a remote directory and its contents. .DESCRIPTION This function deletes a directory and its contents on a remote computer. It sends a script block to the remote computer to clear the directory contents using `Clear-DirectoryContents`, then deletes the directory itself. .PARAMETER Directory The path of the remote directory to be deleted. .PARAMETER ComputerName The name of the remote computer where the directory is located. .EXAMPLE Remove-RemoteDirectory -Directory "D:\OldFiles" -ComputerName "RemotePC" Deletes the "D:\OldFiles" directory and its contents on the remote computer "RemotePC". .NOTES This function is specifically for remote directories. Use `Remove-LocalDirectory` for local directory deletions. #> function Remove-RemoteDirectory { [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param ( [Parameter(Mandatory = $true)] [string]$Directory, [Parameter(Mandatory = $true)] [string]$ComputerName ) # Check if the remote computer is online if (-not (Test-ComputerPing -ComputerName $ComputerName)) { $deletionInfo = @{ Directory = $Directory DeletionSuccess = $false DeletionMessage = "The remote computer '$ComputerName' is offline or unreachable." ComputerName = $ComputerName } return New-FolderDeletionResult @deletionInfo } # Get the script blocks for Clear-DirectoryContents and Invoke-MirRoboCopy functions $clearDirectoryFunction = Get-FunctionScriptBlock -FunctionName 'Clear-DirectoryContents' $invokeMirRoboCopyFunction = Get-FunctionScriptBlock -FunctionName 'Invoke-MirRoboCopy' if (-not $clearDirectoryFunction -or -not $invokeMirRoboCopyFunction) { Write-Error "Unable to retrieve required functions." return } $scriptBlock = { param ($remoteDirectory, $clearFunction, $roboCopyFunction) # Define the functions from the passed strings & $clearFunction & $roboCopyFunction # Call the Clear-DirectoryContents function if (Clear-DirectoryContents -Directory $remoteDirectory -Confirm:$false) { return @{ Directory = $remoteDirectory Success = $true Message = "Successfully deleted remote directory '$remoteDirectory'." ComputerName = $env:COMPUTERNAME } } else { return @{ Directory = $remoteDirectory Success = $false Message = "Failed to delete remote directory '$remoteDirectory'." ComputerName = $env:COMPUTERNAME } } } try { if ($PSCmdlet.ShouldProcess("$ComputerName`: $Directory", "Delete remote directory")) { # Execute the script block on the remote machine $rawResult = Invoke-Command -ComputerName $ComputerName -ScriptBlock $scriptBlock -ArgumentList $Directory, $clearDirectoryFunction, $invokeMirRoboCopyFunction $deletionInfo = @{ Directory = $rawResult.Directory DeletionSuccess = $rawResult.Success DeletionMessage = $rawResult.Message ComputerName = $rawResult.ComputerName } return New-FolderDeletionResult @deletionInfo } } catch { $deletionInfo = @{ Directory = $Directory DeletionSuccess = $false DeletionMessage = "Error occurred while deleting remote directory '$Directory'. $_" ComputerName = $ComputerName } return New-FolderDeletionResult @deletionInfo } } #EndRegion './Public/Remove-RemoteDirectory.ps1' 114 |