Private/Remove-VM.ps1
Function Remove-VM { [CmdletBinding(DefaultParameterSetName = 'Name', SupportsShouldProcess = $True)] param( [Parameter(ParameterSetName = 'Id')] [Parameter(ParameterSetName = 'Name')] [ValidateNotNullOrEmpty()] [Alias('CN')] [string]$ComputerName = $env:COMPUTERNAME, [Parameter(ParameterSetName = 'Id', Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidateNotNull()] [System.Nullable[guid]] $Id, [Parameter(ParameterSetName = 'Name', Position = 0, ValueFromPipeline = $true)] [Alias('VMName')] [ValidateNotNullOrEmpty()] [string[]]$Name, [Parameter(ParameterSetName = 'ClusterObject', Mandatory = $true, Position = 0, ValueFromPipeline = $true)] [PSTypeName('Microsoft.FailoverClusters.PowerShell.ClusterObject')] [ValidateNotNullOrEmpty()] [psobject]$ClusterObject, [Switch]$Passthru ) begin { Write-Verbose -Message "Starting $($MyInvocation.Mycommand)" Write-Verbose -Message "Using parameter set $($PSCmdlet.ParameterSetName)" Try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } #remove Whatif from Boundparameters since Get-VM doesn't recognize it $PSBoundParameters.Remove("WhatIf") | Out-Null $PSBoundParameters.Remove("Passthru") | Out-Null $PSBoundParameters.Remove("Confirm") | Out-Null $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-VM', [System.Management.Automation.CommandTypes]::Cmdlet) #$scriptCmd = {& $wrappedCmd @PSBoundParameters } Write-Verbose "Using parameters:" Write-verbose ($PSBoundParameters | Out-String) $ScriptCmd = { & $wrappedCmd @PSBoundParameters -pv vm | foreach-object -begin { #create a PSSession to the computer Try { Write-Verbose "Creating PSSession to $computername" $mysession = New-PSSession -ComputerName $computername #turn off Hyper-V object caching Write-Verbose "Disabling VMEventing on $computername" Invoke-Command { Disable-VMEventing -Force -confirm:$False } -session $mySession } catch { Throw } } -process { Write-Debug ($vm | Out-String) #write the VM to the pipeline if -Passthru was called if ($Passthru) { $vm } Invoke-Command -scriptblock { [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'medium')] Param($VM, [string]$VerbosePreference) $WhatIfPreference = $using:WhatifPreference $confirmPreference = $using:ConfirmPreference Write-Verbose "Whatif = $WhatifPreference" Write-Verbose "ConfirmPreference = $ConfirmPreference" #set confirm value switch ($confirmPreference) { "high" { $cv = $false } "medium" { $cv = $False } "low" { $cv = $True } Default { $cv = $False } } $State = (Get-VM $VM.name).State if (!($State -eq "Off")) { Stop-VM -Name $VM.name -TurnOff } #remove snapshots first #$VM is the pipelinevariable from the wrapped command Write-Verbose "Testing for snapshots" if (Get-VMSnapshot -VMName $VM.name -ErrorAction SilentlyContinue) { Write-Verbose "Removing existing snapshots" Remove-VMSnapshot -VMName $VM.name -IncludeAllChildSnapshots -Confirm:$cv } $disks = $vm.id | Get-VHD if ($disks.Count -eq 0) { $DiskRemove = $True } #remove disks foreach ($disk in $disks) { #the disk path might still reflect a snapshot so clean them up first #This code shouldn't be necessary since we are removing snapshots, #but just in case... [regex]$rx = "\.avhd(.?)" if ($disk.path -match $rx) { Write-Verbose "Cleaning up snapshot leftovers" #get a clean version of the file extension $extension = $rx.Matches($disk.path).value.replace("a", "") #a regex to find a GUID and file extension [regex]$rx = "_(\{){0,1}[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}(\}){0,1}.avhd(.?)" $thePath = $rx.Replace($disk.path, $extension) } else { $thePath = $disk.path } Try { Write-Verbose "Removing $thePath" if (Test-Path $thePath) { Remove-Item -Path $thePath -ErrorAction Stop -Confirm:$cv } $DiskRemove = $True } Catch { Write-Warning "Failed to remove $thePath" Write-warning $_.exception.message #don't continue removing anything if there was a problem removing the disk file $DiskRemove = $False } } if ($diskRemove) { #remove the VM $VM | ForEach-Object { Write-Verbose "Removing virtual machine $($_.name)" Remove-VM -Name $_.Name -Force } #foreach } #if disk remove was successful else { Write-Verbose "Aborting virtual machine removal" } } -session $mySession -ArgumentList ($vm, $VerbosePreference) -hidecomputername } -end { #remove PSSession. Ignore -Whatif and always remove it. Write-Verbose "Removing PSSession to $computername" Remove-PSSession -Session $mySession -WhatIf:$false -Confirm:$False } } #scriptCMD $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } Write-Verbose -Message "Ending $($MyInvocation.Mycommand)" } } |