Output bottom line in Powershell - windows

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

Related

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...

"gwmi win32_quickfixengineering" but only need InstalledOn date

gwmi win32_quickfixengineering InstalledOn |sort installedon -desc | select -First 1
I've tried but that gives me an odd formatting. I simply need to return the installedOn date and maybe the name.
i'm trying to find the most recently installed patch on a system and get that date value.
I've also tried.
gwmi win32_quickfixengineering |sort installedon -desc | select -First 1
better formatting but still too much information.
To get just the InstalledOn properties, you can use the -ExpandProperty option as below.
GWMI win32_quickfixengineering | sort -Descending InstalledOn `
| Select -ExpandProperty InstalledOn -First 1
Otherwise you can do something like the below to get a brief overview of the installed KBs.
GWMI win32_quickfixengineering | Select HotFixID, InstalledOn, Caption
Info:
Select -ExpandProperty
Get-HotFix / win32_quickfixengineering
The easiest way to get specific information you want is the following:
Lets say you need a name of a service for a command:
$Service = Get-Service Spooler
That command would retrieve more information than just the name, but to get the only name, you can type:
$Service.name
That will return only that value from the saved variable.
So in your case you could do:
(Here you save all the information into a variable)
$Quickfix = gwmi win32_quickfixengineering | sort installedon -desc | select -First 1
(You can then use that variable to return specific information from that variable)
Then use: $Quickfix.InstalledOn
That will return you JUST the date.
Then you could do something like:
Write-Output "Latest update was $($Quickfix.HotFixID) installed on: $($Quickfix.InstalledOn)"
That will give you an output of the KB and the date installed. You can of course edit the text, it was just an example.

Combining several outputs into a table

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.

Powershell Formatting - Pipeline vs Control structure (?)

I am still rather new to PowerShell and saw the two examples below and was wondering why they show two different results when, at least to me, they're seem to query for the same answer. Thanks ahead for the input.
get-host | select version
Vs.
(get-host).version
Get-Host | Select-Object version creates a custom object with a single property, Version, from the inputobjects which in this case is the output from Get-Host.
PS C:\Users\frode> Get-Host | Select-Object Version | Get-Member -MemberType Properties
TypeName: Selected.System.Management.Automation.Internal.Host.InternalHost
Name MemberType Definition
---- ---------- ----------
Version NoteProperty version Version=5.0.14257.1000
(Get-Host).Version loops through the objects returned from Get-Host and extract/expands the value of the Version-property. This is the same as running Get-Host | Select-Object -ExpandProperty Version or Get-Host | Foreach-Object { $_.Version }.
PS C:\Users\frode> (Get-Host).Version | Get-Member -MemberType Properties
TypeName: System.Version
Name MemberType Definition
---- ---------- ----------
Build Property int Build {get;}
Major Property int Major {get;}
MajorRevision Property int16 MajorRevision {get;}
Minor Property int Minor {get;}
MinorRevision Property int16 MinorRevision {get;}
Revision Property int Revision {get;}

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