Converting input to integer and doing arithmetic in powershell - powershell

not sure how to convert a string to an integer and then do an "add 1" to it. Here's what I'm trying to do:
1) Capture an IP address from a prompt
2) create list of variables with the increasing IPs as such:
$startIP = Read-Host
$ip1 = $startIP
$ip2 = $ip1 + 1
$ip3 = $ip2 + 1
So for example, we'd input 10.0.0.1, and then $ip2 would be 10.0.0.2 and so on.
I know I need to convert this to an integer after reading the input, but am unsure how to do that. Many thanks!

Found these functions that converts an IP to an Int64 and back
Function Convert-IpToInt64 () {
param ([String]$ip)
process {
$octets = $ip.split(".")
return [int64]([int64]$octets[0]*16777216 +[int64]$octets[1]*65536 +[int64]$octets[2]*256 +[int64]$octets[3])
}
}
Function Convert-Int64ToIp() {
param ([int64]$int)
process {
return (([math]::truncate($int/16777216)).tostring()+"."+([math]::truncate(($int%16777216)/65536)).tostring()+"."+([math]::truncate(($int%65536)/256)).tostring()+"."+([math]::truncate($int%256)).tostring() )
}
}
With that you can now convert the input to an something that can be incremented
$startIP = Read-Host
$ip1 = Convert-IpToInt64 $startIP
$ip2 = $ip1 + 1
$ip3 = $ip2 + 1

Related

What is the correct IP address conversion from number?

I am trying to convert number into IP address using powershell method and checking same online, I am getting 2 different result.
Example:
number = 16812043
result1 = 11.136.0.1 #using powershell
result2 = 1.0.136.11 #https://codebeautify.org/decimal-to-ip-converter
I have tried below code
function Convert-NumberToIP
{
param(
[Parameter(Mandatory=$true)][string]$number
)
[Int64] $numberInt = 0
if([Int64]::TryParse($number, [ref]$numberInt))
{
if(($numberInt -ge 0) -and ($numberInt -le 0xFFFFFFFFl))
{
([IPAddress] $numberInt).ToString()
}
}
}
Convert-NumberToIP -number 16812043
I am getting 2 different result not sure which 1 is correct, or should I update the function.
Use the IPAddress.NetworkToHostOrder() method to flip the endianness of the octets represented by your decimal number:
PS ~> [ipaddress]::new([ipaddress]::NetworkToHostOrder(16812043)).IPAddressToString
1.0.136.11

Powershell stripping the first character out of a variable when returning from function

I'm working on some PS code to automatically name a computer to our standards. There are two functions that build the name, one to grab the serial number and test if it is too long for the MS 15-character limit, the second puts the pieces together. When the get serial number function is called, everything works OK, but when the variable is read in the other function, it's missing the first character.
Here's the relevant code and log file:
Function Format-CompName {
$compType = (Get-CimInstance Win32_SystemEnclosure).ChassisTypes
WriteLog "Computer chassis type is: $compType"
switch ($compType)
{
1{$WDWL = $desktop}
2{$WDWL = $desktop}
3{$WDWL = $desktop}
4{$WDWL = $desktop}
5{$WDWL = $desktop}
6{$WDWL = $desktop}
7{$WDWL = $desktop}
8{$WDWL = $desktop}
9{$WDWL = $laptop}
10{$WDWL = $laptop}
11{$WDWL = $laptop}
12{$WDWL = $laptop}
13{$WDWL = $laptop}
14{$WDWL = $laptop}
15{$WDWL = $laptop}
16{$WDWL = $laptop}
30{$WDWL = $laptop}
31{$WDWL = $laptop}
32{$WDWL = $laptop}
}
WriteLog "Prefix is: $prefix"
WriteLog "Middle name is: $WDWL"
Get-SerialNumber
WriteLog "Post return SN..."
WriteLog $strSN
$strCompName = $prefix + $WDWL + $strSN
WriteLog "Device name before Return: $strCompName"
$strCompName
}
Function Get-SerialNumber
{
# Get the serial number. Note: Lenovo now uses Win32_BIOS instead of Win32_Product (older machines may not work).
WriteLog "Getting the serial number."
$strSN = (Get-CimInstance Win32_BIOS).SerialNumber
WriteLog "Serial Number is: $strSN"
#Is it too long?
if ($strSN.Length -gt 8) {
WriteLog "Serial number is too long."
$snNumDiff = $strSN.Length - 8
#write-host $snNumDiff
$strSN = $strSN.substring($snNumDiff)
return $strSN
WriteLog "Adjusted SN is: " $strSN
}
else {
WriteLog "Serial number is within character limits."
WriteLog "Non-adjusted Serial number is: $strSN"
return $strSN
}
}
And the log...
2022/12/02 09:05:23 Naming script is starting
2022/12/02 09:05:23 Computer chassis type is: 10
2022/12/02 09:05:23 Prefix is: GU
2022/12/02 09:05:23 Middle name is: -WL-
2022/12/02 09:05:23 Getting the serial number.
2022/12/02 09:05:23 Serial Number is: 1RM4M13
2022/12/02 09:05:23 Serial number is within character limits.
2022/12/02 09:05:23 Non-adjusted Serial number is: 1RM4M13
2022/12/02 09:05:23 Post return SN...
2022/12/02 09:05:23 RM4M13
2022/12/02 09:05:23 Device name before Return: GU-WL-RM4M13
2022/12/02 09:05:23 Function returned:
2022/12/02 09:05:23 New name = 1RM4M13 GU-WL-RM4M13
Logging all the details to isolate where the problem is.

