Using where DeviceName -contains and getting no results - powershell

I'm trying to get the content from the boot order list with the following command but $pr is empty and there is no error message:
$pr = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder |select -Expand DeviceName| Where DeviceName -contains "*Target:0, Lun:0)"^
Where's my mistake?
When I run this:
$pr = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder |select -Expand DeviceName
It returns this:
Generic USB Boot
Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port 331i Adapter - NIC (PXE IPv6)
Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port 331i Adapter - NIC (PXE IPv4)
Slot 3 Port 1 : HP Ethernet 10Gb 2-port 530T Adapter - NIC (PXE IPv6)
Embedded RAID 1 : Smart Array P440ar Controller - 279.43 GiB, RAID 1 Logical Drive(Target:0, Lun:1)
Windows Boot Manager
Internal USB 1 : HPE Dual 8GB MicroSD EM USB Kit - USB RAID LUN
Embedded RAID 1 : Smart Array P440ar Controller - 279.37 GiB, RAID 1 Logical Drive(Target:0, Lun:0)
Embedded FlexibleLOM 1 Port 1 : HP FlexFabric 10Gb 2-port 533FLR-T Adapter - NIC (PXE IPv6)
Embedded RAID 1 : Smart Array P440ar Controller - 279.37 GiB, RAID 1 Logical Drive(Target:0, Lun:2)
Embedded FlexibleLOM 1 Port 1 : HP FlexFabric 10Gb 2-port 533FLR-T Adapter - NIC (PXE IPv4)
Slot 3 Port 1 : HP Ethernet 10Gb 2-port 530T Adapter - NIC (PXE IPv4)

Use -like instead of -contains.
Contains should be used when you want to determine if a value is in a collection of values. Like should be used (with wildcard characters) when you want to partially match a string. This is a common PowerShell misconception.
You've also used -ExpandProperty on DeviceName after which have a collection of strings without that property name. As such you need to do this in your Where:
| Where {$_ -like "*Target:0, Lun:0)"}
$_ is a special placeholder that represents the current item in the pipeline, which with a system.string object is (by default) its string value.

Here is a bigger picture of my little project.
And what i´ve reached so far.
It will find more makings in the near future.
##
# The following Script is checking the current HPPowerProfile Setting on the local Server
# and set it to Maximum_Performance if its not already set.
#
# Also it set´s the UEFIBootOrder to HDD firts (Target:0, Lun:0)
##
# Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\mysecurestring.txt
# Set Access Credentials
$username = "*******"
$password = cat C:\mysecurestring.txt | Convertto-SecureString
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
# Set ILO Hostname
$sv = hostname
$ri = $sv.replace("YY","XX")
# Connect to HPBios
$conObj = Connect-HPBIOS $ri -Credential $cred -DisableCertificateAuthentication
# Check current BootMode (depending on Boot Mode, other cmdlet´s will be executed)
$bm = $conObj | Get-HPBIOSBootMode | select -Expand BootMode
if ( $bm -eq "UEFI Mode")
{echo "UEFI"}
else
{echo "echo $bm"}
# Check current Server Power Profile
$pr = Get-HPBIOSPowerProfile $conObj | select -Expand HPPowerProfile
if (-not( $pr -eq "Maximum Performance"))
{$conObj | Set-HPBIOSPowerProfile -HPPowerProfile Maximum_Performance}
else
{echo "No change needed"}
# Find HDD and move it to Boot Order #1
$bo = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder | Where DeviceName -like "*Drive(Target:0, Lun:0)" | select -Expand Index
if (-not( $bo -eq "1"))
{$conObj | Set-HPBIOSUEFIBootOrder -UEFIBootOrder "$bo,1"}
else
{echo "No change needed"}

Related

Logic issue in powershell if statement

