Combining several outputs into a table - windows

Using Powershell I am trying to put the results of three commands into a table and output them to a file, then repeat the command forever. I can't figure out exactly how to format the table correctly.
This is my script
while (1){
$ping = test-connection 8.8.8.8 -delay 1 -count 1
$wifi = #{n='Status';e={get-netadapter -physical -name Wi-Fi | select Status}}
$timestamp = #{n='TimeStamp';e={Get-Date}}
$ping | format-table __SERVER, Address, ResponseTime, $timestamp, $wifi | out-file "C:\test-connection.txt" -append
start-sleep -s 10
}
$ping gets the ping results of 8.8.8.8
$wifi gets the status of the wi-fi adapter
$timestamp gets the current time
The final output is meant to look something like this:
__SERVER Address ResponseTime TimeStamp Status
-------- ------- ------------ --------- ------
Hostname 8.8.8.8 19 18/02/2019 10:19:23 Up
Hostname 8.8.8.8 19 18/02/2019 10:19:23 Up
Hostname 8.8.8.8 19 18/02/2019 10:19:23 Up
Hostname 8.8.8.8 19 18/02/2019 10:19:23 Up
...
However, with my current setup it does this:
__SERVER Address ResponseTime TimeStamp Status
-------- ------- ------------ --------- ------
Hostname 8.8.8.8 20 18/02/2019 10:19:13 #{Status=Up}
__SERVER Address ResponseTime TimeStamp Status
-------- ------- ------------ --------- ------
Hostname 8.8.8.8 19 18/02/2019 10:19:23 #{Status=Up}
__SERVER Address ResponseTime TimeStamp Status
-------- ------- ------------ --------- ------
Hostname 8.8.8.8 20 18/02/2019 10:19:33 #{Status=Up}
Any assistance is appreciated.

You would have to hide the table headers on subsequent writes, and also trim the output.
Try this:
while (1) {
$ping = test-connection 8.8.8.8 -delay 1 -count 1
$wifi = #{n='Status';e={get-netadapter -physical -name Wi-Fi | select -expand Status}}
$timestamp = #{n='TimeStamp';e={Get-Date}}
$path = "C:\test-connection.txt"
$ping | ft __SERVER, Address, ResponseTime, $timestamp, $wifi -Hide:(Test-Path $path) | out-string | % {$_.trim()} | out-file $path -append
start-sleep -s 10
}
Using Format-Table for file output is not a good idea though, it's meant for display in the console. Consider using CSV or a custom format.

Related

Output bottom line in Powershell

I want to output the last entry of Get-Hotfix in PowerShell. How does it work?
Example:
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
DESKTOP-FU... Update KB5010472 NT-AUTORITÄT\SYSTEM 15.03.2022 00:00:00
DESKTOP-FU... Update KB5003791 06.10.2021 00:00:00
DESKTOP-FU... Security Update KB5011487 NT-AUTORITÄT\SYSTEM 14.03.2022 00:00:00
DESKTOP-FU... Update KB5007273 NT-AUTORITÄT\SYSTEM 02.01.2022 00:00:00
DESKTOP-FU... Security Update KB5011352 NT-AUTORITÄT\SYSTEM 09.02.2022 00:00:00
DESKTOP-FU... Security Update KB5005699 06.10.2021 00:00:00
I want to output the KB5005699 update to the console.
You can use Select-Object with the -Last 1 parameter to get the last object and -ExpandProperty HotFixID to get the Value of the HotFixID property:
Get-HotFix | Select-Object -Last 1 -ExpandProperty HotFixID
Another alternative would be to get the last object by the -1 index and use dot notation .HotFixID to get the Value:
(Get-HotFix)[-1].HotFixID

Why sometimes powershell cmdlet "select-string" does not return any value?

