I have the following code that works as a stand-alone query:
$Type = (Invoke-Command -ComputerName $Computer -ScriptBlock { Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Manufacturer })
switch -regex ($Type)
{
"VMw.+" {"VM"}
default {"Physical"}
}
I want to add the switch command within the Invoke command instead of a variable (dropping the $Type variable) so that it can be run against multiple computers, how can this be accomplished, I am not determined to use Switch to accomplish the end result?
Get-WmiObject has a ComputerName property so you don't need to use Invoke-Command
switch -regex (Get-WmiObject -ComputerName $Computer -Class Win32_ComputerSystem | Select-Object -ExpandProperty Manufacturer)
{
"VMw.+" {"VM"}
default {"Physical"}
}
And by wrapping it in a simple foreach loop you can easily run it against multiple computers:
$Computers = "computer1","computer3","computer3"
foreach ($Computer in $Computers) {
switch -regex (Get-WmiObject -ComputerName $Computer -Class Win32_ComputerSystem | Select-Object -ExpandProperty Manufacturer)
{
"VMw.+" {Write-Output "$Computer is a VM Computer"}
default {Write-Output "$Computer is a Physical Computer"}
}
}
Related
#Listing machine from which we will Query
$Machines = Get-ADComputer -Filter * -SearchBase 'OU=Laptops,OU=Win10Modern,OU=LN,OU=Workstations,DC=cooley,DC=com' | Select-Object Name
#Getting the Network Adapter version for Wi-Fi Adapter
ForEach ($Machine in $Machines) {
Get-NetAdapter | Select-Object Name,InterfaceDescription,DriverVersion,DriverDate,DriverProvider
}
Currently, your code loops over objects in variable $Machines, where each object has a single property called Name.
In order to get just the name values, either use Select-Object -ExpandProperty Name or get the array of names like this:
# get an array of computernames
$Machines = (Get-ADComputer -Filter * -SearchBase 'OU=Laptops,OU=Win10Modern,OU=LN,OU=Workstations,DC=cooley,DC=com').Name
Next loop over these computernames and have each computer run the Get-NetAdapter cmdlet:
# capture the output(s) in variable $result
$result = foreach ($Machine in $Machines) {
if (Test-Connection -ComputerName $Machine -Count 1 -Quiet) {
Invoke-Command -ComputerName $Machine -ScriptBlock {
Get-NetAdapter | Select-Object SystemName,Name,InterfaceDescription,
DriverVersion,DriverDate,DriverProvider,Status,AdminStatus
}
}
else {
Write-Warning "Computer '$Machine' does not respond"
}
}
# output on screen
$result
# or to GridView
$result | Out-GridView -Title 'NetAdapterInfo'
# or to CSV file
$result | Export-Csv -Path 'X:\NetAdapterInfo.csv' -NoTypeInformation
AdminStatus is a setting (enabled --> 'up'; disabled --> 'down')
Status is operational status (connected --> 'up'; disconnected --> 'down')
I don't think you can use Get-NetAdapter to connect to remote computers.
You can however use Get-WmiObject Win32_NetworkAdapter -ComputerName .
Like this:
ForEach ($Machine in $Machines) {
Get-WmiObject -Class Win32_NetworkAdapter -Filter "NetConnectionStatus = 2" -ComputerName $Machine
}
You need to become familiar with the properties of the Win32_NetworkAdapter class. You can see all of the properties by running this command:
Get-WmiObject -Class Win32_NetworkAdapter -ComputerName "Localhost" | fl * -Force
or you can use this command to see all of the properties (and methods) available to you.
Get-WmiObject -Class Win32_NetworkAdapter -ComputerName "Localhost" | Get-Member
Most computers will have more than 1 network card (some are hidden) and you have to filter the irrelevant ones out.
Running this:
$WMI = Get-WMIObject -Class Win32_DiskDrive
ForEach ($Drive in $WMI){
$Drive.DeviceID + ": " + $Drive.Status
}
Returns results like:
\\.\PHYSICALDRIVE1: OK
\\.\PHYSICALDRIVE0: OK
\\.\PHYSICALDRIVE2: OK
\\.\PHYSICALDRIVE3: OK
Is there an easy way to restrict results to \.\PHYSICALDRIVE0?
Basically, I am trying to return a simple "OK" for Physical Drive 0's health.
I tried the following:
$WMI = Get-WMIObject -Class Win32_DiskDrive
ForEach ($Drive in $WMI | Where $Drive.DeviceID -Contains "\\.\PHYSICALDRIVE0"){
$Drive.Status
}
But nothing is outputted (at all). How would I restrict the status output to just the Physical Drive 0 from DeviceID?
I would do it this way:
$WMI = Get-WMIObject -Class Win32_DiskDrive
ForEach ($Drive in $WMI) {
if ($Drive.DeviceID -contains "\\.\PHYSICALDRIVE0") {
$Drive.Status
}
}
You look thru $wmi and check if each value contains this specific value.
If you have a match, it will show the Disk status.
There are many ways, depending on how specific you wish to be:
Get-WMIObject -Class Win32_DiskDrive | Where-Object DeviceID -eq '\\.\PHYSICALDRIVE0'
Get-WMIObject -Class Win32_DiskDrive | Where-Object DeviceID -match 'E0$'
Get-WMIObject -Class Win32_DiskDrive | Where-Object Index -eq 0
If you wish these to run on older versions of PowerShell, then use the older syntax by placing each "test" into a scriptblock:
Get-WMIObject -Class Win32_DiskDrive | Where-Object { $_.DeviceID -eq '\\.\PHYSICALDRIVE0' }
Basically, I'm trying to read a BIOS setting and then with the if condition, if it matches to execute another command.
It works fine with other variables, it is just with this one.
#This Script will check for VT and VTD on Lenovo machines and enable them
#if the current value is disabled.
#Run Set-ExecutionPolicy Unrestricted first.
#Run As administrator
#Check the current values
$VT= gwmi -class Lenovo_BiosSetting -namespace root\wmi |
Where-Object {$_.CurrentSetting.split(",",[StringSplitOptions]::RemoveEmptyEntries) -eq "VirtualizationTechnology"} |
Format-List CurrentSetting
$VTD= gwmi -class Lenovo_BiosSetting -namespace root\wmi |
Where-Object {$_.CurrentSetting.split(",",[StringSplitOptions]::RemoveEmptyEntries) -eq "VTdFeature"} |
Format-List CurrentSetting
#Modify the values
#$EnabledVT= (gwmi -class Lenovo_SetBiosSetting -namespace root\wmi).SetBiosSetting("VirtualizationTechnology,Enable")
#$EnableVTD= (gwmi -class Lenovo_SetBiosSetting -namespace root\wmi).SetBiosSetting("VTdFeature,Enable")
#$SaveBios=(gwmi -class Lenovo_SaveBiosSettings -namespace root\wmi).SaveBiosSettings()
#Check if VT is disabled and enable it if it is.
Echo "Virtualization current settings are below"
Write-output $VT
IF ($VT -like "*Disable*") {
"this is not working"
} else {
"Setting is already set to enabled, no changes made."
}
#Check if VTD is disabled and enable it if it is.
Write-output $VTD
IF ($VTD -like "*,Disable") {
this is not working
} else {
"Setting is already set to enabled, no changes made."
}
#Save bios settings.
$SaveBios
Write-host "Check completed, Please restart computer for changes to take effect if any changes were made. "
I have tried different conditions to match exactly or the like or the match but nothing seems to be able to find anything.
So, here's the issue that you are having. You are piping the output of your command to Format-List, and storing that info in your variable. Don't do that. The Format-* cmdlets should be used to format things for output to the console, not for storing data for use later. Instead remove that part, and then reference the CurrentSetting property of the object.
$VT= gwmi -class Lenovo_BiosSetting -namespace root\wmi | Where-Object {$_.CurrentSetting.split(“,”,[StringSplitOptions]::RemoveEmptyEntries) -eq “VirtualizationTechnology”}
$VTD= gwmi -class Lenovo_BiosSetting -namespace root\wmi | Where-Object {$_.CurrentSetting.split(“,”,[StringSplitOptions]::RemoveEmptyEntries) -eq “VTdFeature”}
IF ($VT.CurrentSetting -like "*Disable*") {"this is now working"}
else {"Setting is already set to enabled, no changes made."}
This will function as desired.
Instead of Format-List, use Select-Object -ExpandProperty:
$VT = gwmi -class Lenovo_BiosSetting -namespace root\wmi | Where-Object {$_.CurrentSetting.split(“,”,[StringSplitOptions]::RemoveEmptyEntries) -eq “VirtualizationTechnology”} | Select-Object -ExpandProperty CurrentSetting
$VTD = gwmi -class Lenovo_BiosSetting -namespace root\wmi | Where-Object {$_.CurrentSetting.split(“,”,[StringSplitOptions]::RemoveEmptyEntries) -eq “VTdFeature”} | Select-Object -ExpandProperty CurrentSetting
Help me pls,
i'am going my mind, what is wrong in my script??? i'm testing this script under Windows 2012.
There is shares:
\FS-SHARES\TEST12
\FS-SHARES\TEST15
\FS-SHARES\TEST20
function StripShare($sharename) {
$res=$sharename -replace ".*\\(.*)" , '$1'
return $res
}
function getShareProp($sharename) {
$s=""
Get-WmiObject -class Win32_Share -computername "." -filter "Type=0" | % {
if (stripshare($_.name) -eq $sharename) {
$s=$_.name
}
}
return $s
}
getShareProp(stripshare("s:\TEST12"))
OUTPUT
----
TEST20
getShareProp(stripshare("s:\TEST15"))
---
OUTPUT
TEST20
Solved!
p.s. Something strange with pipeline in powershell 3.
function getShareProp($sharename) {
$s=""
$a=Get-WmiObject -class Win32_Share -computername "." -filter "Type=0"
foreach ($_ in $a) {
$t=stripshare($_.name)
if ($t -eq $sharename) {
$s=$_.name
}
}
return $s
}
I'm not sure I understand what you are attempting to accomplish, but I think just adding to the filter will mostly provide the same functionality.
Get-WmiObject -class Win32_Share -computername "." -filter "Type=0 and name='TEST12'" | select Name
or if you're looking for the Share name associated with a physical path.
Get-WmiObject -class Win32_Share -computername "." -filter "Type=0 and path='S:\TEST12'" | select Name
I'm pulling my hair out here, because I just can't seem to get this to work, and I can't figure out how to google this issue. I'm running Powershell 2.0. Here's my script:
$computer_names = "server1,server2"
Write-Output "Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}"
Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
The last command gives the error:
Invoke-Command : One or more computer names is not valid. If you are trying to
pass a Uri, use the -ConnectionUri parameter or pass Uri objects instead of
strings.
But when I copy the output of the Write-Output command to the shell and run that, it works just fine. How can I cast the string variable to something that Invoke-Command will accept? Thanks in advance!
Jamey and user983965 are correct, in that your declaration is wrong. However foreach here is not mandatory. If you just fix your array declaration like this, it will work:
$computer_names = "server1","server2"
Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
You declared your array incorrectly. Put a comma between strings and pipe it to for-each like:
$computer_names = "server1", "server2";
$computer_names | %{
Write-Output "Invoke-Command -ComputerName $_ -ScriptBlock {
...snip
If you're getting an array of computers from active directory too - like this:
$computers = Get-ADComputer -filter {whatever}
Make sure you remember to select/expand the results.. like this:
$Computers= Get-ADComputer -filter * | Select-Object -ExpandProperty Name
Then...
Invoke-Command -ComputerName $Computers -ScriptBlock {Do Stuff}
have you tried:
$computer_names = "server1" , "server2"
foreach ($computer in $computer_names)
{
Write-Output "Invoke-Command -ComputerName $computer -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}"
Invoke-Command -ComputerName $computer -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
}