Not sure why but my if statement not go on the proper direction, in the following example one interface is disabled but it still shows the True value, however it should show the False one.
I have the following interfaces:
get-netadapter
Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
---- -------------------- ------- ------ ---------- ---------
Embedded FlexibleLOM ...2 HPE FlexFabric 10Gb 4-port 536FLR-...#2 10 Disabled 08-xxx-62 10 Gbps
Embedded FlexibleLOM ...1 HPE FlexFabric 10Gb 4-port 536FLR-...#4 11 Up 08-xxx-60 10 Gbps
You can see one is disabled.
This is the script:
$vmswitch1stinterface = (Get-VMSwitchTeam -Name "Teaming").NetAdapterInterfaceDescription|select -first 1
$vmswitch2ndinterface = (Get-VMSwitchTeam -Name "Teaming").NetAdapterInterfaceDescription|select -last 1
$1stinterfacestatus = Get-NetAdapter -InterfaceDescription $vmswitch1stinterface|select Status
$2ndinterfacestatus = Get-NetAdapter -InterfaceDescription $vmswitch2ndinterface|select Status
if (($1stinterfacestatus -and $2ndinterfacestatus) -eq 'up')
{
Write-Host "OK: NIC ports are up (VMSwitch)"
Exit 0
} else
{
Write-Host "WARNING: An interface is down! Please check in the list which one is not UP:"
Get-NetAdapter -InterfaceDescription $vmswitch1stinterface|Select-Object InterfaceDescription, Status
Get-NetAdapter -InterfaceDescription $vmswitch2ndinterface|Select-Object InterfaceDescription, Status
Exit 1
}
The values are as follow for easy determination:
$vmswitch1stinterface: HPE FlexFabric 10Gb 4-port 536FLR-T Adapter #4
$vmswitch2ndinterface: HPE FlexFabric 10Gb 4-port 536FLR-T Adapter #2
$1stinterfacestatus
Status
------
Up
$2ndinterfacestatus
Status
------
Disabled
The result of this script is the following which is not correct:
OK: NIC ports are up (VMSwitch)
What I'm missing in the logic?
$1stinterfacestatus and $2ndinterfacestatus are PSCustomObjects and it can have properties. In your case both objects has Status property which you can access it using . notation.(ie, $yourPSCustomObject.Status).
I think you intended to test if both interfaces are up, which you can do by
if (($1stinterfacestatus.status -eq 'up' -and $2ndinterfacestatus.status -eq 'up')) {
Write-Output "Both interfaces are up"
}

PowerShell Scripting for System Center VMM

Am new to scripting kindly help me write a script that will connect to VMM and get details such as below.
Name : ABC Machine
CPUCount : 8
Memory : 8192
DynamicMemoryEnabled : False
VHDType : DynamicallyExpanding
MaximumSize : 214748364800
Size : 4194304
Location : C:\ClusterStorage\Volume3\CRB\CRB Test Machine_disk_1.vhdx
Classification : Silver
VHDType : DynamicallyExpanding
MaximumSize : 4748364800
Size : 41304
Location : C:\ClusterStorage\Volume2\CRB\CRB Test Machine_disk_2.vhdx
Classification : Silver
I have been able to get individual commands to get the info however I am not able to make a script that will do it for all VMs and convert disk sizes to GB
My working commands are
Get-SCVirtualMachine -Name "ABC Machine" | select Name, CPUCount, Memory, DynamicMemoryEnabled | fl
$DiskINfo = Get-SCVirtualDiskDrive -VMMServer "abc.abcgroupcloud.com" -VM "ABC Machine"
$DiskINfo.VirtualHardDisk | select VHDType, MaximumSize, Size, Location, Classification
1- create an array with all the VM names (or read it from a file with get-content)
2- use a foreach loop to excecute you script over all these VM
3- use a calulated property to display the size in Gb
$computers=#("ABC machine","XYZ machine")
$computers | foreach-object {
Get-SCVirtualMachine -Name $_ | select Name, CPUCount, Memory, DynamicMemoryEnabled | fl
$DiskINfo = Get-SCVirtualDiskDrive -VMMServer "abc.abcgroupcloud.com" -VM $_
$DiskINfo.VirtualHardDisk | select VHDType, MaximumSize, #{Name="Size in Gb";Expression={$($_.size)Mb / 1Gb}}, Location, Classification
}
Old question, but just to add some info.
This will get all the Virtual Machines in your host group in VMM, after entering the correct host group name.
$VMs will be the array, which will contain all the details you are after.
$hg = Get-SCVMHostGroup -Name "My Hostgroup Name"
$hosts = Get-SCVMHost -VMHostGroup $hg
$VMs = $null
ForEach ($h in $hosts)
{
$VMs += Get-SCVirtualMachine -VMHost $h
}