This command works, logfolder contains several log files, select-string will search on each file and look for the -pattern 'update'
get-childitem -recurse C:\logfolder -file | select-string -pattern "update"
But this other line won't work, it won't return any results
get-eventlog -logname system -entrytype error | select-string -pattern "terminated"
I am 100% positive that there is an event with the string "terminated", maybe I am missing some concepts here.
select-string converts the input object to a string. Unfortunately with get-eventlog this isn't very helpful. By the way, get-eventlog has been replaced by get-winevent.
get-eventlog -logname system -entrytype error | select -first 1
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
63255 Aug 31 07:44 Error Microsoft-Windows... 1129 The processing of Group Policy failed because o...
get-eventlog -logname system -entrytype error | select -first 1 | % { "$_" }
System.Diagnostics.EventLogEntry
get-eventlog -logname system -entrytype error | select -first 1 | select-string log
System.Diagnostics.EventLogEntry
get-eventlog -logname system -entrytype error | select -first 1 |
where message -match processing
Index Time EntryType Source InstanceID Message
----- ---- --------- ------ ---------- -------
63255 Aug 31 07:44 Error Microsoft-Windows... 1129 The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient cond...
get-winevent #{logname='system';level=2} -maxevents 1 |
? message -match processing | ft -GroupBy logname
ProviderName: System
TimeCreated Id LevelDisplayName Message
----------- -- ---------------- -------
8/31/2021 7:44:27 AM 1129 Error The processing of Group Policy failed because of lack of network connectivity to a domain controller. This may be a transient condition. A success...

Get list all IP addresses connected to your server using Powershell / CMD

EDITED
my goal :
get "total" list of IP's connected to port 80 in windows server.
TOTAL IP's
5 1.1.1.1
12 2.2.2.2
1 3.3.3.3
in centos, i found this
netstat -tn 2>/dev/null | grep :80 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head
but if windows server, is there any way do that using powershell or cmd?
*i get one example but its not reaching my goal :
netstat -n | find "80"
credit for example : https://mkyong.com/linux/list-all-ip-addresses-connected-to-your-server/
Get-NetTCPConnection is the PowerShell equivalent and creates a robust object you can filter to your needs.
In your example, you're getting all connections to port 80 on your device, here's what that looks like in PowerShell:
Get-NetTCPConnection |where RemotePort -eq 80
LocalAddress LocalPort RemoteAddress RemotePort State AppliedSetting OwningProcess
------------ --------- ------------- ---------- ----- -------------- -------------
192.168.0.27 51135 50.63.202.49 80 CloseWait Internet 12508
192.168.0.27 51134 50.63.202.49 80 CloseWait Internet 12508
192.168.0.27 51133 50.63.202.49 80 CloseWait Internet 12508
192.168.0.27 51132 50.63.202.49 80 CloseWait Internet 12508
If you wanted to gather just the remote IP addresses, for instance:
Get-NetTCPConnection |where RemotePort -eq 80 |select RemoteAddress
RemoteAddress
-------------
50.63.202.49
50.63.202.49
50.63.202.49
50.63.202.49
50.63.202.49
50.63.202.49
If you need to group them to see how many sessions per IP, you can pipe into the Group-Object cmdlet like so:
Get-NetTCPConnection |where RemotePort -eq 80 |select RemoteAddress |
group-object -Property RemoteAddress |select Name,Count
Name Count
---- -----
72.21.91.29 1
23.35.182.63 6
One quick and dirty way to find TCP sessions connected to port 80 is
for /f "tokens=3" %a in ('netstat -n ^| find ":80 "') do #echo %a > filename.txt
You would obtain output similar to the following:
10.1.1.3:52025
10.1.1.3:53014
10.1.1.3:53039
10.1.1.3:53044
10.1.1.3:53066

get IPv4 address into a variable