How to add fields in table to a Word document with Powershell

I'm able to add fields in the footer of a word document, like this :
$footer = $Section.Footers.Item(1)
$footer.Range.Text = "";
$Footer.Range.ParagraphFormat.Alignment=2
$Range = $Footer.Range
$null = $ExistingDoc.Fields.Add($footer.range, 33) # Page
$Range.SetRange($Range.end + 1,$Range.end + 1)
$null = $Range.InsertBefore(' of ')
$Range.SetRange($Range.end + 1,$Range.end + 1)
$null = $ExistingDoc.Fields.Add($range, 26) # Total Page
$Range.SetRange($Range.star,$Range.start)
$null = $Range.InsertBefore('Page ')
$Footer.Range.ParagraphFormat.Alignment=2
But I'm not able to add a table and put fields in it.
I tried many syntaxes with no luck like :
$table2 = $ExistingDoc.Tables.Add($footer.range,2,3)
$range2 = $table2.cell(1,1).select
$null = $ExistingDoc.Fields.Add($Footer.range.Tables(2), 33)
or
$table2 = $ExistingDoc.Tables.Add($footer.range,2,3)
$null = $ExistingDoc.Fields.Add($table2.cell(1,1), 33)
I did it with a macro and find the following code :
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"PAGE ", PreserveFormatting:=True
But no luck to convert it to Powershell, any help is welcome.

Building a list of IP addresses

