I have a powershell command with below output, The command output shows the active NIC adapter and NIC adapter name differ in each machine. But what I am looking here is, in one server active NIC adapter is Local Area Connection and in another one it is Ethernet.This will differ in all VM's
PS C:\> netsh interface ipv4 show interface |where { $_ -match '\sconnected' -and $_ -notmatch 'loopback'}
12 5 1500 connected **Local Area Connection**
PS C:\>
PS C:\> netsh interface ipv4 show interface |where { $_ -match '\sconnected' -and $_ -notmatch 'loopback'}
12 5 1500 connected **Ethernet**
PS C:\>
I want only the adapter name to be captured (eg: Local Area Connection\Ethernet etc).
Can anyone help me modifying the command so that I will get the NIC adapter name without any white space as output?
The output should be like below
Local Area Connection
Ethernet
Ethernet 2
If you are running this on a Windows 8 or Server 2012 or newer operating system you can use the Get-NetAdapter cmdlet instead to get the result you want:
Get-NetAdapter | Where {$_.Status -eq 'Up'} | Select -ExpandProperty Name
On an older OS you could try this, which splits the text for each interface by the word "connected" and it's trailing whitespace using the regex special character \s and then return the second item of that split:
$Interfaces = netsh interface ipv4 show interface | where { $_ -match '\sconnected' -and $_ -notmatch 'loopback'}
$Interfaces | ForEach-Object {
($_ -Split 'connected\s+')[1]
}
Or here is another option that avoids using the -split operator and instead uses a regex lookbehind to match 'connected' followed by 5 spaces in the string before what we want to return:
$Interfaces = netsh interface ipv4 show interface | where { $_ -notmatch 'loopback'}
$Interfaces | ForEach-Object {
[regex]::matches($_, '(?<=connected\s{5})(.*)').value
}
Related
Help please. I want the output to display
interface vlan1 is not configured with ospf
interface vlan3 is configured with ospf
interface vlan7 is configured with ospf
but the output I got when running this script below is
interface vlan1 interface vlan3 interface vlan7 is configured with ospf
$interface = select-string -path c:\doc\config.txt -pattern "interface\vlan\d{1,3} -context 0, 3
$ospf = Select-string -inputobject $interface -pattern "ip ospf message-digest.*" | % {$_.matches.value}
if ($ospf -ne $null)
{
$int = $ interface | select -expandproperty line #don't want to show line#
write-host "$int is configured with ospf"
}
else
{
$int = $ interface | select -expandproperty line #don't want to show line#
Write-host "$int is not configured with ospf"
}
interface Vlan1
no ip address
shutdown
!
interface Vlan3
ip ospf message-digest-key 100 md5 7 aa93naf
!
interface Vlan7
standby 38 preempt
ip ospf message-digest-key 100 md5 7 asf9394
Your approach is IMO overcomplicated,
split the config file into chunks(interfaces) separated by the !,
check each single interface for the ospf string,
select the first line of the current interface and output with the test result.
## Q:\Test\2019\03\08\SO_55056710.ps1
$interfaces = (Get-Content .\config.txt -Raw) -split "!`r?`n"
foreach($interface in $interfaces){
if ($interface -match "ip ospf message-digest"){
$ospf = "is"} else {$ospf = "is not"}
"{0} {1} configured with ospf" -f ($interface -split "`r?`n")[0],$ospf
}
Sample output:
> Q:\Test\2019\03\08\SO_55056710.ps1
interface Vlan1 is not configured with ospf
interface Vlan3 is configured with ospf
interface Vlan7 is configured with ospf
I am attempting to use netstat -bano and collect the output in PowerShell for some very specific reporting requirements.
I have working regex that should be able to parse this output no problem, but since the output appears on multiple lines, the regex isn't being processed correctly
here's a screenshot of how it comes out of netstat
desired output is something like this (all on one line):
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 1092 RpcSs [svchost.exe]
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4 Can not obtain ownership information
TCP 0.0.0.0:623 0.0.0.0:0 LISTENING 7404 [LMS.exe]
TCP 0.0.0.0:3389 0.0.0.0:0 LISTENING 1224 TermService [svchost.exe]
the use of tools outside of Windows isn't possible, so I'm confined to common tools.
Using Get-Process matching on PID also won't work, as it hides sub process information under svchost and lsass. netstat with a -b is perfect because it shows both svchost.exe and the process that utilizes the port
I've scoured the internet to find a viable solution but most end in a different resolution
EDIT**here is my final script using input from you guys
$data = (netstat -bano |select -skip 4 | Out-String) -replace '(?m)^ (TCP|UDP)', '$1' -replace '\r?\n\s+([^\[])', "`t`$1" -replace '\r?\n\s+\[', "`t[" -split "`n"
[regex]$regex = '(?<protocol>TCP|UDP)\s+(?<address>\d+.\d+.\d+.\d+|\[::\]|\[::1\]):(?<port>\d+).+(?<state>LISTENING|\*:\*)\s+(?<pid>\d+)\s+(?<service>Can not obtain ownership information|\[\w+.exe\]|\w+\s+\[\w+.exe\])'
$output = #()
$data | foreach {
$_ -match $regex
$outputobj = #{
protocol = [string]$matches.protocol
address = [string]$matches.address -replace '\[::\]','[..]' -replace '\[::1\]','[..1]'
port = [int]$matches.port
state = [string]$matches.state -replace "\*:\*",'NA'
pid = [int]$matches.pid
service = ([string]$matches.service -replace 'Can not obtain ownership information','[System' -split '.*\[')[1] -replace '\]',''
subservice = ([string]$matches.service -replace 'Can not obtain ownership information','' -split '\[.*\]')[0]
}
$output += New-Object -TypeName PSobject -Property $outputobj
}
$output |select address,port,protocol,pid,state,service,subservice
I would probably do something like this:
mangle the output into a single string:
netstat -bano | Out-String
remove indention of the lines beginning with UDP or TCP to make them distinguishable from the other lines:
-replace '(?m)^ (TCP|UDP)', '$1'
join all indented lines that don't begin with a square bracket to the line preceding them:
-replace '\r?\n\s+([^\[])', "`t`$1"
join all indented lines that do begin with a square bracket to the line preceding them:
-replace '\r?\n\s+\[', "`t["
Complete statement:
(netstat -bano | Out-String) -replace '(?m)^ (TCP|UDP)', '$1' -replace '\r?\n\s+([^\[])', "`t`$1" -replace '\r?\n\s+\[', "`t["
Building off what TheMadTechnician had, I found a few cases that broke his output. Specifically: netstat sometimes skips columns; when a friendly app name and an executable are both output on separate lines, it breaks CSV formatting. Here's an updated version of his/her code to take those pieces into account:
$netstat = (netstat -abn | Select -skip 2) -replace "Address\s{2,}State", "Address,State,Application" -join "`n" `
-split "(?= [TU][CD]P\s+(?:\d+\.|\[\w*:\w*:))" | % {
$_.trim() -replace "`n",' ' `
-replace '\*\:\*', '*:*,' `
-replace '\s{2,}', ',' `
-replace '(.*?),(.*?),(.*?),(.*?),(.*?),', '$1,$2,$3,$4,$5 '
} | `
ConvertFrom-Csv
You can join the output of netstat so that it becomes one large multi-line string, then split it on lines that start with whitespace followed by TCP or UDP, followed by an IP address (to remove false positives of an application having a name of 'TCP tracker' or something). Then trim any whitespace from the beginning or end of the line, replace anywhere that there's two or more spaces with a comma, and push the results to ConvertFrom-Csv to create objects. From that you could filter, group, or just simply pipe to Format-Table to see the results.
$Netstat = (netstat -bano | Select -skip 2) -join "`n" -split "(?= [TU][CD]P\s+(?:\d+\.|\[\w*:\w*:))" |
ForEach-Object {$_.trim() -replace "`n",' ' -replace '\s{2,}',','} |
ConvertFrom-Csv
# Filter the results for TCP connections and pipe the results to Format-Table
$Netstat | Where {$_.Proto -eq 'TCP'} | Format-Table
I am interning at a company and we need to redefine our client's printer IP schema. I'm fairly green with powershell and I am using Powershell ISE and when I use:
Get-PrinterPort
I get the full list as expected. However, if I am looking for any printer ports within the subnet set of 192.168.228.*, I have used the following:
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.').index[-1]} -eq '228')
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.')} -match '192.168.228*')
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.').index[-1]} -match '228')
Nothing will display. I have tried many variations of the -match, -icontains, -contains, -like and several others that will search for the partial IP address
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.')} -match '*228')
I have also modified the script to:
Get-WmiObject -Class Win32_TCPIPPrinterPort -OutVariable allIPs
foreach ($splitIP in $allIPs -split '.' ){
$splitIP = $allIPs -split '.'
sort $splitIP[2] -Unique -OutVariable uniqueSubnetIP
}
$uniqueSubnetIP
This is the output I get from the above code
Ultimately, I want to filter through each of the subnet IPs and locate the ones where the last octet are outside the schema and automate a process to put them in range like this:
< 192.268.***.50 || > 192.168.***.60
Any help you can offer is really appreciated; I've spent days trying to figure this out.
First, I wouldn't consider $printerport.name to be reliable for detecting subnets; use $printerport.hostaddress instead.
Get-WMIObject -Class Win32_TCPIPPrinterPort | Where-Object {($_.HostAddress -split '\.')[2] -eq 228} appears to return the printerport objects in the subnet you want - for a different subnet, just change the 228 to whatever the appropriate value is.
The -split operator takes a regular expression, so the . must be escaped, \.. The operation will result in an array of four items, representing the octets of the IP address of the port. The third octet is in #()[2]; you can test other octets similarly by changing the [2] to [0], [1], or [3].
I'm trying to use a PowerShell script to extract my local network IP address from the output of ipconfig. I have gotten it working using a temporary output file but would like to eliminate that step and just use a variable inside the script. I cannot figure out why my script that isn't using a temporary output file won't work. Any help would be much appreciated.
Here are the two scripts. First, the working version:
$input_path = 'C:\Users\Will\Code\Scripts\tmp.txt'
$regex = '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
ipconfig | select-string "IPv4" | select-string -notmatch "192.168.56." > tmp.txt
$ipAddress = select-string -Path $input_path -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
# Pop up an alert window with the IP address
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup($ipAddress,0,"Done",0x1)
# Copy the IP address to the clipboard
$ipAddress | CLIP
And now the almost identical, but non-working version using only variables:
$regex = '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
$input = ipconfig | select-string "IPv4" | select-string -notmatch "192.168.56."
#$input > inputVar.txt
$ipAddress = select-string -inputObject $input -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
# Pop up an alert window with the IP address
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup($ipAddress,0,"Done",0x1)
# Copy the IP address to the clipboard
$ipAddress | CLIP
I am using select-string to find the lines containing 'IPv4' piped into another call to select-string to eliminate the line containing the IP address of my virtual machine. If I enable the test output on line 6 of the non-working script and compare it to the 'tmp.txt' file from the working script, I can see that up to this point, both scripts work identically.
Furthermore, lines 10-15 in both scripts are identical. So I believe that the only line in question is #8.
I have tried it every way I can think of, but always get the same result ("IPv4" rather than the IP address) The first script works as expected and gives me the IP.
Both of these options seem like they should work (and are probably the most logical of all that I've tried), but neither gives me the IP:
$ipAddress = select-string -inputObject $input -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
and
$ipAddress = $input | select-string -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
I've even tried eliminating all the extra steps and just making one long pipe like this:
$ipAddress = ipconfig | select-string "IPv4" | select-string -notmatch "192.168.56." | select-string -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
and just copying to the clipboard like this:
ipconfig | select-string "IPv4" | select-string -notmatch "192.168.56." | select-string -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value } | CLIP
But nothing seems to work.
Where have I gone wrong with this?
Thanks!
Updates 03/13/2015 6:30pm
I'm running Windows 7 64bit
Here's the output of $PSVersionTable:
Name Value
---- -----
CLRVersion 2.0.50727.5485
BuildVersion 6.1.7601.17514
PSVersion 2.0
WSManStackVersion 2.0
PSCompatibleVersions {1.0, 2.0}
SerializationVersion 1.1.0.1
PSRemotingProtocolVersion 2.1
And yes, my end goal is just to get the IP. Really, I just wanted to find a quick way to do that. I guess I didn't technically need the IP by itself for what I'm using it for, but then once I got into it, I got pretty caught up in trying to figure the rest of this out just out of curiosity.
Thanks for all the help!
I'm just getting back into coding after a ~10 year break and I'm super rusty.
I'm not sure why my non working version isn't working for me if it's working for you. When I run it, I get "IPv4" in the pop up and on the clipboard, rather than the IP (which I get in the working version that uses the temp file.
I'm going to integrate these regex changes to my current script and play around with your gwmi solution, Matt. An initial run isn't returning anything for me, but I'll toy around with it and let you know.
Let me know if you have any more ideas on why the version with the variable isn't working correctly on my end in light of this updated info. It's totally baffling to me.
Thanks again!
Updates 03/13/2015 10:27pm
Here's the output of $PSVersionTable after the update:
Name Value
---- -----
PSVersion 4.0
WSManStackVersion 3.0
SerializationVersion 1.1.0.1
CLRVersion 4.0.30319.18444
BuildVersion 6.3.9600.16406
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion 2.2
Here is what happens if I run the Piped Commands piece by piece in PowerShell. As you can see, it seems to break on line 14 at:
$ipAddress = $ipAddress | % { $_.Matches }
Anyhow, thought this might help:
PS C:\Users\Will\Code> $regex = '\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
PS C:\Users\Will\Code> $inputVar = ipconfig | select-string "IPv4" | select-string -notmatch "192\.168\.56\."
PS C:\Users\Will\Code> $inputVar
IPv4 Address. . . . . . . . . . . : 192.168.0.105
PS C:\Users\Will\Code> $ipAddress = select-string -inputObject $inputVar -Pattern $regex -AllMatches
PS C:\Users\Will\Code> $ipAddress
IPv4 Address. . . . . . . . . . . : 192.168.0.105
PS C:\Users\Will\Code> $ipAddress = $ipAddress | % { $_.Matches }
PS C:\Users\Will\Code> $ipAddress
Groups : {IPv4}
Success : True
Captures : {IPv4}
Index : 3
Length : 4
Value : IPv4
PS C:\Users\Will\Code> $ipAddress = $ipAddress | % { $_.Value }
PS C:\Users\Will\Code> $ipAddress
IPv4
PS C:\Users\Will\Code>
Found an issue with this line:
$input = ipconfig | select-string "IPv4" | select-string -notmatch "192.168.56."
You cannot use $input the way you're trying to use it here.
It is one of the default variables in Powershell. Change the instances of $input to $iplist or another variable name.
Updated answer based on your latest edit:
Odd seeing it select IPv4 like that. I don't get the same results here. Try this, it is similar to Matt's method, but skips a couple of the Foreach-Object calls.
$ipAddress = (select-string -inputObject $inputVar -Pattern $regex -AllMatches).tostring().split(" ")[-1]
I should note this may not be the best process if you have multiple network adapters returned. In my case I have three and this only selects the last one.
Chaining Select-String
I think that is the issue you are having. That and you are treating Select-String like Where-Object. Consider the following
ipconfig | select-string "IPv4" | % { $_.Matches } | % { $_.Value }
The results of this would be at least one string that is IPv4 since that is exactly what you are asking for. Understand that select-string does not return strings but Microsoft.PowerShell.Commands.MatchInfo objects. I can imagine what is going on through your head would be "but my output should the strings?". That is why you see most uses of Select-String use % { $_.Matches } | % { $_.Value } to extract the matched strings.
There is a difference in what PowerShell is willing to show you on console and the actual underlying object. Not sure if you need more explanation. This edit would make your code work in place:
ipconfig | select-string "IPv4" | out-string |
select-string -notmatch "192.168.56." | out-string |
select-string -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
Still, that seems a little odd as the first Select-Strings are acting like Where clauses like I already mentioned. You could also do this then:
ipconfig | Where-Object {$_ -match "IPv4" -and $_ -notmatch "192\.168\.56\." } |
select-string -Pattern $regex -AllMatches | % { $_.Matches } | % { $_.Value }
Other approaches
I don't see any issues with you non-working version but I would like to offer an improvement to you select-string's since you don't exactly need to use more than one with some minor changes.
$ipAddressPrefix = [regex]::Escape("169.254.125.")
$ipaddresses = ipconfig | select-string "IPv4.*?: (?!$ipAddressPrefix).*" | % { $_.Matches } | % {$_.Value.Split(": ")[-1]}
# Pop up an alert window with the IP address
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup($ipaddresses,0,"Done",0x1)
Lets take the first 3 octets that you are trying to not match and make an escaped matching string. Then using a negative lookahead we match the lines containing "IPv4" but that don't have the $ipAddressPrefix following the colon.
Then, using all matches returned we split the string on the colon and space to get the IpAddresses matched. Again, note that it is very possible to get more than one address returned in this way.
Preferntial Method
Parsing string to get this information is fine and dandy but you can get it much easier using WMI and not having to working about things like leading and trailing spaces
$ipAddressPrefix = [regex]::Escape("169.254.125.")
$ipaddresses = gwmi Win32_NetworkAdapterConfiguration | Where { $_.IPAddress -and ($_.IPAddress -notmatch "$ipAddressPrefix|:") } |
Select -Expand IPAddress
$ipaddresses should contain the same results using either code snippet. The Where clause is broken down into these two parts
$_.IPAddress --> this would filter out empty strings and nulls
$_.IPAddress -notmatch "$ipAddressPrefix|:" would ensure that the $ipAddressPrefix matches are ommited. You will also see the : which will omit the IPv6 addresses.
I am trying to read the host file and trying to ping the each host name and after that capturing the IP address in the response and trying to match with the IP address mentioned in the host file.
I have three scenarios:-
1) Its pinging the host and getting the reply back with the correct IP
Result :-Resolved and Replied
2) It's Not pinging at all and not resolving the IP
Result :-Not Resolved and Not Replied
3) It's Pinging but not resolving the IP correctly mentioned to the IP in the host file
Result :-Not Resolved and Replied
I am trying to achieve that scenario with the below script but not fully achieved as different expression need to be used.
Can someone help me to finish it
$lines = Get-Content myfile.txt | Where {$_ -notmatch "((^#)|(^\s+$))"}
# get all test pairs
$tests=$lines |
ForEach-Object{
$fields = $_ -split '\s+'
echo " Fields are $fields"
for ($i = 1; $i -lt $fields.Length; $i++){
New-Object PsObject -Property #{IP=$fields[0];Host=$fields[$i]}
}
}
$tests |
ForEach-Object{
$props=#{
IPAddress=$_.ip
Hostname=$_.Host
Resolve =' '
Reply = ' '
}
$PingResult = ping -n 1 -w 10 $_.host
#echo "$PingResult"
foreach ($line in $PingResult)
{
if ($line.StartsWith("Pinging") -eq $true)
{
$_.ip= $line -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
echo "IP is $IP"
if ($matches[0])
{
$props.Resolve ='Y'
$props.Reply='Y'
}
else
{
$props.Resolve ='Y'
$props.Reply='N'
}
}
}New-Object PsCustomObject -Property $props
}|
Format-Table -AutoSize | Out-String | Out-File D:\CEP\testlogging.txt
Note:- Cannot use Test-Connection because it throws exception when server wont reply back or doesnot exist and it takes more time to ping.
Thanks.
Suppose it's too late to be of much help but this should resolve the issues you are reporting with Test-Connection.
Test-Connection -ComputerName $IP -Count 1 -ErrorAction SilentlyContinue
That will limit the ping count to 1 and error will be ignored. Then you can work with the object it produces instead of having to parse lines.