清理 Hyper-V 中无法删除的虚拟机残留
我在 Hyper-V 管理器里看到一台早已不用的虚拟机,但执行 Get-VM -Name 和 Remove-VM 都提示找不到对象。管理员权限和 vmms 服务没有问题,虚拟交换机也能正常读取。
这说明管理器里的条目可能已经损坏,或者只剩下一条底层注册。下面是我最后使用的清理顺序。
先试正常删除
在管理员 PowerShell 中确认权限:
$principal = [Security.Principal.WindowsPrincipal]::new(
[Security.Principal.WindowsIdentity]::GetCurrent()
)
$principal.IsInRole(
[Security.Principal.WindowsBuiltInRole]::Administrator
)结果应为 True。然后检查目标:
$targetName = 'TARGET_VM'
Get-VM -Name $targetName |
Format-List Name,State,Status,Id,Path,ConfigurationLocation
Get-VMHardDiskDrive -VMName $targetName |
Format-Table ControllerType,ControllerNumber,ControllerLocation,Path
Get-VMSnapshot -VMName $targetName |
Format-Table Name,SnapshotType,CreationTime如果 Get-VM 能找到它,直接使用 Hyper-V 自带命令:
Remove-VM -Name $targetName -WhatIf
Remove-VM -Name $targetName-WhatIf 会先显示即将删除的对象。确认名称无误后再执行第二条。
Get-VM 找不到时检查底层注册
Hyper-V 的虚拟机对象位于 root/virtualization/v2。先查询普通虚拟机和计划虚拟机:
$namespace = 'root/virtualization/v2'
$targetName = 'TARGET_VM'
$targets = @(
Get-CimInstance -Namespace $namespace -ClassName Msvm_ComputerSystem |
Where-Object { $_.ElementName -ieq $targetName }
Get-CimInstance -Namespace $namespace -ClassName Msvm_PlannedComputerSystem |
Where-Object { $_.ElementName -ieq $targetName }
)
$targets |
Format-List ElementName,Name,EnabledState,OperationalStatus没有结果时,不要继续调用删除方法。此时管理器里显示的更可能是旧连接或界面缓存,关闭 Hyper-V 管理器再打开即可。
如果找到了唯一对象,可以调用 Hyper-V 的 DestroySystem:
if ($targets.Count -ne 1) {
throw "要求精确匹配一个对象,实际找到 $($targets.Count) 个,已停止。"
}
$service = Get-CimInstance `
-Namespace $namespace `
-ClassName Msvm_VirtualSystemManagementService
$result = Invoke-CimMethod `
-InputObject $service `
-MethodName DestroySystem `
-Arguments @{ AffectedSystem = $targets[0] }
if ($result.ReturnValue -notin 0, 4096) {
throw "DestroySystem 失败,返回值:$($result.ReturnValue)"
}
$result目标虚拟机应当处于关闭或保存状态。返回 0 表示已经完成,4096 表示任务正在异步执行,需要等结果中的 Job 完成。
删除后重新查询:
Get-CimInstance -Namespace $namespace -ClassName Msvm_ComputerSystem |
Where-Object { $_.ElementName -ieq $targetName }
Get-CimInstance -Namespace $namespace -ClassName Msvm_PlannedComputerSystem |
Where-Object { $_.ElementName -ieq $targetName }两条命令都没有输出,再关闭并重新打开 Hyper-V 管理器。
虚拟磁盘要单独处理
删除虚拟机注册不等于删除 .vhd 或 .vhdx。如果还要清理磁盘文件,应当先记录 Get-VMHardDiskDrive 返回的准确路径,再确认它没有被其他虚拟机使用。
不要递归删除整个 Hyper-V 目录,也不要用 *.vhdx 通配符批量清理。
这次虚拟机残留和端口问题碰巧同时出现,但两者不能画等号。端口的处理记录在排查 Windows 动态端口与保留端口冲突。