Is there an easy way in PowerShell 3.0 on Windows 7 to get the local computer's IPv4 address into a variable?
Here is another solution:
$env:HostIP = (
Get-NetIPConfiguration |
Where-Object {
$_.IPv4DefaultGateway -ne $null -and
$_.NetAdapter.Status -ne "Disconnected"
}
).IPv4Address.IPAddress
How about this? (not my real IP Address!)
PS C:\> $ipV4 = Test-Connection -ComputerName (hostname) -Count 1 | Select IPV4Address
PS C:\> $ipV4
IPV4Address
-----------
192.0.2.0
Note that using localhost would just return and IP of 127.0.0.1
PS C:\> $ipV4 = Test-Connection -ComputerName localhost -Count 1 | Select IPV4Address
PS C:\> $ipV4
IPV4Address
-----------
127.0.0.1
The IP Address object has to be expanded out to get the address string
PS C:\> $ipV4 = Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPV4Address
PS C:\> $ipV4
Address : 556228818
AddressFamily : InterNetwork
ScopeId :
IsIPv6Multicast : False
IsIPv6LinkLocal : False
IsIPv6SiteLocal : False
IsIPv6Teredo : False
IsIPv4MappedToIPv6 : False
IPAddressToString : 192.0.2.0
PS C:\> $ipV4.IPAddressToString
192.0.2.0
If I use the machine name this works. But is kind of like a hack (because I am just picking the first value of ipv4 address that I get.)
$ipaddress=([System.Net.DNS]::GetHostAddresses('PasteMachineNameHere')|Where-Object {$_.AddressFamily -eq "InterNetwork"} | select-object IPAddressToString)[0].IPAddressToString
Note that you have to replace the value PasteMachineNameHere in the above expression
This works too
$localIpAddress=((ipconfig | findstr [0-9].\.)[0]).Split()[-1]
Here are three methods using windows powershell and/or powershell core, listed from fastest to slowest.
You can assign it to a variable of your choosing.
Method 1: (this method is the fastest and works in both windows powershell and powershell core)
$ipAddress = (Get-NetIPAddress | Where-Object {$_.AddressState -eq "Preferred" -and $_.ValidLifetime -lt "24:00:00"}).IPAddress
Method 2: (this method is as fast as method 1 but it does not work with powershell core)
$ipAddress = (Test-Connection -ComputerName (hostname) -Count 1 | Select -ExpandProperty IPv4Address).IPAddressToString
Method 3: (although the slowest, it works on both windows powershell and powershell core)
$ipAddress = (Get-NetIPConfiguration | Where-Object {$_.IPv4DefaultGateway -ne $null -and $_.NetAdapter.status -ne "Disconnected"}).IPv4Address.IPAddress
Here is what I ended up using
$ipaddress = $(ipconfig | where {$_ -match 'IPv4.+\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' } | out-null; $Matches[1])
which breaks down as
execute ipconfig command - get all the network interface information
use powershell's where filter with a regular expression
regular expression finds the line with "IPv4" and a set of 4 blocks each with 1-3 digits separated by periods, i.e. a v4 IP address
disregard the output by piping it to null
finally get the first matched group as defined by the brackets in the regular expression.
catch that output in $ipaddress for later use.
(Get-WmiObject -Class Win32_NetworkAdapterConfiguration | where {$_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null}).IPAddress
This one liner gives you the IP address:
(Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
Include it in a Variable?
$IPV4=(Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
Another variant using $env environment variable to grab hostname:
Test-Connection -ComputerName $env:computername -count 1 | Select-Object IPV4Address
or if you just want the IP address returned without the property header
(Test-Connection -ComputerName $env:computername -count 1).IPV4Address.ipaddressTOstring
tldr;
I used this command to get the ip address of my Ethernet network adapter into a variable called IP.
for /f "tokens=3 delims=: " %i in ('netsh interface ip show config name^="Ethernet" ^| findstr "IP Address"') do set IP=%i
For those who are curious to know what all that means, read on
Most commands using ipconfig for example just print out all your IP addresses and I needed a specific one which in my case was for my Ethernet network adapter.
You can see your list of network adapters by using the netsh interface ipv4 show interfaces command. Most people need Wi-Fi or Ethernet.
You'll see a table like so in the output to the command prompt:
Idx Met MTU State Name
--- ---------- ---------- ------------ ---------------------------
1 75 4294967295 connected Loopback Pseudo-Interface 1
15 25 1500 connected Ethernet
17 5000 1500 connected vEthernet (Default Switch)
32 15 1500 connected vEthernet (DockerNAT)
In the name column you should find the network adapter you want (i.e. Ethernet, Wi-Fi etc.).
As mentioned, I was interested in Ethernet in my case.
To get the IP for that adapter we can use the netsh command:
netsh interface ip show config name="Ethernet"
This gives us this output:
Configuration for interface "Ethernet"
DHCP enabled: Yes
IP Address: 169.252.27.59
Subnet Prefix: 169.252.0.0/16 (mask 255.255.0.0)
InterfaceMetric: 25
DNS servers configured through DHCP: None
Register with which suffix: Primary only
WINS servers configured through DHCP: None
(I faked the actual IP number above for security reasons 😉)
I can further specify which line I want using the findstr command in the ms-dos command prompt.
Here I want the line containing the string IP Address.
netsh interface ip show config name="Ethernet" | findstr "IP Address"
This gives the following output:
IP Address: 169.252.27.59
I can then use the for command that allows me to parse files (or multiline strings in this case) and split out the strings' contents based on a delimiter and the item number that I'm interested in.
Note that I am looking for the third item (tokens=3) and that I am using the space character and : as my delimiters (delims=: ).
for /f "tokens=3 delims=: " %i in ('netsh interface ip show config name^="Ethernet" ^| findstr "IP Address"') do set IP=%i
Each value or token in the loop is printed off as the variable %i but I'm only interested in the third "token" or item (hence tokens=3). Note that I had to escape the | and = using a ^
At the end of the for command you can specify a command to run with the content that is returned. In this case I am using set to assign the value to an environment variable called IP. If you want you could also just echo the value or what ever you like.
With that you get an environment variable with the IP Address of your preferred network adapter assigned to an environment variable. Pretty neat, huh?
If you have any ideas for improving please leave a comment.
I was looking for the same thing and figured this out:
$ip = Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $(Get-NetConnectionProfile | Select-Object -ExpandProperty InterfaceIndex) | Select-Object -ExpandProperty IPAddress
This filters out both the loopback address and some virtual networks I have.
$ip = (Get-NetIPAddress -AddressFamily IPv4 -InterfaceIndex $(Get-NetConnectionProfile).InterfaceIndex).IPAddress
OR
function Get-LocalIP {
(
Get-NetIPAddress `
-AddressFamily IPv4 `
-InterfaceIndex $(
Get-NetConnectionProfile
).InterfaceIndex
).IPAddress
}
$ip = Get-LocalIP
To grab the device's IPv4 addresses, and filter to only grab ones that match your scheme (i.e. Ignore and APIPA addresses or the LocalHost address). You could say to grab the address matching 192.168.200.* for example.
$IPv4Addr = Get-NetIPAddress -AddressFamily ipV4 | where {$_.IPAddress -like X.X.X.X} | Select IPAddress
# Patrick Burwell's Ping Script - Patrick.Burwell#Infosys.com #
$Output= #() #sets an array
$names = Get-Content ".\input\ptd.pc_list.txt" #sets a list to use, like a DNS dump
foreach ($name in $names){ #sets the input by enumerating a text file to loop through and sets a variable to execute against
if ($IPV4 = Test-Connection -Delay 15 -ComputerName $name -Count 1 -ErrorAction SilentlyContinue|select IPV4Address #run ping and sets only IPV4Address response variable
){# If true then run...
$Output+= $Name,($IPV4.IPV4Address).IPAddressToString # Fills the array with the #true response
Write-Host $Name',','Ping,'($IPV4.IPV4Address).IPAddressToString -ForegroundColor Green #Sets the output to receive the Name, result and IPV4Address and prints the reply to the console with specific colors
}
else{#If false then run...
$Output+= "$name," #Fills the array with the #false response
Write-Host "$Name," -ForegroundColor Red #Prints the reply to the console with specific colors
}
}
#$Output | Out-file ".\output\result.csv" #<-- use to export to a text file (Set path as needed)
#$Output | Export-CSV ".\output\result.csv" -NoTypeInformation #<-- use to export to a csv file (Set path as needed)
#If you choose, you can merely have the reply by the name and IP, and the Name and no IP by removing the Ping comments
As I was working in Powershell 3, none of the answers here worked for me. It's based on Rob's approach, but this one works when you have multiple network adapters, it also picks out the IP correctly using capture groups
function GetIPConfig {
return ipconfig | select-string ('(\s)+IPv4.+\s(?<IP>(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(\s)*') -AllMatches | %{ $_.Matches } | % { $_.Groups["IP"]} | %{ $_.Value }
}
Non of the top comments are actually fully correct since a computer can have multiple interfaces and an interface can have multiple IP addresses. There are a few answers here which technically correct but utilizes "funky" ways to filter out wellknown addresses (like APIPA, localhost, etc) whereas even Powershell 3.0 have a native way to do so with PrefixOrigin.
$IPv4Addresses = $(Get-NetIPAddress | Where-Object { $_.PrefixOrigin -ne "WellKnown" -and $_.AddressFamily -eq "IPv4" }).IPAddress
I do this :
$interFaceAliasName="LAN" # You have to change the name according to your interface's name
$myInterface=(Get-NetIPAddress -InterfaceAlias $interFaceAliasName)
$myIP=$myInterface.IPv4Address
I recently had the same issue. So I wrote a script to parse it from the ipconfig /all output. This script is easily modifiable to obtain any of the parameters of the interfaces and it works on Windows 7 also.
Get output of IP config in LineNumber | Line format
$ip_config = $(ipconfig /all | % {$_ -split "rn"} | Select-String -Pattern ".*" | select LineNumber, Line)
Get list of interfaces (+ last line of ipconfig output) in LineNumber | Line format
$interfaces = $($ip_config | where {$_.Line -notmatch '^\s*$'} | where {$_.Line -notmatch '^\s'}) + $($ip_config | Select -last 1)
Filter through the interfaces list for the specific interface you want
$LAN = $($interfaces | where {$_.Line -match 'Wireless Network Connection:$'})
Get the start and end line numbers of chosen interface from output
$i = $interfaces.IndexOf($LAN)
$start = $LAN.LineNumber
$end = $interfaces[$i+1].LineNumber
Pick the lines from start..end
$LAN = $ip_config | where {$_.LineNumber -in ($start..$end)}
Get IP(v4) address field (returns null if no IPv4 address present)
$LAN_IP = #($LAN | where {$_ -match 'IPv4.+:\s(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'})
$LAN_IP = &{If ($LAN_IP.Count -gt 0) {$Matches[1]} Else {$null}}
$a = ipconfig
$result = $a[8] -replace "IPv4 Address. . . . . . . . . . . :",""
Also check which index of ipconfig has the IPv4 Address

Powershell format-table or select-object only show top results

I am trying to find users that have been sending the most emails.
But in the end I only want to display the top 10 (or n number) of senders.
Is there a way to only show the top results using select-object or format-table
$Messages = Get-ExchangeServer * | where{$_.ServerRole -eq "HubTransport"} | %{get-messagetrackinglog -server $_.name -EventID "SEND" -Start (get-date -format G).AddDays(-1) -ResultSize unlimited}) 2>&1 | out-null
$messages | where{$_.sender -like "*#OurDomain.com*"} | select sender | group sender | sort count -Descending | ft count,name
Is there a way to make this only display the top results?
The only way I can think of would be storing them in a variable and outputting them in a for loop
Before the ft, add:
select -first 10
Replacing the 10 with how many you want.
So the full command would be:
$messages | where{$_.sender -like "*#OurDomain.com*"} | select sender | group sender | sort count -Descending | select -first 10 | ft count,name
This is asked a long time ago. But I got surprised by one thing, that you were using select and didn't look at this thing. Well in case you are thinking this is a rude answer - no it won't be. The point is you were this close to the solution. So few days back (by the way I don't know powershell much) I was asked this question and I had to display things only the first few. So the first thing I did was get-help *display* thinking that it would somehow show me something which would let me display some stuff. I was wrong, and realized I need to look for something. Then I look for the action words or the verbs. I checked get-Verb and then I could see the verbs that are relevant.
And I found select. It sounds reasonable, and then I opened help for select. get-help select -ShowWindow. And I checked the parameters and found this
-First <Int32>
Gets only the specified number of objects. Enter the number of objects to get.
Required? false
Position? named
Default value False
Accept pipeline input? False
Accept wildcard characters? false
And that's it. I don't know anything about power shell but I guess this can still be found with some workout like this.
For you, you knew that it would be select so you could have easily checked the parameters to solve it. In fact even the examples on how to do stuff is helpful. For example right after discovering First I got this example which made me clear about the syntax.
PS C:\>Get-Process | Sort-Object -Property WS | Select-Object -Last 5
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
2866 320 33432 45764 203 222.41 1292 svchost
577 17 23676 50516 265 50.58 4388 WINWORD
826 11 75448 76712 188 19.77 3780 Ps
1367 14 73152 88736 216 61.69 676 Ps
1612 44 66080 92780 380 900.59 6132 INFOPATH
Yes this can be first as well and I did that and got the result.
PS C:\WINDOWS\system32> Get-Process | Sort-Object -Property WS | Select-Object -First 5
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
0 0 60 8 0 0 Idle
841 39 22988 8 0.69 2540 3 SystemSettings
538 38 17900 36 0.97 12636 3 WinStore.App
452 29 16568 44 0.81 25724 3 Video.UI
181 11 1800 832 0.08 6544 0 GoogleCrashHandler
Note: The previous answer is awesome and showed everything that the OP needed. I am just showing my way of solving the same thing.

Resources