Public/Remove-VMConnectConfig.ps1

#.ExternalHelp VMConnectConfig-help.xml
function Remove-VMConnectConfig
{
    [CmdletBinding(ConfirmImpact = 'Medium', DefaultParameterSetName = 'Name', HelpURI='https://thegraffix.github.io/VMConnectConfig/remove-vmconnectconfig.html', SupportsShouldProcess)]
    [Alias('rvmc')]
    param (
        [Parameter(Mandatory, ParameterSetName = 'All')]
        [switch]$All,

        [Parameter(Mandatory, ParameterSetName = 'Deleted')]
        [switch]$Deleted,

        [switch]$Force,

        [Parameter(Mandatory, ParameterSetName = 'Id', Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('VMId')]
        [ValidateNotNullOrEmpty()]
        [System.Guid[]]$Id,

        [Parameter(Mandatory, ParameterSetName = 'InputObject', Position = 0, ValueFromPipeline)]
        [System.Management.Automation.PSTypeName('VMConnectConfig')]$InputObject,

        [Parameter(Mandatory, ParameterSetName = 'Name', Position = 0, ValueFromPipeline)]
        [SupportsWildcards()]
        [ValidateNotNullOrEmpty()]
        [System.String[]]$Name,

        [Parameter(Mandatory, ParameterSetName = 'Nuke')]
        [switch]$Nuke
    )

    begin
    {
        # This is a workaround for a bug where advanced functions can output an error if "-ErrorAction/-WarningAction Ignore" are used.
        if ($ErrorActionPreference -eq 'Ignore') {$ErrorActionPreference = 'Ignore'}
        if ($WarningPreference -eq 'Ignore') {$WarningPreference = 'Ignore'}

        $null = Test-VMConfigFolder

        $fileAttributeNormal = [System.IO.FileAttributes]::Normal
        [System.String[]]$filesToRemoveList = @()
        $uiOption = [Microsoft.VisualBasic.FileIO.UIOption]::OnlyErrorDialogs
    } #begin

    process
    {
        if ($PSCmdlet.ParameterSetName -ne 'Nuke')
        {
            $allConfigFiles = Get-AllConfigFiles
        }

        switch ($PSCmdlet.ParameterSetName)
        {
            'All'
            {
                $filesToRemoveList = $allConfigFiles.FullName
                break
            } # -All

            'Deleted'
            {
                Write-VMVerbose -Function Remove-VMConnectConfig -Category Reading -Message ($MsgTable.GettingConfigFilesForDeletedVirtualMachines -f $VMConfigFolder)
                $filesToRemoveList = (Get-VMConnectConfig -Deleted -ErrorAction SilentlyContinue -Verbose:$false).Path
                break
            } # -Deleted

            'Id'
            {
                foreach ($vmGuid in $Id)
                {
                    $files = @()
                    $files = [System.String[]](($allConfigFiles | Where-Object {$_.Name -match "vmconnect\.rdp\.$vmGuid.*\.config"}).FullName)

                    if (($files.Count -eq 0) -or ([System.String]::IsNullOrEmpty($files)))
                    {
                        $errMsg = ($MsgTable.ConfigFileNotFoundIdError -f $VMConfigFolder, $vmGuid)

                        $errParams = @{
                            Category = $ErrorCatObjectNotFound
                            Exception = New-Object -TypeName 'System.ArgumentException' -ArgumentList $errMsg
                            Message = $errMsg
                        }

                        Write-Error @errParams
                    } #if no .config file(s) found.
                    else
                    {
                        foreach ($file in $files)
                        {
                            $filesToRemoveList += $file
                        }
                    }
                } #foreach ($vmGuid in $Id)

                break
            } # -Id

            'InputObject'
            {
                foreach ($file in $InputObject.Path)
                {
                    $filesToRemoveList += $file
                }

                break
            } # -InputObject

            'Name'
            {
                foreach ($vmName in $Name)
                {
                    $files = @()

                    try
                    {
                        $files = [System.String[]]((Select-Xml -Path $allConfigFiles.FullName -XPath $VMNameXPath | Where-Object {$_.Node.Value -like $vmName}).Path)
                    } #try
                    catch
                    {
                        # Do nothing. This is to fully suppress terminating errors from the Select-Xml cmdlet when the 1.0 directory exists but is empty.
                    } #catch

                    if (($files.Count -eq 0) -or ([System.String]::IsNullOrEmpty($files)))
                    {
                        $errMsg = ($MsgTable.ConfigFileNotFoundNameError -f $VMConfigFolder, $vmName)

                        $errParams = @{
                            Category = $ErrorCatObjectNotFound
                            Exception = New-Object -TypeName 'System.ArgumentException' -ArgumentList $errMsg
                            Message = $errMsg
                        }

                        Write-Error @errParams
                    } #if no .config file(s) found.
                    else
                    {
                        foreach ($file in $files)
                        {
                            $filesToRemoveList += $file
                        }
                    }
                } #foreach ($vmName in $Name)

                break
            } # -Name

            'Nuke'
            {
                $actionString= ($MsgTable.ActionMsgRemoveDirectory)

                if ($PSCmdlet.ShouldProcess($VMConfigFolder, $actionString))
                {
                    try
                    {
                        # Reset attributes for the $VMConfigFolder directory.
                        Set-ItemProperty -Path $VMConfigFolder -Name 'Attributes' -Value $fileAttributeNormal -Force -ErrorAction Stop
                    } #try
                    catch
                    {
                        $PSCmdlet.WriteError($_)
                        break
                    } #catch

                    if ($Force)
                    {
                        try
                        {
                            Write-VMVerbose -FunctionName Remove-VMConnectConfig -Category Deleting -Message ($MsgTable.DeletingPermanentlyMsg -f $VMConfigFolder)
                            # Reset attributes on every file to make sure that Delete() works.
                            Get-ChildItem -Path $VMConfigFolder -Recurse:$true -Force | Set-ItemProperty -Name 'Attributes' -Value $fileAttributeNormal -Force -ErrorAction Stop
                            ([System.IO.DirectoryInfo]$VMConfigFolder).Delete($true)
                        } #try
                        catch
                        {
                            $PSCmdlet.WriteError($_)
                        } #catch
                    } #if -Force
                    else
                    {
                        try
                        {
                            Write-VMVerbose -FunctionName Remove-VMConnectConfig -Category Deleting -Message ($MsgTable.DeletingMsg -f $VMConfigFolder)
                            $recycleOption = [Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin
                            $null = [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory($VMConfigFolder, $uiOption, $recycleOption)
                        } #try
                        catch
                        {
                            $PSCmdlet.WriteError($_)
                        } #catch
                    } #else
                } #ShouldProcess

                break
            } # -Nuke
        } #switch ($PSCmdlet.ParameterSetName)
    } #process

    end
    {
        if ($PSCmdlet.ParameterSetName -eq 'Nuke')
        {
            return
        }

        # Remove any duplicates.
        $filesToRemoveList = $filesToRemoveList | Select-Object -Unique

        if ($filesToRemoveList.Count -eq 0)
        {
            Write-Warning ($MsgTable.NoFilesToDelete)
            return
        }

        [System.String[]]$validConfigFilePathList = @()

        foreach ($configFile in $filesToRemoveList)
        {
            try
            {
                if ((Test-VMConnectConfig -LiteralPath $configFile -ErrorAction Stop) -eq $false)
                {
                    $errMsg = ($MsgTable.InvalidConfigFileError -f $configFile)

                    $errParams = @{
                        Category = $ErrorCatInvalidArgument
                        Exception = New-Object -TypeName 'System.ArgumentException' -ArgumentList $errMsg
                        Message = $errMsg
                        TargetObject = $configFile
                    }

                    Write-Error @errParams
                }
                else
                {
                    $validConfigFilePathList += $configFile
                }
            }
            catch
            {
                $PSCmdlet.WriteError($_)
            }
        }

        if ($Force)
        {
            $actionString = ($MsgTable.ActionMsgDeletePermanently)
        }
        else
        {
            $actionString = ($MsgTable.ActionMsgMoveToRecycleBin)
        }

        foreach ($file in $validConfigFilePathList)
        {
            if ($PSCmdlet.ShouldProcess($file, $actionString))
            {
                try
                {
                    if ($Force)
                    {
                        $recycleOption = [Microsoft.VisualBasic.FileIO.RecycleOption]::DeletePermanently
                        $deleteVerboseMsg = ($MsgTable.DeletingPermanentlyMsg -f $file)

                        # Reset attributes on every file to make sure that DeleteFile() works.
                        ([System.IO.FileInfo]$file).Attributes = [System.IO.FileAttributes]::Normal
                    }
                    else
                    {
                        $recycleOption = [Microsoft.VisualBasic.FileIO.RecycleOption]::SendToRecycleBin
                        $deleteVerboseMsg = ($MsgTable.DeletingMsg -f $file)
                    }

                    Write-VMVerbose -FunctionName Remove-VMConnectConfig -Category Deleting -Message $deleteVerboseMsg
                    $null = [Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($file, $uiOption, $recycleOption)
                } #try
                catch
                {
                    $PSCmdlet.WriteError($_)
                } #catch
            } #ShouldProcess
        } #foreach

        # Perform garbage collection.
        [System.GC]::Collect()
        [System.GC]::WaitForPendingFinalizers()
    } #end
} #function Remove-VMConnectConfig