Get iscsi mapped drive letter from iscsi initiator name

In PowerShell I'm trying to get the drive letter that an ISCSI target is mapped to. I'm using the following to get the ISCSI initiator name.
Get-IscsiTarget | ? {$_.IsConnected -eq $True} | Select -ExpandProperty NodeAddress
I have tried using Get-Disk | Select * and Get-PSDrive | Select * but these cmdlets do not seem to have any fields that I can link a target to, to obtain its drive letter.
As long as you have one active partition (not including reserved) per ISCSI target, you can use the following to match an ISCSI address to its corresponding drive letter.
foreach ($disk in (Get-Disk | ?{$_.BusType -Eq "iSCSI"})){
$DriveLetter = ($disk | Get-Partition | ?{$_.Type -eq "Basic"}).DriveLetter
$ISCSI = $disk | Get-IscsiSession
[pscustomobject]#{
DiskNumber=$disk.Number;
DriveLetter=$DriveLetter;
InitiatorNodeAddress=$ISCSI.InitiatorNodeAddress;
InitiatorIP=$ISCSI.InitiatorPortalAddress;
Size=$disk.Size;
}
}
This will check all connected ISCSI disks and get their corresponding drive letter, then it will put all the information into a customer PowerShell object and return it.

CPU core count from a Hyper-V host under SCVMM 2012

I asked this question on the TechNet forums without any luck (link), so I thought I'd see if anyone around here might have an answer:
At our company we have a VMM server (SCVMM 2012) controlling two physical Hyper-V hosts (let's call them HOST01 and HOST02). I'm trying to get some information about HOST01 via PowerShell queries on the VMM server:
Get-VMHost -ComputerName HOST01
..which among other things returns some CPU info:
...
LogicalProcessorCount = 12
PhysicalCPUCount = 1
CoresPerCPU = 12
L2CacheSize = 2048
L3CacheSize = 20480
BusSpeed = 100
ProcessorSpeed = 2294
ProcessorModel = Xeon
ProcessorManufacturer = Intel
ProcessorArchitecture = 9
ProcessorFamily = 179
CpuUtilization = 33
...
Now, I happen to know that HOST01 runs on a 6 core CPU with hyperthreading *), so LogicalProcessorCount = 12 is correct, but I expected to see CoresPerCPU = 6 (not 12). Why doesn't VMM show the correct number of physical cores? Am I looking in the wrong place?
Alternatively, is there a way to see whether hyperthreading is activated on the host, so I could divide by 2 as a last resort?
*) HOST01 is our own test server, so I have queried it separately through WMI to get CPU data, but in a production environment we cannot rely on having access to anything but the VMM server.
With Hyper-Threading enabled you get 2 logical processors per core. Since VMM cares only about the number of logical processors I doubt you'll be able to get "lower level" CPU information out of it. To get the actual number of cores for each CPU you have to query the processor information via WMI:
Get-WmiObject Win32_Processor -Computer HOST01 |
select Name, NumberOfCores, NumberOfLogicalProcessors
Edit: In a situation where user and host have no access at all to the hypervisors I don't think you'll be able to obtain that information. Not without making some changes to the infrastructure, that is. The following might provide a viable approach, if you have someone who can set it up on the VMM host for you.
Periodically collect the information from the hypervisors with a scheduled task running the following script on the VMM host:
$datafile = 'C:\path\to\data.csv'
$hypervisors = Get-SCVMHost | select -Expand Name
Get-WmiObject Win32_Processor -Computer $hypervisors |
select Name, NumberOfCores | Export-Csv $datafile -NoType -Encoding ASCII
Publish the content of the datafile with a custom web server on the VMM host:
$port = 8000
$datafile = 'C:\path\to\data.csv'
$lastUpdate = Get-Date 0
$data = ''
function Get-Data {
$filedate = (Get-Item $datafile).LastWriteTime
if ($filedate -gt $lastUpdate) {
$script:data = Import-Csv 'C:\Temp\text.csv' | ConvertTo-Json
$script:lastUpdate = $filedate
}
$script:data
}
If (-not (Test-Path -LiteralPath $datafile)) {
New-Item -ItemType File -Path $datafile | Out-Null
}
$listener = New-Object Net.HttpListener
$listener.Prefixes.Add("http://+:$port/")
$listener.Start()
while ($listener.IsListening) {
$response = $listener.GetContext().Response
$response.Headers.Add('Content-Type', 'text/plain')
$buffer = [Text.Encoding]::ASCII.GetBytes((Get-Data))
$response.ContentLength64 = $buffer.Length
$response.OutputStream.Write($buffer, 0, $buffer.Length)
$response.Close()
}
$listener.Stop()
If the Windows Firewall is enabled on the VMM host you need to open the listener port in it.
With that in place you can access the data from a server or workstation like this:
Invoke-WebRequest 'http://vmmserver:8000/' | select -Expand Content |
ConvertFrom-Json

