Logic issue in powershell if statement - powershell

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"
}

Related

Powershell query results list

The Powershell script provides results table below. We need to find out if VM is reachable or not, so I would like to check if "Time" column is not empty.
The question:
How to check if "Time(ms)" has value? how to query any column or row in such a cases in general?
$result = Test-ConnectionAsync "MyVm"
C:\$result
Source Destination IPV4Address IPV6Address Bytes Time(ms)
------ ----------- ----------- ----------- ----- --------
SourceVM MyVM 10.20.20.10 32 207
SourceVM MyVM 10.20.20.10 32 207
SourceVM MyVM 10.20.20.10 32 207
SourceVM MyVM 10.20.20.10 32 207
thank you!
You can use the Where-Object functionality that checks the value of any column of the given row. If you want to find out what column names are supposed to be, use Get-Member to get all the properties or methods of that object.
# Get all the properties of $result[0]
$result[0] | Get-Member
# Among other things, you will ResponseTime as one of the properties you can use.
# Check if Time(ms) has any value. Following will give you only those rows that match the condition
#Original where statement
#$result | Where-Object { $_.ResponseTime -ne $null }
#Updated where statement
$result | Where-Object { $null -ne $_.ResponseTime }

how to format Powershell output in specific way?

I need to scan my network for specific processes on servers. I've done this script:
28..31 | ForEach-Object { Get-Process -ComputerName "192.168.0.$_" -Name svc* }
Now how can I format output so it shows on which IP address found process shown? Thank you.
I suggest switching to PowerShell's remoting, because:
it provides a framework for executing any command remotely - rather than relying on individual cmdlets to support a -ComputerName parameter and uses a firewall-friendly transport.
it will continue to be supported in PowerShell [Core] v6+, where the cmdlet-individual -ComputerName parameters aren't supported anymore; this obsolete remoting method uses an older, less firewall-friendly form of remoting that the - obsolete since v3 - WMI cmdlets also use (the latter were replaced by the CIM cmdlets).
It is therefore better to consistently use the firewall-friendly PowerShell remoting with its generic remoting commands (Invoke-Command, Enter-PSSession, ...).
If you use Invoke-Command to target (multiple) remote computers, the objects returned automatically contain and display the name of the originating computer, via the automatically added .PSComputerName property:
# Create the array of IP addresses to target:
$ips = 28..31 -replace '^', '192.168.0.'
# Use a *single* Invoke-Command call to target *all* computers at once.
# Note: The results will typically *not* reflect the input order of
# given IPs / computer names.
Invoke-Command -ComputerName $ips { Get-Process -Name svc* }
You'll see output such as the following - note the PSComputerName column:
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName PSComputerName
------- ------ ----- ----- ------ -- -- ----------- --------------
1013 18 7464 13732 52.72 8 0 svchost 192.168.0.30
...
Note that you can suppress automatic display of the .PSComputerName property with Invoke-Command's -HideComputerName parameter.
However, the property is still available programmatically, which allows you to do the following:
Invoke-Command -ComputerName $ips { Get-Process -Name svc* } -HideComputerName |
Format-Table -GroupBy PSComputerName
This yields display output grouped by computer name / IP:
PSComputerName: 192.168.0.30
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1013 18 7464 13732 52.72 8 0 svchost
...
PSComputerName: 192.168.0.28
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
1007 17 7112 12632 65.45 11 0 svchost
...
If you wanted to sort by IP address before grouping, you could insert | Sort-Object { [version] $_.PSComputerName }[1] before the Format-Table call.
For sorting by computer names, just
| Sort-Object PSComputerName would do.
[1] Casting to [version] is a trick to ensure proper sorting of IP addresses; IP address strings can be interpreted as [version] (System.Version) instances, and such instances are directly comparable, using the numeric values of the version components (first by .MajorVersion, then by .MinorVersion, ...)
here's one way to do the job. [grin] what it does ...
builds the ip final octet range
sets the IPv4 base octets
builds the list of processes to search for
sets the "no response" text
iterates thru the 4th octet range
builds the IPv4 address
checks to see if it is online/responding
if so, gets the hostname
for my version of PoSh [win7, ps5.1] the Get-Process cmdlet will NOT accept an ip address. a hostname is required.
corrects for the damaged hostname returned when one uses ATT for inet service
creates an ordered hashtable to use for building the property list
builds the various props as needed
converts the hashtable to a PSCustomObject
sends that to the $Results collection
shows it on screen
sends it to a CSV file
here's the code ...
$4thOctetRange = 64..66
$IpBase = '192.168.1'
$ProcessList = #(
'AutoHotKey'
'BetterNotBeThere'
'DisplayFusion'
'Foobar2000'
)
$NoResponse = '__n/a__'
$Results = foreach ($4OR_Item in $4thOctetRange)
{
$Ip = '{0}.{1}' -f $IpBase, $4OR_Item
$Online = Test-Connection -ComputerName $Ip -Count 1 -Quiet
if ($Online)
{
# getting the hostname is REQUIRED by my version of Get-Process
# it will not accept an IP address
# version info = win7, ps5.1
# this may need adjusting for your returned hostname
# mine shows Hostname.attlocal.net
# that is not valid with any query i make, so i removed all after the 1st dot
$HostName = ([System.Net.Dns]::GetHostByAddress($Ip)).HostName.Split('.')[0]
}
else
{
$HostName = $NoResponse
}
$TempProps = [ordered]#{}
$TempProps.Add('IpAddress', $Ip)
$TempProps.Add('Online', $Online)
$TempProps.Add('HostName', $HostName)
foreach ($PL_Item in $ProcessList)
{
if ($TempProps['Online'])
{
# if the process aint found, the "SilentlyContinue" forces a $Null
# the "[bool]" then coerces that to a "False"
$TempProps.Add($PL_Item, [bool](Get-Process -ComputerName $HostName -Name $PL_Item -ErrorAction SilentlyContinue))
}
else
{
$TempProps.Add($PL_Item, $NoResponse)
}
}
# send the object out to the $Results collection
[PSCustomObject]$TempProps
}
# send to screen
$Results
# send to CSV file
$Results |
Export-Csv -LiteralPath "$env:TEMP\Senator14_RemoteProcessFinder.csv" -NoTypeInformation
truncated screen output ...
IpAddress : 192.168.1.65
Online : True
HostName : ZK_01
AutoHotKey : True
BetterNotBeThere : False
DisplayFusion : True
Foobar2000 : True
IpAddress : 192.168.1.66
Online : False
HostName : __n/a__
AutoHotKey : __n/a__
BetterNotBeThere : __n/a__
DisplayFusion : __n/a__
Foobar2000 : __n/a__
csv file content ...
"IpAddress","Online","HostName","AutoHotKey","BetterNotBeThere","DisplayFusion","Foobar2000"
"192.168.1.64","False","__n/a__","__n/a__","__n/a__","__n/a__","__n/a__"
"192.168.1.65","True","ZK_01","True","False","True","True"
"192.168.1.66","False","__n/a__","__n/a__","__n/a__","__n/a__","__n/a__"

