Hey everyone - I think I have an easy question.

I need a powershell script that checks to see if the machine is virtual / physical. And if it is physical to display a msg “This is not a virtual machine” for like 10 seconds and then turn the PC off.

It will be used in an SCCM task sequence

6 Spice ups

Here you go:

http://gallery.technet.microsoft.com/scriptcenter/Determine-if-a-computer-is-cdd20473

1 Spice up

something like this

$Result = $null

$bios = gwmi Win32_BIOS -computername computername | Select-Object “version”,“serialnumber”

$compsys = gwmi Win32_ComputerSystem -computername $DC.Name | Select-Object “model”,“manufacturer”

if($bios.Version -match “VRTUAL”) {$DCVM = “Virtual - Hyper-V”}

elseif($bios.Version -match “A M I”) {$DCVM = “Virtual - Virtual PC”}

elseif($bios.Version -like “Xen”) {$DCVM = “Virtual - Xen”}

elseif($bios.SerialNumber -like “VMware”) {$DCVM = “Virtual - VMWare”}

elseif($compsys.manufacturer -like “Microsoft”) {$DCVM = “Virtual - Hyper-V”}

elseif($compsys.manufacturer -like “VMWare”) {$DCVM = “Virtual - VMWare”}

elseif($compsys.model -like “Virtual”) {$DCVM = “Virtual”}

else {$DCVM = “Physical”}

But at the end, I’d like it to react to If dcvm=physical display the msg This is not a virtual computer and then turn off the PC

1 Spice up

I wrote this a few days ago for almost the same thing.

I needed to know which of my servers were physical and which were virtual (total between the 2 I have 105)

This will get you a list of physicals Or you can alter it very easily to get a list of virtuals. Instead of putting into a file like I am, you could put the server list into an array and use that array as an if when you goto process each server to say. If $env:Computername is in the array, don’t do anything, else do all kinds of SCCM stuff.

$Servers = (Get-Content "Servers.txt")

$Results = @()

ForEach ($Server in $Servers)
{
	Write-Host "Checking ... $Server" -ForegroundColor Magenta -BackgroundColor Black
	$Results += Get-WmiObject -ComputerName $Server -Class Win32_ComputerSystem -Namespace "root\CIMV2" | Select @{Name="Server";Expression={$Server}},Manufacturer
}

$Results | Where-Object { $_.Manufacture -ne "Microsoft Corporation" -or $_.Manufacturer -ne "VMWare Inc." } | Out-File "C:\PhysicalServers.txt"

Basically, it’s a WMI query for the manufacturer. Usually VMs have a Manufacture of “Microsoft Corporate” or “VMware Inc.” if they are a VM. Otherwise they would have their actual manufacturer, such as HP, Dell, etc.

2 Spice ups

Just curious if VMWare has updated their P2V tools to update the manufacturer? I had to write something similar, but ended up looking like the code below, searching for the MAC address as it did not update our VMs that had been virtualized from physical machines.

$Adapters=gwmi win32_networkadapterconfiguration -ComputerName $ServerName | where {$_.MACAddress -like "00:50:56*"}
foreach ($Nic in $Adapters){ # Get adapter information to see if MAC address = VMWare MAC
if ($Nic.MACAddress -match "00:50:56*"){$VMsvr = "Virtual"}}

That I am not sure. THat is the way I had to overcome the problem. As we know, there are many ways to do the same thing.

$Result = $null
$bios = gwmi Win32_BIOS -computername computername | Select-Object "version","serialnumber"
$compsys = gwmi Win32_ComputerSystem -computername $DC.Name | Select-Object "model","manufacturer"
if($bios.Version -match "VRTUAL") {$DCVM = "Virtual - Hyper-V"}
elseif($bios.Version -match "A M I") {$DCVM = "Virtual - Virtual PC"}
elseif($bios.Version -like "*Xen*") {$DCVM = "Virtual - Xen"}
elseif($bios.SerialNumber -like "*VMware*") {$DCVM = "Virtual - VMWare"}
elseif($compsys.manufacturer -like "*Microsoft*") {$DCVM = "Virtual - Hyper-V"}
elseif($compsys.manufacturer -like "*VMWare*") {$DCVM = "Virtual - VMWare"}
elseif($compsys.model -like "*Virtual*") {$DCVM = "Virtual"}
else {$DCVM = "Physical"}

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$OUTPUT= [System.Windows.Forms.MessageBox]::Show("This is not a Virtual Machine." , "Status" , 0)

if ($OUTPUT -eq "OK" ) 
{
Parameter Set: Default
Stop-Computer -localhost
}

So - I think I got it pretty close. I just don’t know how to get one section of the script to depend on the other. The top half finds out if the machine is a physical machine or a VM. I need the bottom half to only run, if the "else {dcvm = “Physical”}

I’m almost there!

Instead of a pop-up window consider a more PowerShell like output by instead creating a PowerShell object:

[PSCustomObject]@{
    Name = $DC.Name
    BiosVersion = $bios.Version
    Make = $compsys.Make
    Model = $compsys.Model
    DCVM = $DCVM
}

From there assign that to an array. When done you’ll have a nice little array of objects with all of the pertinent information in it. You can then do fun things like:

$Array | Sort Name | Export-CSV c:\myServers.csv -NoTypeInformation

Remember that PowerShell is object oriented, so any time you don’t use object output you’re loosing potential. Now, in this case you may still want to do the prompt because you’re looking for interactive reboots and so on, but you should always consider object output :slight_smile:

I am still a terribly rookie-ish powershell player. But I do enjoy learning about these things. Can you think of a better way for me to solve my issue? Toss out some script if you can lol - that’s what I am looking for. Some script to help me accomplish my goal.

I have a task sequence in SCCM deployed to help my team mates image virtual PCs in a test environment. But I don’t want other’s using this task sequence to image their machines because it doesn’t have all the requirements that the production task sequence does. So I am trying to build a script that checks to see if it’s a VM, and if not… stops the progress.