IP Address Input from Jenkins to Variable powershell - powershell

I Have Jenkins job that asks for IP Address
$ip = $env:Lan_ip
what the user enter goes to $ip
now $ip is 192.168.10.10 for Example
now I'm trying to insert this variable to FortiGate SSH
Invoke-SshCommand $Firewall -command ‘config system interface
edit port1
set ip $ip 255.255.255.0
end’
but he can not read the $ip I need to make it like INT separate with .
im getting this Error
node_check_object fail! for ip $ip
how can i convert the sting im getting from the user when he enter the ip address in for example --> 192.168.10.10
to usable variable in the code

From what I gather from here is that you need to give the subnet mask as a CIDR-formatted subnet mask like 255.255.255.0/24
To get that CIDR value off a subnet IP address, you can use this function:
function Get-SubnetMaskLength ([string]$SubnetMask) {
# $cidr = Get-SubnetMaskLength "255.255.240.0" --> 20
$result = 0
[IPAddress]$ip = $SubnetMask
foreach ($octet in $ip.GetAddressBytes()) {
while ($octet) {
$octet = ($octet -shl 1) -band [byte]::MaxValue
$result++
}
}
$result
}
So
$subNet = '255.255.255.0'
$cidr = Get-SubnetMaskLength $subNet # --> 24
$subNetAndCidr = '{0}/{1}' -f $subNet, $cidr # --> 255.255.255.0/24
P.S. Always use straight quotes instead of the curly thingies ‘ and ’ in code!

Related

Powershell IP address range