Enable Jump Frame

I am trying to create a powershell script to enable Jumpframe on Openstack windows VM's. The command to find active network card and also the current MTU value also the command to change MTU value all below.
From the below command I am first finding the active network card , then trying to find the MTU value of that NIC and if I found MTU value less than 1600 I need that to be changed to 9000.
PS C:\> **wmic nic where "netconnectionid like '%'" get netconnectionid**
NetConnectionID
Ethernet
PS C:\> **netsh.exe int ipv4 show subint**
MTU MediaSenseState Bytes In Bytes Out Interface
------ --------------- --------- --------- -------------
4294967295 1 0 1400 Loopback Pseudo-Interface 1
1200 1 1335974344 5867793 Ethernet
PS C:\> **netsh int ipv4 set subint "Ethernet" mtu=9000 store=persistent**
Can anyone let me know how can I write a condition to accomplish what I am looking for ?
Try the following:
$enabledAdaptersNames = Get-NetAdapter |? {$_.status -eq "Up" -or $_.status -eq "Disconnected"} | Select -ExpandProperty name
Get-NetIPInterface |? { $enabledAdapterNames -contains $_.InterfaceAlias -and $_.NlMtu -lt 1600} | Set-NetIPInterface -NlMtuBytes 9000

Using where DeviceName -contains and getting no results

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"}

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