I have just the script for you. I wanted to have a way to quickly find out what machines were virtual at work, so I whipped this up in PowerShell today.
Param(
[string]$ComputerName = 'localhost',
[string]$ComputersListFile
)
if ($ComputersListFile) {$computers = Get-Content -Path $ComputersListFile} else {$computers = $ComputerName}
if ($ComputerName -eq'localhost')
{
if((Get-WmiObject -Class win32_bios).SerialNumber.StartsWith("VMware")) {Write-Output "This machine is a VM!"} else {Write-Output "This machine is probably not a VM"}
}
else
{
invoke-command -ComputerName $computers -ScriptBlock {$hostname = hostname; if((Get-WmiObject -Class win32_bios).SerialNumber.StartsWith("VMware")) {Write-Output "$hostname is a VM!"} else {Write-Output "$hostname probably is not a VM"}}
}
This only works as it is for VMWare virtualization, not for Hyper-V or VirtualBox, but it would be easy to add tests for those too. The test is to look at the BIOS SerialNumber and see if it starts with the string "VMware". It's just that simple. ...You could also look at the MAC address of the NIC and see if the first few digits match one of the VMWare prefixes, but the BIOS string was easier.
Run it like this:
.\IsItAVM.ps1 -ComputerName computer1, computer2, computer3
or like this if you have a list of computers already in a file:
.\IsItAVM.ps1 -ComputersListFile U:\computers.txt
Of course, this will only work if the computer you are testing is Windows with PowerShell and has PowerShell remoting enabled, and you are not blocked by a firewall... but in an IT environment where PowerShell is being used for management this fits nicely.
Have fun!
--
Edit: Added a little bit of code to better handle the localhost case. If you just run it as .\IsItAVM.ps1 or manually specify just localhost in the -ComputerName then it will not try to use Invoke-Command, so it will not need remoting turned on for a localhost check. Also it gives a slightly different message on a localhost check.