I need to help with my code which is write in Powershell. Program should generate IP addresses in range. For example from 10.4.254.250 to 10.4.255.255.
When I have the same subnet (from 10.4.255.x to 10.4.255.x), all is correct. Problem starts when I have different subnet (from 10.4.254.250 to 10.4.255.255).
Output is invalid. Try it please. Thank you, for your help.
Correct output should be, that ip address which is 10.4.255.X starts from 1. Now starts from 250 to 255.
I need to get all ip addresses from variable $from to variable $to. When IP address in the same subnet $from = "10.4.255.1" $to = "10.4.255.1" all is correct. Problem starts, when different subnet $from = "10.4.254.250" $to = "10.4.255.255"
Look at my code bellow:
$from = "10.4.254.250"
$to = "10.4.255.255"
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
foreach ($Ip_Adresa_A in $Ip_Adresa_Od[0]..$Ip_Adresa_Do[0])
{
foreach ($Ip_Adresa_B in $Ip_Adresa_Od[1]..$Ip_Adresa_Do[1])
{
foreach ($Ip_Adresa_C in $Ip_Adresa_Od[2]..$Ip_Adresa_Do[2])
{
foreach ($Ip_Adresa_D in $Ip_Adresa_Od[3]..$Ip_Adresa_Do[3])
{
$Ip_Adresa_Pocitace = "$Ip_Adresa_A.$Ip_Adresa_B.$Ip_Adresa_C.$Ip_Adresa_D"
$Ip_Adresa_Pocitace
}
}
}
}
Wrong output is:
10.4.254.250
10.4.254.251
10.4.254.252
10.4.254.253
10.4.254.254
10.4.254.255
10.4.255.250
10.4.255.251
10.4.255.252
10.4.255.253
10.4.255.254
10.4.255.255
Working with IP addresses and ranges is complicated, and something I try to avoid if a program/software I am using does it already. Here are some functions that I wrote a while back that convert the addresses to decimal values, that are easier to manipulate. There are probably better, more precise solutions than this, but it will also return a range based off an address with a Subnet address or CIDR mask too. It should also cover the case #vonPryz mentioned where the addresses are across .24 CIDR ranges.
function Find-IPRange {
<#
.SYNOPSIS
Determines all the IP address in a given range or subnet.
.DESCRIPTION
This function can evaluate a set of addresses based of the following three options:
Range - What IP addresses are between this and that address
Mask - What are the IP addresses given a particular IP address and mask, i.e. 24, 25.
Subnet - What are the IP addresses given a particular IP address and subnet address, i.e 255.255.0.0, 255.255.255.192
You have to specify an IP address to use the subnet and mask options. For the range you have to specify two addresses.
.PARAMETER Start
Start address of an IP range
.PARAMETER End
End address of an IP range
.PARAMETER IP
Any valid ip address
.PARAMETER Subnet
A valid Subnet IP address i.e. 255.255.255.0, 255.255.0.0
.PARAMETER Mask
A valid net mask from 0 to 32
.EXAMPLE
Find-IPRange -IP 192.168.0.4 -mask 30
.EXAMPLE
Find-IPRange -Start 192.168.1.250 -End 192.168.2.5
.EXAMPLE
Find-IPRange -IP 10.100.100.10 -Subnet 255.255.255.240
#>
[CmdletBinding(DefaultParameterSetName = "Range")]
Param (
[Parameter(Mandatory = $true, ParameterSetName = "Range")]
[System.Net.IPAddress]
$Start,
[Parameter(Mandatory = $true, ParameterSetName = "Range")]
[System.Net.IPAddress]
$End,
[Parameter(Mandatory = $true, ParameterSetName = "Mask")]
[Parameter(Mandatory = $true, ParameterSetName = "Subnet")]
[System.Net.IPAddress]
$IP,
[Parameter(Mandatory = $true, ParameterSetName = "Subnet")]
[System.Net.IPAddress]
$Subnet,
[Parameter(Mandatory = $true, ParameterSetName = "Mask")]
[ValidateRange(0, 32)]
[System.Int32]
$Mask,
[Parameter(ParameterSetName = "Mask")]
[Parameter(ParameterSetName = "Subnet")]
[System.Management.Automation.SwitchParameter]
$ReturnRange
)
Begin {
# If the user specifies a mask, then convert it to a subnet ip address
if ($Mask) {
$Binary = ("1" * $Mask) + ("0" * (32 - $Mask))
$Decimal = [System.Convert]::ToInt64($Binary, 2)
[System.Net.IPAddress]$Subnet = ConvertFrom-IntToIP -Decimal $Decimal
}
}
Process {
# If we're looking at a subnet, we need to establish the start address and the broadcast address for it. We're using bitwise operators to do this.
if ($PSCmdlet.ParameterSetName -ne "Range") {
# Compare bits where both are a match using the bitwise AND operator
[System.Net.IPAddress]$SubnetAddr = $Subnet.Address -band $IP.Address
# Flip the subnet mask i.e. 0.0.0.255 for 255.255.255.0 by using the bitwise XOR operator and then compare against a bitwise OR operator
[System.Net.IPAddress]$Broadcast = ([System.Net.IPAddress]'255.255.255.255').Address -bxor $Subnet.Address -bor $SubnetAddr.Address
# Return the start and end of a subnet only if requested
if ($ReturnRange) { return $SubnetAddr, $Broadcast }
# Convert the start and end of the ranges to integers
$RangeStart = ConvertFrom-IPToInt -ip $SubnetAddr.IPAddressToString
$RangeEnd = ConvertFrom-IPToInt -ip $Broadcast.IPAddressToString
}
else {
$RangeStart = ConvertFrom-IPToInt -ip $Start.IPAddressToString
$RangeEnd = ConvertFrom-IPToInt -ip $End.IPAddressToString
}
# Loop through the points between the start and end of the ranges and convert them back to IP addresses
for ($Addr = $RangeStart; $Addr -le $RangeEnd; $Addr ++) { ConvertFrom-IntToIP -Decimal $Addr }
}
End {
}
}
function ConvertFrom-IPToInt {
<#
.SYNOPSIS
Converts an IP address to an Int64 value.
.DESCRIPTION
Converts an IP address to an Int64 value.
.PARAMETER IP
A valid IP address to be converted to an integer
.EXAMPLE
ConvertFrom-IPToInt -IP 192.168.0.1
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[System.Net.IPAddress]
$IP
)
Begin {
}
Process {
# Split the IP address in to octets
$Octets = $IP -split "\."
# Multiply the octets based on the maximum number of addresses each octet provides.
[System.Int64]$Decimal = ([System.Int32]$Octets[0] * [System.Math]::Pow(256, 3)) +
([System.Int32]$Octets[1] * [System.Math]::Pow(256, 2)) +
([System.Int32]$Octets[2] * 256) +
([System.Int32]$Octets[3])
}
End {
# Return the int64 value
$Decimal
}
}
function ConvertFrom-IntToIP {
<#
.SYNOPSIS
Converts an Int64 value to an IP address.
.DESCRIPTION
Converts an Int64 value to an IP address.
.PARAMETER Decimal
A decimal value for the IP Address to be converted
.EXAMPLE
ConvertFrom-IntToIP -Decimal 3232235521
#>
[CmdletBinding()]
Param (
[Parameter(Mandatory = $true)]
[System.Int64]
$Decimal
)
Begin {
# Initialise an array for the octets
$Octets = #()
}
Process {
# Work out first octet by dividing by the total number of addresses.
$Octets += [System.String]([System.Math]::Truncate($Decimal / [System.Math]::Pow(256, 3)))
# Work out second octet by the modulus of the first octets total number of addresses divided by the total number of address available for a class B subnet.
$Octets += [System.String]([System.Math]::Truncate(($Decimal % [System.Math]::Pow(256, 3)) / [System.Math]::Pow(256, 2)))
# Work out third octet by the modulus of the second octets total number of addresses divided by the total number of address available for a class C subnet.
$Octets += [System.String]([System.Math]::Truncate(($Decimal % [System.Math]::Pow(256, 2)) / 256))
# Work out fourth octet by the modulus of the third octets total number of addresses.
$Octets += [System.String]([System.Math]::Truncate($Decimal % 256))
# Join the strings to form the IP address
[System.Net.IPAddress]$IP = $Octets -join "."
}
End {
# Return the ip address object
$IP.IPAddressToString
}
}
DISCLAIMER: I am not a network engineer so please feel free to suggest any changes to how the addresses are converted to ints and back. This function also hasn't been through any unit testing, so there may be cases that exist where it does not work.
Example Output:
Find-IPRange -Start 10.4.254.250 -End 10.4.255.255
10.4.254.250
10.4.254.251
10.4.254.252
10.4.254.253
10.4.254.254
10.4.254.255
10.4.255.0
10.4.255.1
10.4.255.2
...truncated
10.4.255.249
10.4.255.250
10.4.255.251
10.4.255.252
10.4.255.253
10.4.255.254
10.4.255.255
Other uses:
Find-IPRange -IP 192.168.0.4 -Mask 28
192.168.0.0
192.168.0.1
192.168.0.2
192.168.0.3
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
192.168.0.8
192.168.0.9
192.168.0.10
192.168.0.11
192.168.0.12
192.168.0.13
192.168.0.14
192.168.0.15
Find-IPRange -IP 192.168.0.4 -Subnet 255.255.255.252
192.168.0.4
192.168.0.5
192.168.0.6
192.168.0.7
You have to convert your IP address to an integer and then in each iteration of a for loop convert the integer to a byte array:
$from = "10.4.254.250"
$to = "10.4.255.255"
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
#change endianness
[array]::Reverse($Ip_Adresa_Od)
[array]::Reverse($Ip_Adresa_Do)
#convert octets to integer
$start=[bitconverter]::ToUInt32([byte[]]$Ip_Adresa_Od,0)
$end=[bitconverter]::ToUInt32([byte[]]$Ip_Adresa_Do,0)
for ($ip=$start; $ip -lt $end; $ip++)
{
#convert integer back to byte array
$get_ip=[bitconverter]::getbytes($ip)
#change endianness
[array]::Reverse($get_ip)
$new_ip=$get_ip -join "."
$new_ip
}
I hope I understand your question. I believe you would like to restart the counter on the 4th octet back to 1 once the 3rd octet iterates from 254 to 255? There's probably a better way to do this but for now hopefully this works. I've added an if statement that resets the range once the final 10.4.254.255 ip is reached. This will allow your loop to include the 10.4.255.x range starting from 1 in the 4th octet until 255 is reached. The while loop condition will be set to false once the final 10.4.255.255 IP is reached and exit.
I hope this helps and provides the desired result.
$from = "10.4.254.250"
$to = "10.4.254.255"
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
$run = "true";
while($run -eq "true")
{
if($Ip_Adresa_Pocitace -eq "10.4.254.255")
{
$from = "10.4.255.1"
$to = "10.4.255.255"
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
}
foreach ($Ip_Adresa_C in $Ip_Adresa_Od[2]..$Ip_Adresa_Do[2])
{
foreach ($Ip_Adresa_D in $Ip_Adresa_Od[3]..$Ip_Adresa_Do[3])
{
$Ip_Adresa_Pocitace = "10.4.$Ip_Adresa_C.$Ip_Adresa_D"
$Ip_Adresa_Pocitace
if($Ip_Adresa_Pocitace -eq "10.4.255.255")
{
$run = "false";
}
}
}
}
Results:
10.4.254.250
10.4.254.251
10.4.254.252
10.4.254.253
10.4.254.254
10.4.254.255
10.4.255.1
10.4.255.2
10.4.255.3
...
10.4.255.249
10.4.255.250
10.4.255.251
10.4.255.252
10.4.255.253
10.4.255.254
10.4.255.255
Solution w/ new parameters.
# Orininal Parameters
# $from = "10.4.254.250"
# $to = "10.4.254.255"
$from = "10.4.253.250"
$to = "10.4.253.255"
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
$run = "true";
while($run -eq "true")
{
if($Ip_Adresa_Pocitace -eq "10.4.253.255")
{
# Orininal Parameters
# $from = "10.4.255.1"
# $to = "10.4.255.255"
$from = "10.4.254.1"
$to = "10.4.254.255"
$end = $to
$Ip_Adresa_Od = $from -split "\."
$Ip_Adresa_Do = $to -split "\."
}
foreach ($Ip_Adresa_C in $Ip_Adresa_Od[2]..$Ip_Adresa_Do[2])
{
foreach ($Ip_Adresa_D in $Ip_Adresa_Od[3]..$Ip_Adresa_Do[3])
{
$Ip_Adresa_Pocitace = "10.4.$Ip_Adresa_C.$Ip_Adresa_D"
$Ip_Adresa_Pocitace
if($Ip_Adresa_Pocitace -eq $end)
{
$run = "false";
}
}
}
}
Results:
10.4.253.250
10.4.253.251
10.4.253.252
10.4.253.253
10.4.253.254
10.4.253.255
10.4.254.1
10.4.254.2
10.4.254.3
...
10.4.254.253
10.4.254.254
10.4.254.255