Setting Static IP on NICs - Powershell

I am creating a script which will run through a lot of the basic tasks when commissioning a new server. Now most servers have multiple NICs these days and I need to question the user (using the script) what NIC they want to assign the IP to.
At the moment I have:
$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true}
Which will put the NICs into $NICs I believe. However from here I want to print them out to the user, and then somehow assign a value to each NIC, like an index, so the user can type in, "1" or "2" so tell the script what NIC to apply the Ip configuration to which will be done like:
If($ipQuestion -eq "Y") {
$ipAddr = Read-Host "Enter IP Address: "
$subnet = Read-Host "Enter Subnet: "
$dns = Read-Host "Enter DNS: "
Write-Host "Multiple DNS servers?" -ForegroundColor Green
$multipleDNSServersQuestion = Read-Host
If($multipleDNSServersQuestion -eq 'Y'){
$dns2 = Read-Host "Enter Secondary DNS: "
}
$dGateway = Read-Host "Enter Default Gateway: "
}
$NIC.EnableStatic($ipAddr, $subnet)
$NIC.SetGateways($dGateway)
$NIC.SetDNSServerSearchOrder($dns, $dns2)
$NIC.SetDynamicDNSRegistration("TRUE")
Any ideas?
If you ensure $NICS is always an array, you can use the array index to specify each NIC. To ensure it is always an array do this:
$NICs = #(Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true})
Then print out the info like so:
PS> $NICS = #(Get-WMIObject Win32_NetworkAdapterConfiguration)
PS> $NICS | Foreach {$i=-1}{$i++;$_} | ft #{n='index';e={$i}},Description,ServiceName
index Description ServiceName
----- ----------- -----------
0 WAN Miniport (L2TP) Rasl2tp
1 WAN Miniport (SSTP) RasSstp
2 WAN Miniport (IKEv2) RasAgileVpn
3 WAN Miniport (PPTP) PptpMiniport
4 WAN Miniport (PPPOE) RasPppoe
5 WAN Miniport (IP) NdisWan
6 WAN Miniport (IPv6) NdisWan
7 WAN Miniport (Network Monitor) NdisWan
8 Microsoft Kernel Debug Network Adapter kdnic
9 RAS Async Adapter AsyncMac
10 Broadcom NetXtreme Gigabit Ethernet b57nd60a
11 Microsoft ISATAP Adapter tunnel
12 Microsoft Teredo Tunneling Adapter tunnel
13 Microsoft 6to4 Adapter tunnel
14 Microsoft ISATAP Adapter tunnel
Then access each NIC like so:
$NICS[$selectedIndex]
$NICs = #(Get-WMIObject Win32_NetworkAdapterConfiguration ...)
will make $NICs an array, which can be accessed by (zero-based) index:
$NICs[0] # <-- first interface
$NICs[1] # <-- second interface
...
The way I would do it. If you have a look to the network connexions panel in the internet connexions. You can see the string the user know for his devices :
So in a dialog with the user I would give this name retreiving it with win32_NetworkAdapter joinning Win32_NetworkAdapterConfiguration with Index.
$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true}
$NICs | % {$i = (Get-WmiObject win32_NetworkAdapter -Filter "index=$($_.index)").NetConnectionID; $_} | ft #
{n='index';e={$i}},Description,ServiceName
index Description ServiceName
----- ----------- -----------
NET1 Intel(R) 82567LM Gigabit Network Conne... e1yexpress