Veeam v13: Cross-Platform Restore from VMware to Hyper-V
Veeam v13: Cross-Platform Restore from VMware to Hyper-V
Instant Recovery of a VMware VM backup to a Hyper-V cluster, plus the VMware Tools cleanup Veeam does not do for you
Veeam Backup and Replication v13 can take a VMware VM backup and restore it directly onto a Microsoft Hyper-V host as a running VM. The feature is called Instant Recovery to Microsoft Hyper-V. It handles disk format conversion, generates a Hyper-V VM configuration, and boots the VM on the target host straight from the backup file. The VM is up in minutes while Veeam migrates the data to production storage in the background.
What Veeam does not handle is VMware Tools cleanup inside the guest. After the VM boots on Hyper-V, VMware Tools services, drivers, and registry entries are still sitting there. They do not cause a boot failure, but they generate errors, consume resources, and clutter the system. This article walks through the full Instant Recovery wizard from the build we just did, then covers the PowerShell scripts we wrote to strip VMware Tools out of the guest after the restore.
Before you start
You need a VMware VM backup already present in a Veeam v13 backup repository, and a Hyper-V host or cluster registered in Veeam as a managed server (either directly or through SCVMM). The target host must have enough compute, memory, and storage to run the restored VM.
The Instant Recovery Wizard
In the Veeam Backup and Replication console, open the Home view. In the inventory pane, expand Backups. Find the VMware backup job that contains the VM you want to restore. Right-click the VM and select Instant Recovery > Microsoft Hyper-V.
That opens the Instant Recovery to Microsoft Hyper-V wizard. Seven steps: Machines, Host, Datastore, Network, Name, Secure Restore, and Reason.
Machines
The wizard shows the VM you selected and its restore point. If you need a different restore point, click Point to choose a specific backup or snapshot. You can also add more VMs to restore in the same operation.
Machines step. The VMware VM is selected with its most recent restore point. Click Point to choose a different restore point if needed.
Host
Select the target Hyper-V host where the VM will run. If you added SCVMM to Veeam, you will see your VMM-managed hosts and clusters here. If you added the cluster directly, you will see individual hosts. Pick the host with available resources.
Host step. The VM is mapped to a Hyper-V host on the cluster. The Cluster Resource column shows whether the VM will be registered as a cluster resource.
Datastore
Select where the VM configuration files and virtual disks will land on the target host. For a cluster, this is typically a Cluster Shared Volume (CSV) path. The wizard shows the flat disk file from the VMware backup that Veeam will convert to VHDX format during the migration phase.
Datastore step. Configuration files and the flat VMDK land on the CSV. Check "Allocate required disk space before migration" to pre-allocate the VHDX on the target volume.
Network
Map the source VMware port group to a target Hyper-V virtual switch. The source column shows the VMware network label from the backup. Click Network to map it to a Hyper-V virtual switch on the target host. If you leave it as "Not connected," the VM will boot without network. You can connect it later from Hyper-V Manager.
Network step. Map the VMware port group to a Hyper-V virtual switch. Click Network at the bottom right to open the mapping dialog.
Secure Restore
Secure Restore scans the backup for malware before restoring. You need a compatible antivirus on the mount server for this to work. If you do not have one, skip it. You can also scan using a YARA rule if you have custom detection rules configured.
Secure Restore step. Optional malware scan before restore. Requires antivirus on the mount server. Skip if not configured.
Summary and Finish
Review the summary. It shows the original VM name, new VM name, restore point, target host, target folder, and network mapping. Check "Power on target VM after restoring" if you want the VM to boot immediately.
Summary step. Verify the target host, target folder, and network mapping before clicking Finish.
Click Finish. Veeam starts the Instant Recovery process.
What Happens During Instant Recovery
The restore session log shows the sequence of operations. Veeam pre-allocates the VHDX on the target CSV, mounts the VHDs from the backup, modifies the guest OS settings for Hyper-V compatibility, creates a snapshot, publishes the VM on the Hyper-V host, and then waits for you to trigger the data migration to production storage.
Restore session log. The VM is published and running on Hyper-V from the backup file. The "Guest OS settings were modified successfully" line is Veeam adapting the OS for Hyper-V. The final line waits for you to start the migration to production storage.
At this point, the VM is live on Hyper-V but running from the backup repository. Performance will be limited by the repository storage speed. The VM shows as "Mounted" in the Veeam console under Instant Recovery.
Instant Recovery view. The VM is mounted and running from the backup repository. The Backup Name column confirms the source was a VMware vCenter backup.
Two-phase process
Instant Recovery is not a one-step restore. Phase 1 mounts the VM from the backup file so it boots immediately. Phase 2 migrates the VM data from the backup repository to the production CSV. You must trigger Phase 2 from the restore session or Instant Recovery view. Until you complete the migration, the VM is dependent on the backup repository. If the repository goes offline, the VM goes down.
The VMware Tools Problem
After the VM boots on Hyper-V, log in to the guest. VMware Tools is still installed. The services will fail to start because there is no VMware hypervisor underneath, but the services, drivers, registry entries, and program files are all still sitting there.
Veeam does adapt the guest OS for Hyper-V during the restore. The restore session log shows "Guest OS settings were modified successfully." That step patches the OS so it boots on Hyper-V. But it does not touch VMware Tools. In a VMware to VMware restore you would never notice because Tools just reconnects. Cross platform, you are left with a dead toolset that needs manual cleanup.
The first thing you will try is Programs and Features. We did. The VMware Tools MSI uninstaller launched, tried to detect the hypervisor, could not find one, and threw an error. It would not proceed. So we scripted the removal instead.
VMware Tools MSI uninstall failed on our Hyper-V guest
The MSI uninstaller could not detect a VMware hypervisor and refused to proceed. If you hit this same wall, do not waste time troubleshooting the installer. Use the scripted removal below.
VMware Tools Removal Scripts
We ended up needing two scripts. The Windows 10 and Windows Server version is a straight brute force removal. The Windows 11 version is more structured. It tries the MSI silent uninstall path first, covers a wider set of VMware services (VGAuthService, NSX Guest Introspection if present), and cleans up additional file paths. Both scripts run as Administrator on the restored VM.
Adapt these scripts to your environment
These scripts worked on our builds. Your guest OS may have additional VMware components, different service names, or third party VMware integrations that are not covered here. Review the service list and folder paths before running. Test on a non production VM first.
Windows 10 / Windows Server (vm_tools_remove.ps1)
The simple version. Stops services, nukes registry keys, removes MSI uninstaller entries, and deletes the file system leftovers. Fast and direct.
# 1. Stop and Disable VMware Services
$services = @("VMTools", "vmusbmouse", "vmmouse", "vmvss", "VMMEMCTL", "vmci", "vsock")
foreach ($service in $services) {
if (Get-Service -Name $service -ErrorAction SilentlyContinue) {
Write-Host "Stopping and removing service: $service" -ForegroundColor Yellow
Stop-Service -Name $service -Force -ErrorAction SilentlyContinue
sc.exe delete $service | Out-Null
}
}
# 2. Remove Registry Entries (Software and Uninstaller)
$registryPaths = @(
"HKLM:\SOFTWARE\VMware, Inc.",
"HKLM:\SOFTWARE\Wow6432Node\VMware, Inc."
)
foreach ($path in $registryPaths) {
if (Test-Path $path) {
Write-Host "Removing registry path: $path" -ForegroundColor Yellow
Remove-Item -Path $path -Recurse -Force
}
}
# 3. Search and Destroy MSI Uninstall Keys
$uninstallPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Get-ChildItem -Path $uninstallPath | ForEach-Object {
$key = Get-ItemProperty $_.PSPath
if ($key.DisplayName -like "*VMware Tools*") {
Write-Host "Removing MSI Uninstall Key: $($key.DisplayName)" -ForegroundColor Yellow
Remove-Item -Path $_.PSPath -Recurse -Force
}
}
# 4. Remove Driver Files and Application Data
$folders = @(
"${env:ProgramFiles}\VMware\VMware Tools",
"${env:ProgramData}\VMware"
)
foreach ($folder in $folders) {
if (Test-Path $folder) {
Write-Host "Removing folder: $folder" -ForegroundColor Yellow
Remove-Item -Path $folder -Recurse -Force -ErrorAction SilentlyContinue
}
}
Write-Host "Cleanup complete. Please reboot the VM to finish the process." -ForegroundColor Green
Windows 11 (Remove-VMwareTools_win11.ps1)
The Win11 version takes a different approach. It checks for admin privileges up front. It tries the MSI silent uninstall first by extracting the product code from the registry and running msiexec /x with quiet flags. If the MSI path does not exist or fails, it falls back to brute force service deletion and file cleanup. It also covers VGAuthService, VMwareAliasManagerAndTicketService, NSX Guest Introspection, and the x86 Program Files path.
# Remove-VMwareTools_win11.ps1
# Removes VMware Tools and does basic cleanup after migration to Hyper-V.
# Run in an elevated PowerShell session.
[CmdletBinding()]
param()
$ErrorActionPreference = "Stop"
function Write-Info {
param([string]$Message)
Write-Host "[INFO] $Message" -ForegroundColor Cyan
}
function Write-WarnMsg {
param([string]$Message)
Write-Host "[WARN] $Message" -ForegroundColor Yellow
}
function Write-Ok {
param([string]$Message)
Write-Host "[OK] $Message" -ForegroundColor Green
}
function Test-IsAdmin {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($identity)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Get-UninstallEntries {
$paths = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
)
$results = foreach ($path in $paths) {
Get-ItemProperty -Path $path -ErrorAction SilentlyContinue | Where-Object {
$_.DisplayName -match "VMware Tools|VMware NSX Guest Introspection"
}
}
$results | Sort-Object DisplayName -Unique
}
function Convert-UninstallStringToSilent {
param([string]$UninstallString)
if ([string]::IsNullOrWhiteSpace($UninstallString)) {
return $null
}
$cmd = $UninstallString.Trim()
if ($cmd -match "msiexec(\.exe)?") {
if ($cmd -match "/I\s*({[A-Fa-f0-9\-]+})") {
$productCode = $matches[1]
return "msiexec.exe /x $productCode /qn /norestart"
}
if ($cmd -match "/X\s*({[A-Fa-f0-9\-]+})") {
$productCode = $matches[1]
return "msiexec.exe /x $productCode /qn /norestart"
}
if ($cmd -match "({[A-Fa-f0-9\-]+})") {
$productCode = $matches[1]
return "msiexec.exe /x $productCode /qn /norestart"
}
return "$cmd /qn /norestart"
}
if ($cmd.StartsWith('"')) {
return "$cmd /S /v`"/qn REBOOT=ReallySuppress`""
}
return "$cmd /S /v`"/qn REBOOT=ReallySuppress`""
}
function Invoke-UninstallCommand {
param([string]$CommandLine)
Write-Info "Running uninstall command: $CommandLine"
$proc = Start-Process -FilePath "cmd.exe" -ArgumentList "/c $CommandLine" `
-Wait -PassThru -WindowStyle Hidden
return $proc.ExitCode
}
function Stop-IfExists {
param([string]$ServiceName)
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($null -ne $svc) {
if ($svc.Status -ne "Stopped") {
Write-Info "Stopping service $ServiceName"
Stop-Service -Name $ServiceName -Force -ErrorAction SilentlyContinue
}
Write-Ok "Service checked: $ServiceName"
}
}
function Remove-ServiceIfExists {
param([string]$ServiceName)
$svc = Get-Service -Name $ServiceName -ErrorAction SilentlyContinue
if ($null -ne $svc) {
Write-WarnMsg "Deleting leftover service $ServiceName"
& sc.exe delete $ServiceName | Out-Null
}
}
function Remove-PathIfExists {
param([string]$PathToRemove)
if (Test-Path -LiteralPath $PathToRemove) {
Write-WarnMsg "Removing leftover path: $PathToRemove"
Remove-Item -LiteralPath $PathToRemove -Recurse -Force `
-ErrorAction SilentlyContinue
}
}
if (-not (Test-IsAdmin)) {
throw "Run this script from an elevated PowerShell session as Administrator."
}
Write-Info "Starting VMware Tools removal"
$possibleServices = @(
"VMTools",
"VGAuthService",
"VMwareAliasManagerAndTicketService",
"vmvss",
"vmscsi",
"vmci",
"vmx86"
)
foreach ($svc in $possibleServices) {
Stop-IfExists -ServiceName $svc
}
$entries = Get-UninstallEntries
if (-not $entries -or $entries.Count -eq 0) {
Write-WarnMsg "No VMware uninstall entries found in registry."
} else {
foreach ($entry in $entries) {
Write-Info "Found product: $($entry.DisplayName)"
$command = $null
if (-not [string]::IsNullOrWhiteSpace($entry.QuietUninstallString)) {
$command = $entry.QuietUninstallString
} elseif (-not [string]::IsNullOrWhiteSpace($entry.UninstallString)) {
$command = Convert-UninstallStringToSilent `
-UninstallString $entry.UninstallString
}
if ([string]::IsNullOrWhiteSpace($command)) {
Write-WarnMsg "No uninstall command found for $($entry.DisplayName)"
continue
}
try {
$exitCode = Invoke-UninstallCommand -CommandLine $command
if ($exitCode -eq 0 -or $exitCode -eq 1605 -or
$exitCode -eq 1614 -or $exitCode -eq 3010) {
Write-Ok "$($entry.DisplayName) uninstall completed (exit $exitCode)"
} else {
Write-WarnMsg "$($entry.DisplayName) returned exit code $exitCode"
}
} catch {
Write-WarnMsg "Failed uninstall: $($_.Exception.Message)"
}
}
}
Start-Sleep -Seconds 3
foreach ($svc in $possibleServices) {
Remove-ServiceIfExists -ServiceName $svc
}
$leftoverPaths = @(
"$env:ProgramFiles\VMware\VMware Tools",
"$env:ProgramFiles\Common Files\VMware",
"${env:ProgramFiles(x86)}\VMware\VMware Tools",
"$env:ProgramData\VMware"
)
foreach ($path in $leftoverPaths) {
Remove-PathIfExists -PathToRemove $path
}
Write-Host ""
Write-Ok "Cleanup finished."
Write-Host "Reboot the VM now." -ForegroundColor Yellow
Differences Between the Two Scripts
Win10/Server version is a straight line script. It assumes the MSI uninstaller is broken (which it was in our case) and goes directly to service deletion, registry cleanup, and file removal. Simple and fast.
Win11 version tries the MSI silent uninstall first. It extracts the product code from the registry uninstall entries, builds a silent msiexec /x command, and runs it. If that works, great. If it fails or the entries do not exist, it falls through to the same brute force cleanup. It also covers a wider set of services (VGAuthService, VMwareAliasManagerAndTicketService, vmscsi, vmx86) and additional file paths (Common Files\VMware, Program Files x86). The admin check at the top prevents it from running unprivileged and producing partial cleanup.
Reboot required
After running the script, reboot the VM. Some VMware drivers are loaded at boot time and their files cannot be deleted while they are in use. The reboot clears the driver load, releases any remaining locked files, and lets Windows start cleanly without the VMware driver stack.
Post-Restore Checklist
- 1Verify the VM boots and the guest OS is accessible via console or RDP.
- 2Confirm network connectivity. If you mapped the VMware port group to a Hyper-V switch during the wizard, the NIC should be connected. If not, attach it manually in Hyper-V Manager or VMM.
- 3Run the VMware Tools removal script as Administrator. Reboot the VM.
- 4After reboot, confirm VMware Tools services no longer appear in services.msc and the VMware Tools entry is gone from Programs and Features.
- 5Verify that Hyper-V Integration Services are active in the guest. On Windows Server 2016 and later, Integration Services are delivered through Windows Update and should already be present. Check Device Manager for any devices with missing drivers.
- 6Complete the Veeam migration phase. In the Veeam console, go to the Instant Recovery view, right-click the mounted VM, and select Migrate to production. This moves the VM data from the backup repository to the production CSV. The VM stays running during migration.
- 7After migration completes, the VM is fully independent of the backup repository. Add it to a Hyper-V backup job for ongoing protection.
What You've Completed
- Restored a VMware VM backup to a Hyper-V host using Veeam v13 Instant Recovery to Microsoft Hyper-V.
- Walked through the full Instant Recovery wizard: machine selection, host targeting, datastore mapping, network mapping, and secure restore options.
- Identified the two-phase Instant Recovery process: immediate mount from backup, then background migration to production storage.
- Discovered that VMware Tools persists inside the guest after cross-platform restore and that the standard MSI uninstaller fails on a non-VMware hypervisor.
- Deployed two PowerShell scripts to remove VMware Tools from the guest OS: a direct brute force version for Windows 10 and Windows Server, and a structured version for Windows 11 that tries MSI silent uninstall first and covers additional VMware components.
- Completed the post-restore checklist including network validation, Integration Services verification, and migration to production storage.