Powershell - Checking IP Address range based on CSV file

I have been developing VM provision script. My question is : I have here-string like below. now , I want to add route based on ip address range. I am using CSV file with BACKUPIP column.
if an BACKUPIP is in range 10.10.104.1 to 10.10.107.254 it will work route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
if an BACKUPIP is in range 10.10.180.1 to 10.10.185.254 it will work route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
Here is my script:
Import-Csv -Path .\vm.csv -UseCulture -PipelineVariable row |
ForEach-Object -Process {
# Create the VM, store result in $vm
if($($row.IP) -eq '???'){
route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}
else{
route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
}
}
LAST UPDATE :
$rangeFrom104 = '10.10.104.1'
$rangeTo107 = '10.10.107.254'
$rangeFrom180 = '10.10.180.1'
$rangeTo185 = '10.10.185.254'
if (([version]$rangeFrom104) -lt ([version]$($row.IP)) -and ([version]$($row.IP)) -lt ([version]$rangeTo107) )
{
route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}
elseif (([version]$rangeFrom180) -lt ([version]$($row.IP)) -and ([version]$($row.IP)) -lt ([version]$rangeTo185) )
{
route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
}
Really like the [Version] approach Lee_Dailey suggested.
Here's another approach that converts the IP addresses to their numeric values:
function Convert-IPv4ToDecimal ([string]$IpAddress){
# helper function to return the numeric value (uint32) of a dotted IP
# address string used for testing if an IP address is in range.
$n = [uint32[]]$IpAddress.Split('.')
# or use: $n = [uint32[]]([IpAddress]$IpAddress).GetAddressBytes()
# to get the obsolete property ([IpAddress]$IpAddress).Address
# you need to do the math in reversed order.
# return [uint32] ($n[3] -shl 24) + ($n[2] -shl 16) + ($n[1] -shl 8) + $n[0]
# for comparing different ranges as in this question, do not reverse the byte order
return [uint32] ($n[0] -shl 24) + ($n[1] -shl 16) + ($n[2] -shl 8) + $n[3]
}
$startRange1 = Convert-IPv4ToDecimal '172.25.104.1'
$endRange1 = Convert-IPv4ToDecimal '172.25.107.254'
$startRange2 = Convert-IPv4ToDecimal '172.25.112.1'
$endRange2 = Convert-IPv4ToDecimal '172.25.115.254'
Import-Csv -Path .\vm.csv -UseCulture | ForEach-Object {
# Create the VM, store result in $vm
# convert the .BACKUPIP to numeric value
$backupIp = Convert-IPv4ToDecimal $_.BACKUPIP
# test the IP range
if ($backupIp -ge $startRange1 -and $backupIp -le $endRange1) {
Write-Host "BACKUPIP '$($_.BACKUPIP)' is in Range 1"
route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}
elseif ($backupIp -ge $startRange2 -and $backupIp -le $endRange2) {
Write-Host "BACKUPIP '$($_.BACKUPIP)' is in Range 2"
route add yy.yy.yy.yy mask 255.255.255.0 yy.yy.yy.yy -p
}
else {
Write-Warning "No range defined for IP address '$($_.BACKUPIP)'"
}
}
There exists a IPAddress class in .Net:
$MyIPAddress = [System.Net.IPAddress]'10.10.105.7'
$rangeFrom104 = [System.Net.IPAddress]'10.10.104.1'
$rangeTo107 = [System.Net.IPAddress]'10.10.107.254'
If ($rangeFrom104.Address -lt $MyIPAddress.Address -and $MyIPAddress.Address -lt $rangeTo107.Address) {
# route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}
As #Theo commented, the Address property is obsolete:
This property has been deprecated. It is address family dependent.
Please use IPAddress.Equals method to perform comparisons.
I guess this is due to compliance with IPv6 (but I presume that the property won't easily cease to exist as that would probably break some legacy programs). Anyways, that doesn't mean that the whole [System.Net.IPAddress] class is deprecated. Meaning that you might also use the GetAddressBytes method which I think better than a custom function or relying on a (smart! [version]) type but also are both limited to IPv4 (~4 bytes).
With using the GetAddressBytes method, you might simple convert the bytes to a hexadecimal string, which format is comparable (e.g. '10' -gt '0A') as long as the byte arrays are of the same size (e.g. both IPv4):
function Convert-IPAddressToHexadecimal ([Net.IPAddress]$IPAddress, [Switch]$IPv6) {
If ($IPv6) {$IPAddress = $IPAddress.MapToIPv6()}
[BitConverter]::ToString($IPAddress.GetAddressBytes())
}; Set-Alias IP2Hex Convert-IPAddressToHexadecimal
$MyIPAddress = IP2Hex '10.10.105.7' # 0A-0A-69-07
$rangeFrom104 = IP2Hex '10.10.104.1' # 0A-0A-68-01
$rangeTo107 = IP2Hex '10.10.107.254' # 0A-0A-6B-FE
If ($rangeFrom104 -lt $MyIPAddress -and $MyIPAddress -lt $rangeTo107) {
# route add xx.xx.xx.xx mask 255.255.255.0 xx.xx.xx.xx -p
}
If you do need to make your script IPv6 compliant and comparing IP addresses to both IPv4 ranges and IPv6 ranges, you might consider to map all IP addresses to an IPv6 address: using: $MyIPAddress.MapToIPv6().GetAddressBytes() (the -IPv6 switch):
IP2Hex -IPv6 '10.10.105.7' # 00-00-00-00-00-00-00-00-00-00-FF-FF-0A-0A-69-07
Update 2020-09-06:
It is unclear whether the Address property is really obsolete. See: Avoid byte[] allocations once IPAddress.Address is back #18966.
Anyhow, there is a pitfall in using the Address property for comparison as it appears that the address is stored as Big-Endian read from memory as Little-Endian format, see: System.Net.IPAddress returning weird addresses, causing the last byte in 10.10.104.1 (1) to become most significant.
This means that comparing the Address property might give an incorrect result if there are differences between multiple bytes in the concerned IP Addressed:
([IPAddress]'0.0.0.1').Address -lt ([IPAddress]'0.0.1.0').Address
False

How to get IP Address range from subnet and netmask

Team,
I am new to the forum, also new to the development, i am currently using windows 2016, 2012 & 2008 servers in the environment. The script primarily should work on all the environment.
I wanted to find out the IP start ip address and end ip address.
$params = #{
"ComputerName" = "."
"Class" = "Win32_NetworkAdapterConfiguration"
"Filter" = "IPEnabled=TRUE"
}
$netConfigs = Get-WMIObject #params
foreach ( $netConfig in $netConfigs ) {
for ( $i = 0; $i -lt $netConfig.IPAddress.Count; $i++ ) {
if ( $netConfig.IPAddress[$i] -match '(\d{1,3}\.){3}\d{1,3}' ) {
$ipString = $netConfig.IPAddress[$i]
$ip = [IPAddress] $ipString
$maskString = $netConfig.IPSubnet[$i]
$mask = [IPAddress] $maskString
$netID = [IPAddress] ($ip.Address -band $mask.Address)
"IP address: {0}" -f $ip.IPAddressToString
"Subnet mask: {0}" -f $mask.IPAddressToString
"Network ID: {0}" -f $netID.IPAddressToString
}
}
}
Convert IP address to the subnet
[IPAddress] (([IPAddress] "192.168.100.45").Address -band ([IPAddress] "255.255.255.0").Address)
I am currently using 2016 & i am not getting how to proceed further to get the start ip address and end ip address in a single line of code.
Please advise
You can do the following to get the network and broadcast addresses:
$IP = '192.168.4.5'
$mask = '255.255.0.0'
$IPBits = [int[]]$IP.Split('.')
$MaskBits = [int[]]$Mask.Split('.')
$NetworkIDBits = 0..3 | Foreach-Object { $IPBits[$_] -band $MaskBits[$_] }
$BroadcastBits = 0..3 | Foreach-Object { $NetworkIDBits[$_] + ($MaskBits[$_] -bxor 255) }
$NetworkID = $NetworkIDBits -join '.'
$Broadcast = $BroadcastBits -join '.'
# Output
$NetworkID
192.168.0.0
$Broadcast
192.168.255.255
Explanation:
Since bitwise operators (see About Arithmetic Operators) are only supported on integer types, you must do a string to integer conversion to successfully use the operator[1].
The IP and Mask are split on the . character creating a two string array of the octets. The [int[]] cast converts the array into an Int32 array.
For the network address, we perform a -band (bitwise and) on the same index from each array. Since IPs have four octets, we only need to loop over the 0..3 range. The resulting Int32 array ($NetworkIDBits) items joined by the . character, putting the result in IP address format.
For the broadcast address, we perform a -bxor (bitwise XOR) on the integer array derived from the mask with 255. The goal is to flip all of the ones and zeroes in the mask. The result will be an increment value per octet that can be added to the octets of the network address. The final, calculated result is converted to IP address form using -join.
[1]: You don't always need to explicitly cast strings to integers for the conversion. PowerShell can automatically do this in some cases. For example, in my shell, I do not have to cast with [int[]]
The first ip is just the network address plus 1, although that is usually the gateway. For the broadcast address, I'll just point to this link: https://www.indented.co.uk/powershell-subnet-math/
Getting to the Broadcast Address is a bit more complicated than the
Network Address. A Bitwise Or is executed against an Inverted Subnet
Mask. For example, the Inverted form of 255.255.255.0 is 0.0.0.255.

Capture specific text from output into a variable

I'm trying to write a script that will detect what COM port a device is plugged into, then map it to a new port.
Here is the output from the "change port" command:
PS C:\> change port
COM11 = \Device\19H2KP0
COM2 = \Device\Serial1
COM5 = \Device\Serial2
KEYSPAN#*USA19HMAP#00_00#{4d36e978-e325-11ce-bfc1-08002be10318} = \Device\ComUs19H-00
KEYSPAN#*USA19HMAP#00_00#{86e0d1e0-8089-11d0-9ce4-08003e301f73} = \Device\ComUs19H-00
USA19HP0 = \Device\19H2KP0
I need to capture the COM number prior to "\Device\19H2KP0". So in this example output, I would capture COM11 into a variable.
Next I need to run the "change port" command with that variable. i.e.:
change port COM1=$CapturedText
Thank you in advance for any assistance!
Do you already know what the 19H2KP0 bit will be? If so, you could use a regular expression to detect the unique ID using a look-ahead.
Here's a fully working example, using your example text:
$Output = #"
COM11 = \Device\19H2KP0
COM2 = \Device\Serial1
COM5 = \Device\Serial2
KEYSPAN#*USA19HMAP#00_00#{4d36e978-e325-11ce-bfc1-08002be10318} = \Device\ComUs19H-00
KEYSPAN#*USA19HMAP#00_00#{86e0d1e0-8089-11d0-9ce4-08003e301f73} = \Device\ComUs19H-00
USA19HP0 = \Device\19H2KP0
"#
$Output -match "COM[0-9]{1,2}(?=.*$Id)";
Write-Host -Object ('COM port is: {0}' -f $matches[0]);
And now here is the example, using the in-line command:
$Id = '19H2KP0';
$Output = change port;
$Output -match "COM[0-9]{1,2}(?=.*$Id)";
Write-Host -Object ('COM port is: {0}' -f $matches[0]);
Result
COM port is: COM11
Longer, but perhaps more intuitive, you can also use chained -match and -replace operators with simpler regexes:
$CapturedText = (change port) -match 'COM.+19h2kp0' -replace '^(COM\d+).+','$1'
$CapturedText

Calling a variable without a space before it in powershell?

I am trying to use variables from a imported CSV file to substitute variables in a string.
Here's the code.
param( [string] $CSV)
$VMs = Import-Csv $CSV
Foreach ($VM in $VMs) {
psexec \\$VM.VM_Name -h netsh interface ip set address name='"Local Area Connection"' static $VM.IP_Address 255.255.255.0 $VM.Gateway 1
}
this is what it returns:
psexec \#{VM_Name=TESTCSVVM; IP_Address=10.12.81.82; Gateway=10.12.81.1; VLAN=H
Q_VM_81}.VM_Name -h netsh interface ip set address name="Local Area Connection"
static 10.12.81.82 255.255.255.0 10.12.81.1 1
Here's what I want it to look like:
psexec \TESTCSVVM -h netsh interface ip set address name="Local Area Connection"
static 10.12.81.82 255.255.255.0 10.12.81.1 1
Here's the CSV file:
"VM_Name","IP_Address","Gateway","VLAN"
"TESTCSVVM","10.12.81.82","10.12.81.1","HQ_VM_81"
How do I make sure theres no space between the \ and the 1st variable $VM.VM_Name?
Thanks
Try this :
Foreach ($VM in $VMs) {
psexec \\\\$($VM.VM_Name) -h netsh interface ip set address `
name='"Local Area Connection"' `
static $VM.IP_Address 255.255.255.0 $VM.Gateway 1
}
Also, generally wrapping variables in quotes will work too.
So if:
$path = C:\Windows\
$File = MyFile.ext
write-host "$path$File
Would look like:
C:\Windows\myFile.ext