bc3dd6c535
Deploys a fully preconfigured OPNsense appliance into a Hyper-V lab in a single execution, re-running safely because every stage detects the current state before it acts. Main script: - Hyper-V platform detection and installation, exiting 3010 only when the hypervisor itself needs a restart - Random /20 block selection out of a private base network, divided into /24 networks whose VLAN tag is the third octet of their own network address - Zone based roles, with five server zones paired by index to five client zones, plus Management, Infrastructure, DMZ, Storage and Guest - Generated OPNsense config.xml delivered on a FAT32 VHDX at conf/config.xml - Generation 2 virtual machine with secure boot disabled and a LAN trunk carrying VLANs 1-4094 - Marker scoped teardown via RemoveExistingDeployment Toolkit functions: - Save-ToolkitModule, Install-HyperVPlatform, Test-PendingReboot - Expand-CompressedFile, Get-OPNSenseInstallationMedia - Get-HyperVStorageLocation, Get-HostUpstreamDNSConfiguration - New-RandomPassword, New-OPNSensePasswordHash - New-OPNSenseNetworkPlan, New-OPNSenseConfigurationDocument, Save-OPNSenseConfigurationDocument, New-OPNSenseConfigurationDisk - Initialize-OPNSenseVirtualSwitch, New-OPNSenseVirtualMachine, Remove-OPNSenseDeployment Configuration document covers interfaces, VLANs, Kea DHCPv4 scopes with PXE options, Unbound, outbound NAT, six firewall aliases and an ordered rule set that grants management full reach, allows the jump hosts over well known management ports, forces name resolution to approved resolvers, and pairs the client and server zones. Bundles 7-Zip, because the tar.exe included with Windows cannot read a raw bzip2 stream, and BCrypt.Net-Next for the appliance password hash. docs: Add readme with execution flow and generated per function reference docs: Add design specification under .ai/specification Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
474 lines
28 KiB
PowerShell
474 lines
28 KiB
PowerShell
#region Expand-CompressedFile
|
|
Function Expand-CompressedFile
|
|
{
|
|
<#
|
|
.SYNOPSIS
|
|
Expands a compressed file or archive using the first available extraction provider.
|
|
|
|
.DESCRIPTION
|
|
The extraction provider is selected based upon the archive format and the tooling that is available on the device.
|
|
|
|
1. 7-Zip - "Toolkit\Tools\<Architecture>\7z.exe" is preferred, followed by any copy of "7z.exe" or "7za.exe" that is available within the process path, followed by the installed copy within the program files directory. This provider handles every supported format, including a raw bzip2 stream such as an OPNsense disc image.
|
|
2. BSDTar - "tar.exe" is included with the operating system, but it can only read genuine tar archives. It is the only provider that natively supports the removal of leading path components.
|
|
3. .NET - The "System.IO.Compression" namespace is used for zip archives and raw gzip streams.
|
|
|
|
Extraction always occurs within a staging directory so that the leading path component removal and the inclusion filter can be applied before anything is placed into the destination directory.
|
|
|
|
.PARAMETER Path
|
|
A valid file path to the compressed file or archive that will be expanded.
|
|
|
|
.PARAMETER Destination
|
|
A valid folder path. If the folder does not exist, it will be created.
|
|
|
|
.PARAMETER StripComponents
|
|
The number of leading path components to remove from each extracted item. This is the equivalent of the tar "--strip-components" argument and allows a single nested item, such as a disc image, to be placed directly within the destination directory.
|
|
|
|
.PARAMETER IncludeFilter
|
|
One or more wildcard expressions. Only the extracted items whose name matches one of the expressions will be placed into the destination directory.
|
|
|
|
.PARAMETER Force
|
|
Overwrite any item that already exists within the destination directory.
|
|
|
|
.PARAMETER ContinueOnError
|
|
Ignore failures.
|
|
|
|
.EXAMPLE
|
|
$ExpandCompressedFileParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$ExpandCompressedFileParameters.Path = "$($ContentDirectory.FullName)\ISOs\OPNsense-26.1.6-dvd-amd64.iso.bz2"
|
|
$ExpandCompressedFileParameters.Destination = "$($ContentDirectory.FullName)\ISOs"
|
|
$ExpandCompressedFileParameters.StripComponents = 1
|
|
$ExpandCompressedFileParameters.IncludeFilter = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$ExpandCompressedFileParameters.IncludeFilter.Add('*.iso')
|
|
$ExpandCompressedFileParameters.Verbose = $True
|
|
|
|
$ExpandCompressedFileResult = Expand-CompressedFile @ExpandCompressedFileParameters
|
|
|
|
Write-Output -InputObject ($ExpandCompressedFileResult.ItemList)
|
|
|
|
.NOTES
|
|
The copy of "tar.exe" that is included with the operating system cannot read a raw, non-tar bzip2 stream. It fails with "Unrecognized archive format", which is the reason that 7-Zip is bundled within the toolkit.
|
|
|
|
.LINK
|
|
https://learn.microsoft.com/en-us/windows/win32/wsw/tar
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
Param
|
|
(
|
|
[Parameter(Mandatory=$True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('P')]
|
|
[System.IO.FileInfo]$Path,
|
|
|
|
[Parameter(Mandatory=$True)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('D')]
|
|
[System.IO.DirectoryInfo]$Destination,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateRange(0, 16)]
|
|
[Alias('SC')]
|
|
[System.Int32]$StripComponents,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[ValidateNotNullOrEmpty()]
|
|
[Alias('IF')]
|
|
[System.String[]]$IncludeFilter,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[Alias('F')]
|
|
[Switch]$Force,
|
|
|
|
[Parameter(Mandatory=$False)]
|
|
[Alias('COE')]
|
|
[Switch]$ContinueOnError
|
|
)
|
|
|
|
Try
|
|
{
|
|
[System.String]$CmdletName = $MyInvocation.MyCommand.Name
|
|
|
|
$WriteLogMessage.Invoke(0, @("Function `'$($CmdletName)`' is beginning. Please Wait..."))
|
|
|
|
#region Set default parameter value(s)
|
|
Switch ($True)
|
|
{
|
|
{($Null -ieq $IncludeFilter) -or ($IncludeFilter.Count -eq 0)}
|
|
{
|
|
[System.String[]]$IncludeFilter = @('*')
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
Switch ([System.IO.File]::Exists($Path.FullName))
|
|
{
|
|
{($_ -eq $False)}
|
|
{
|
|
Throw "The compressed file `"$($Path.FullName)`" does not exist."
|
|
}
|
|
}
|
|
|
|
Switch ([System.IO.Directory]::Exists($Destination.FullName))
|
|
{
|
|
{($_ -eq $False)}
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Attempting to create the non-existing destination directory. Please Wait... [Path: $($Destination.FullName)]"))
|
|
|
|
$Null = [System.IO.Directory]::CreateDirectory($Destination.FullName)
|
|
}
|
|
}
|
|
|
|
$OutputObjectProperties = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$OutputObjectProperties.Path = $Path
|
|
$OutputObjectProperties.Destination = $Destination
|
|
$OutputObjectProperties.Provider = $Null
|
|
$OutputObjectProperties.ItemList = New-Object -TypeName 'System.Collections.Generic.List[System.IO.FileInfo]'
|
|
$OutputObjectProperties.Duration = $Null
|
|
|
|
$FunctionStartTime = [System.DateTime]::UtcNow
|
|
|
|
#region Determine the archive format
|
|
[Boolean]$IsTarArchive = $Path.Name -imatch '(\.tar$)|(\.tar\.(bz2|gz|xz|zst|lz|lzma)$)|(\.(tbz2|tbz|tgz|txz|tzst)$)'
|
|
[Boolean]$IsZipArchive = $Path.Extension -imatch '(^\.zip$)'
|
|
[Boolean]$IsGzipStream = (($Path.Extension -imatch '(^\.gz$)') -and ($IsTarArchive -eq $False))
|
|
|
|
$WriteLogMessage.Invoke(0, @("Compressed File: $($Path.FullName)"))
|
|
|
|
$WriteLogMessage.Invoke(0, @("Compressed File Size: $([System.Math]::Round($Path.Length / 1MB, 2)) MB"))
|
|
|
|
$WriteLogMessage.Invoke(0, @("[Is Tar Archive: $($IsTarArchive)] [Is Zip Archive: $($IsZipArchive)] [Is Gzip Stream: $($IsGzipStream)]"))
|
|
#endregion
|
|
|
|
#region Locate the available extraction tooling
|
|
[ScriptBlock]$ResolveExtractionTool = {
|
|
Param
|
|
(
|
|
[System.String[]]$ExecutableNameList
|
|
)
|
|
|
|
$ResolvedPath = $Null
|
|
|
|
$SearchDirectoryList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
|
|
Switch ($Null -ine $ToolsDirectory_OSArchSpecific)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SearchDirectoryList.Add($ToolsDirectory_OSArchSpecific.FullName)
|
|
}
|
|
}
|
|
|
|
Switch ($Null -ine $ToolsDirectory_OSAll)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$SearchDirectoryList.Add($ToolsDirectory_OSAll.FullName)
|
|
}
|
|
}
|
|
|
|
$SearchDirectoryList.Add([System.IO.Path]::Combine("$($Env:ProgramFiles)", '7-Zip'))
|
|
$SearchDirectoryList.Add([System.IO.Path]::Combine("$(${Env:ProgramFiles(x86)})", '7-Zip'))
|
|
$SearchDirectoryList.Add("$([System.Environment]::SystemDirectory)")
|
|
|
|
:ExecutableNameListLoop ForEach ($ExecutableName In $ExecutableNameList)
|
|
{
|
|
ForEach ($SearchDirectory In $SearchDirectoryList)
|
|
{
|
|
$CandidatePath = [System.IO.FileInfo][System.IO.Path]::Combine("$($SearchDirectory)", "$($ExecutableName)")
|
|
|
|
Switch ([System.IO.File]::Exists($CandidatePath.FullName))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$ResolvedPath = $CandidatePath
|
|
|
|
Break ExecutableNameListLoop
|
|
}
|
|
}
|
|
}
|
|
|
|
$CommandDetails = Try {Get-Command -Name ($ExecutableName) -CommandType 'Application' -ErrorAction SilentlyContinue | Select-Object -First 1} Catch {$Null}
|
|
|
|
Switch ($Null -ine $CommandDetails)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$ResolvedPath = [System.IO.FileInfo]$CommandDetails.Source
|
|
|
|
Break ExecutableNameListLoop
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Output -InputObject ($ResolvedPath)
|
|
}
|
|
|
|
$SevenZipPath = $ResolveExtractionTool.InvokeReturnAsIs(@('7z.exe', '7za.exe', '7z', '7za'))
|
|
$BSDTarPath = $ResolveExtractionTool.InvokeReturnAsIs(@('tar.exe', 'tar'))
|
|
|
|
[System.String]$SevenZipPathMessage = 'N/A'
|
|
[System.String]$BSDTarPathMessage = 'N/A'
|
|
|
|
Switch ($True)
|
|
{
|
|
{($Null -ine $SevenZipPath)}
|
|
{
|
|
[System.String]$SevenZipPathMessage = $SevenZipPath.FullName
|
|
}
|
|
|
|
{($Null -ine $BSDTarPath)}
|
|
{
|
|
[System.String]$BSDTarPathMessage = $BSDTarPath.FullName
|
|
}
|
|
}
|
|
|
|
$WriteLogMessage.Invoke(0, @("7-Zip Path: $($SevenZipPathMessage)", "BSDTar Path: $($BSDTarPathMessage)"))
|
|
#endregion
|
|
|
|
#region Create the staging directory
|
|
$StagingDirectory = [System.IO.DirectoryInfo][System.IO.Path]::Combine($Destination.FullName, "Expand_$($GetRandomGUID.InvokeReturnAsIs())")
|
|
|
|
$Null = [System.IO.Directory]::CreateDirectory($StagingDirectory.FullName)
|
|
|
|
$WriteLogMessage.Invoke(0, @("Staging Directory: $($StagingDirectory.FullName)"))
|
|
#endregion
|
|
|
|
#region Expand the compressed file using the first suitable provider
|
|
[Boolean]$StripComponentsWasApplied = $False
|
|
|
|
Switch ($True)
|
|
{
|
|
{($IsTarArchive -eq $True) -and ($Null -ine $BSDTarPath)}
|
|
{
|
|
$OutputObjectProperties.Provider = 'BSDTar'
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to expand the archive using the `"$($OutputObjectProperties.Provider)`" provider. Please Wait..."))
|
|
|
|
$ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$ArgumentList.Add('-x')
|
|
$ArgumentList.Add('-f')
|
|
$ArgumentList.Add("`"$($Path.FullName)`"")
|
|
$ArgumentList.Add('-C')
|
|
$ArgumentList.Add("`"$($StagingDirectory.FullName)`"")
|
|
|
|
Switch ($StripComponents -gt 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$ArgumentList.Add("--strip-components=$($StripComponents)")
|
|
|
|
$StripComponentsWasApplied = $True
|
|
}
|
|
}
|
|
|
|
$StartProcessWithOutputParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$StartProcessWithOutputParameters.FilePath = $BSDTarPath.FullName
|
|
$StartProcessWithOutputParameters.WorkingDirectory = $StagingDirectory.FullName
|
|
$StartProcessWithOutputParameters.ArgumentList = $ArgumentList.ToArray()
|
|
$StartProcessWithOutputParameters.AcceptableExitCodeList = @('0')
|
|
$StartProcessWithOutputParameters.CreateNoWindow = $True
|
|
$StartProcessWithOutputParameters.ExecutionTimeout = [System.TimeSpan]::FromMinutes(30)
|
|
$StartProcessWithOutputParameters.ExecutionTimeoutInterval = [System.TimeSpan]::FromSeconds(30)
|
|
$StartProcessWithOutputParameters.Verbose = $False
|
|
|
|
$Null = Start-ProcessWithOutput @StartProcessWithOutputParameters
|
|
|
|
Break
|
|
}
|
|
|
|
{($IsZipArchive -eq $True)}
|
|
{
|
|
$OutputObjectProperties.Provider = 'DotNetZipFile'
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to expand the archive using the `"$($OutputObjectProperties.Provider)`" provider. Please Wait..."))
|
|
|
|
$Null = Add-Type -AssemblyName 'System.IO.Compression.FileSystem' -IgnoreWarnings -Verbose:$False -ErrorAction SilentlyContinue
|
|
|
|
$Null = [System.IO.Compression.ZipFile]::ExtractToDirectory($Path.FullName, $StagingDirectory.FullName)
|
|
|
|
Break
|
|
}
|
|
|
|
{($Null -ine $SevenZipPath)}
|
|
{
|
|
$OutputObjectProperties.Provider = 'SevenZip'
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to expand the archive using the `"$($OutputObjectProperties.Provider)`" provider. Please Wait..."))
|
|
|
|
$ArgumentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$ArgumentList.Add('x')
|
|
$ArgumentList.Add("`"$($Path.FullName)`"")
|
|
$ArgumentList.Add("-o`"$($StagingDirectory.FullName)`"")
|
|
$ArgumentList.Add('-y')
|
|
$ArgumentList.Add('-bso0')
|
|
$ArgumentList.Add('-bsp0')
|
|
|
|
$StartProcessWithOutputParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary'
|
|
$StartProcessWithOutputParameters.FilePath = $SevenZipPath.FullName
|
|
$StartProcessWithOutputParameters.WorkingDirectory = $StagingDirectory.FullName
|
|
$StartProcessWithOutputParameters.ArgumentList = $ArgumentList.ToArray()
|
|
$StartProcessWithOutputParameters.AcceptableExitCodeList = @('0', '1')
|
|
$StartProcessWithOutputParameters.CreateNoWindow = $True
|
|
$StartProcessWithOutputParameters.ExecutionTimeout = [System.TimeSpan]::FromMinutes(30)
|
|
$StartProcessWithOutputParameters.ExecutionTimeoutInterval = [System.TimeSpan]::FromSeconds(30)
|
|
$StartProcessWithOutputParameters.Verbose = $False
|
|
|
|
$Null = Start-ProcessWithOutput @StartProcessWithOutputParameters
|
|
|
|
Break
|
|
}
|
|
|
|
{($IsGzipStream -eq $True)}
|
|
{
|
|
$OutputObjectProperties.Provider = 'DotNetGZipStream'
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to expand the archive using the `"$($OutputObjectProperties.Provider)`" provider. Please Wait..."))
|
|
|
|
$ExpandedFilePath = [System.IO.FileInfo][System.IO.Path]::Combine($StagingDirectory.FullName, $Path.BaseName)
|
|
|
|
$InputStream = [System.IO.File]::OpenRead($Path.FullName)
|
|
$OutputStream = [System.IO.File]::Create($ExpandedFilePath.FullName)
|
|
$DecompressionStream = New-Object -TypeName 'System.IO.Compression.GZipStream' -ArgumentList @($InputStream, [System.IO.Compression.CompressionMode]::Decompress)
|
|
|
|
$Null = $DecompressionStream.CopyTo($OutputStream)
|
|
|
|
$Null = Try {$DecompressionStream.Dispose()} Catch {}
|
|
$Null = Try {$OutputStream.Dispose()} Catch {}
|
|
$Null = Try {$InputStream.Dispose()} Catch {}
|
|
|
|
Break
|
|
}
|
|
|
|
Default
|
|
{
|
|
Throw "An extraction provider capable of expanding `"$($Path.Name)`" could not be located. Place a copy of `"7z.exe`" and `"7z.dll`" within `"$($ToolsDirectory_OSArchSpecific.FullName)`" and try again."
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Remove the requested number of leading path components
|
|
Switch (($StripComponents -gt 0) -and ($StripComponentsWasApplied -eq $False))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Attempting to remove $($StripComponents) leading path component(s) from each expanded item. Please Wait..."))
|
|
|
|
$StagedItemList = [System.IO.Directory]::GetFiles($StagingDirectory.FullName, '*', [System.IO.SearchOption]::AllDirectories)
|
|
|
|
For ($StagedItemListIndex = 0; $StagedItemListIndex -lt $StagedItemList.Count; $StagedItemListIndex++)
|
|
{
|
|
$StagedItem = [System.IO.FileInfo]$StagedItemList[$StagedItemListIndex]
|
|
|
|
[System.String]$RelativePath = $StagedItem.FullName.Substring($StagingDirectory.FullName.Length).TrimStart([System.IO.Path]::DirectorySeparatorChar, [System.IO.Path]::AltDirectorySeparatorChar)
|
|
|
|
$RelativePathSegmentList = New-Object -TypeName 'System.Collections.Generic.List[System.String]'
|
|
$RelativePathSegmentList.AddRange([System.String[]]($RelativePath -isplit '[\\\/]'))
|
|
|
|
Switch ($RelativePathSegmentList.Count -gt $StripComponents)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$Null = $RelativePathSegmentList.RemoveRange(0, $StripComponents)
|
|
|
|
$StrippedItemPath = [System.IO.FileInfo][System.IO.Path]::Combine($StagingDirectory.FullName, ($RelativePathSegmentList -Join [System.IO.Path]::DirectorySeparatorChar))
|
|
|
|
Switch ([System.IO.Directory]::Exists($StrippedItemPath.Directory.FullName))
|
|
{
|
|
{($_ -eq $False)}
|
|
{
|
|
$Null = [System.IO.Directory]::CreateDirectory($StrippedItemPath.Directory.FullName)
|
|
}
|
|
}
|
|
|
|
$Null = [System.IO.File]::Move($StagedItem.FullName, $StrippedItemPath.FullName)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Move the requested item(s) into the destination directory
|
|
$ExpandedItemList = [System.IO.Directory]::GetFiles($StagingDirectory.FullName, '*', [System.IO.SearchOption]::AllDirectories)
|
|
|
|
$WriteLogMessage.Invoke(0, @("$(($ExpandedItemList | Measure-Object).Count) item(s) were expanded into the staging directory."))
|
|
|
|
For ($ExpandedItemListIndex = 0; $ExpandedItemListIndex -lt $ExpandedItemList.Count; $ExpandedItemListIndex++)
|
|
{
|
|
$ExpandedItem = [System.IO.FileInfo]$ExpandedItemList[$ExpandedItemListIndex]
|
|
|
|
$MatchingFilterList = $IncludeFilter | Where-Object {($ExpandedItem.Name -ilike $_)}
|
|
|
|
Switch (($MatchingFilterList | Measure-Object).Count -gt 0)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$DestinationItemPath = [System.IO.FileInfo][System.IO.Path]::Combine($Destination.FullName, $ExpandedItem.Name)
|
|
|
|
Switch ([System.IO.File]::Exists($DestinationItemPath.FullName))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Attempting to remove the pre-existing item `"$($DestinationItemPath.FullName)`". Please Wait..."))
|
|
|
|
$Null = [System.IO.File]::Delete($DestinationItemPath.FullName)
|
|
}
|
|
}
|
|
|
|
$WriteLogMessage.Invoke(0, @("Attempting to move the expanded item `"$($ExpandedItem.Name)`" into the destination directory. Please Wait... [Size: $([System.Math]::Round($ExpandedItem.Length / 1MB, 2)) MB]"))
|
|
|
|
$Null = [System.IO.File]::Move($ExpandedItem.FullName, $DestinationItemPath.FullName)
|
|
|
|
$OutputObjectProperties.ItemList.Add(([System.IO.FileInfo]$DestinationItemPath.FullName))
|
|
}
|
|
|
|
{($_ -eq $False)}
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Skipping the expanded item `"$($ExpandedItem.Name)`". [Reason: The item does not match the inclusion filter of `"$($IncludeFilter -Join '; ')`".]"))
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
$OutputObjectProperties.Duration = New-TimeSpan -Start ($FunctionStartTime) -End ([System.DateTime]::UtcNow)
|
|
|
|
$WriteLogMessage.Invoke(0, @("$($OutputObjectProperties.ItemList.Count) item(s) were placed into `"$($Destination.FullName)`". [Duration: $($OutputObjectProperties.Duration.ToString())]"))
|
|
|
|
$OutputObject = New-Object -TypeName 'System.Management.Automation.PSObject' -Property ($OutputObjectProperties)
|
|
|
|
Write-Output -InputObject ($OutputObject)
|
|
}
|
|
Catch
|
|
{
|
|
$ErrorRecord = $_
|
|
|
|
Switch ($ContinueOnError.IsPresent)
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteLogMessage.Invoke(2, @("[Message: $($ErrorRecord.Exception.Message)] [LineNumber: $($ErrorRecord.InvocationInfo.ScriptLineNumber)] [Code: $($ErrorRecord.InvocationInfo.Line.Trim())]"))
|
|
}
|
|
|
|
{($_ -eq $False)}
|
|
{
|
|
Throw
|
|
}
|
|
}
|
|
}
|
|
Finally
|
|
{
|
|
Switch (($Null -ine $StagingDirectory) -and ([System.IO.Directory]::Exists($StagingDirectory.FullName)))
|
|
{
|
|
{($_ -eq $True)}
|
|
{
|
|
$WriteLogMessage.Invoke(0, @("Attempting to remove the staging directory. Please Wait... [Path: $($StagingDirectory.FullName)]"))
|
|
|
|
$Null = Try {[System.IO.Directory]::Delete($StagingDirectory.FullName, $True)} Catch {}
|
|
}
|
|
}
|
|
|
|
$WriteLogMessage.Invoke(0, @("Function `'$($CmdletName)`' is completed."))
|
|
}
|
|
}
|
|
#endregion
|