I am trying to build an array of possible IP addresses based on a user's input. i.e. IP address along with a CIDR number. My end goal is to compare this list with a separate list of addresses and find which are is missing.
Example
user input: 192.168.1.0 /24
I want to build an array for all possible values for the /24 network (i.e. the IP address can be anywhere from 192.168.1.0 - 192.168.1.255)
In order for this to work, I think I have to convert the IP address to binary and then find the bits that will be the host part of the network, which I've done here:
function ConvertToBinary{
param($ipAddress)
[string]$binaryIP = -join ($ipAddress.Split('.') | ForEach-Object {[System.Convert]::ToString($_,2).PadLeft(8,'0')})
return $binaryIP
}
function FindHost{
param(
[string]$binaryIPAddress,
[int32]$CIDR
)
$hostBits = 32-$CIDR
[string]$myHost = $binaryIPAddress.Substring($binaryIPAddress.Length-$hostBits)
return $myHost
}
$myip = ConvertToBinary "192.168.3.1"
$myHost = FindHost $myip 8
I'm a little stuck on how to proceed, so if anyone can help me out or point me in the right direction, it would be much appreciated
I wrote this using some similar questions to get the first and last address for any subnet given a random IP and mask:
Function Get-SubnetAddresses {
Param ([IPAddress]$IP,[ValidateRange(0, 32)][int]$maskbits)
# Convert the mask to type [IPAddress]:
$mask = ([Math]::Pow(2, $MaskBits) - 1) * [Math]::Pow(2, (32 - $MaskBits))
$maskbytes = [BitConverter]::GetBytes([UInt32] $mask)
$DottedMask = [IPAddress]((3..0 | ForEach-Object { [String] $maskbytes[$_] }) -join '.')
# bitwise AND them together, and you've got the subnet ID
$lower = [IPAddress] ( $ip.Address -band $DottedMask.Address )
# We can do a similar operation for the broadcast address
# subnet mask bytes need to be inverted and reversed before adding
$LowerBytes = [BitConverter]::GetBytes([UInt32] $lower.Address)
[IPAddress]$upper = (0..3 | %{$LowerBytes[$_] + ($maskbytes[(3-$_)] -bxor 255)}) -join '.'
# Make an object for use elsewhere
Return [pscustomobject][ordered]#{
Lower=$lower
Upper=$upper
}
}
Usage looks like:
Get-IPAddresses 10.43.120.8 22
Lower Upper
----- -----
10.43.120.0 10.43.123.255
And I put this together to generate the whole list. I'm sure this could be done better, but the simple instructions run fast enough:
Function Get-IPRange {
param (
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName)][IPAddress]$lower,
[Parameter(Mandatory=$true,ValueFromPipelineByPropertyName)][IPAddress]$upper
)
# use lists for speed
$IPList = [Collections.ArrayList]::new()
$null = $IPList.Add($lower)
$i = $lower
# increment ip until reaching $upper in range
while ( $i -ne $upper ) {
# IP octet values are built back-to-front, so reverse the octet order
$iBytes = [BitConverter]::GetBytes([UInt32] $i.Address)
[Array]::Reverse($iBytes)
# Then we can +1 the int value and reverse again
$nextBytes = [BitConverter]::GetBytes([UInt32]([bitconverter]::ToUInt32($iBytes,0) +1))
[Array]::Reverse($nextBytes)
# Convert to IP and add to list
$i = [IPAddress]$nextBytes
$null = $IPList.Add($i)
}
return $IPList
}
Converting to [IPAddress] on the last line is nice for validating all the results are real, but probably not necessary if you just want the ipv4 strings. Usage:
Get-SubnetAddresses 10.43.120.8 30 | Get-IPRange | Select -ExpandProperty IPAddressToString
10.43.120.8
10.43.120.9
10.43.120.10
10.43.120.11
Sources:
https://stackoverflow.com/a/51307519/7411885
https://stackoverflow.com/a/58821442/7411885

Calculate two audio duration with frame

I am stuck, I need a small logic.
I have two audio durations
x = "00:00:07:18"
y = "00:00:06:00" H : M: S: F
Answer should be x + y = 00:00:13:18
H=hours S= seconds M=minutes F=frame
My question is
if x = "00:00:03:14"
y = "00:00:13:18"
answer should be x + y = **00:00:17:02**
If the frame is greater than 30 it should increase 1 in second.
I am using power shell. How can I determine the logic to calculate both of this?
Calculation of the first 3 parts (hour:minute:second), we can offload to the [timespan] type, then all we need to worry about is carrying excess frames over:
# Simple helper function to turn our input strings into a [timespan] + frame count
function Parse-FrameDuration
{
param(
[string]$Duration
)
$hour,$minute,$second,$frame = ($Duration -split ':') -as [int[]]
[PSCustomObject]#{
Time = New-TimeSpan -Hours $hour -Minutes $minute -Seconds $second
Frame = $frame
}
}
# function to do the actual calculation
function Add-Frame
{
param(
[string]$Base,
[string]$Offset
)
# Parse our two timestamps
$a = Parse-FrameDuration $Base
$b = Parse-FrameDuration $Offset
# Calculate frames % frame rate, remember to carry any excess seconds
$frames = 0
$carry = [math]::DivRem($a.Frame + $b.Frame , 30, [ref]$frames)
# Calculate time difference, add any extra second carried from frame count
$new = ($a.Time + $b.Time).Add($(New-TimeSpan -Seconds $carry))
# Stitch output string together from new timespan + remaining frames
return "{0:hh\:mm\:ss}:{1:00}" -f $new,$frames
}
Now we can do:
PS C:\> Add-Frame -Base 00:00:03:14 -Offset 00:00:13:18
00:00:17:02