PowerShell: How to display in full? - windows

I tried running the following command in PS:
Get-EventLog -LogName Security | findstr 4720
The result I got seems to be squished as if the column widths need to be adjusted. How can I view all the text that is after the ellipses (...)? See screenshot: https://i.imgur.com/fqV5qIs.png
How to view the returned info in full?

As Santiago mentioned you can use Format-Table.
Though since it looks like you're looking for a specific Event ID, I'd recommend instead of using findstr (which may return unrelated results as it's searching for '4720' anywhere in your results - unless that's your intention of course) instead target the attribute using the Where-Object cmdlet (or its' alias ?). Also, if you want a "pure" PowerShell solution I'd recommend using Select-String instead of findstr
E.g.
Get-EventLog -LogName Security | Where-Object {$_.EventID -eq 4720} | Format-Table -AutoSize -Wrap

To expand on the answer from #Novalis, Where-Object like that is definitely faster than findstr, and the Format-Table should sort out the ... you're seeing.
But to take it one step further an even faster method is to use -FilterHashtable. Specifically :
Get-WinEvent -FilterHashtable #{Logname='Security';ID=4720} | Format-Table -AutoSize -Wrap
The reason it's faster is because when using Where-Object you're asking the system for ALL of the system logs, and then once received by your script you're then filtering them out (same with findstr). FilterHashtable just requests the log entries from system that match the require event ID, so less data needs to be sent to your script.

Related

How to get only the uptime of the server on Powershell?

I have the following code, It's work when I use directly within powershell:
Get-WmiObject win32_operatingsystem | select #{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)
And it returns:
LastBootUpTime
--------------
14/09/2019 10:41:50
But when I use the command within a Powershell script .ps1 with invoke-command the output returns more informations:
LastBootUpTime PSComputerName RunspaceId
-------------- -------------- ----------
9/14/2019 10:41:50 AM 192.168.0.20 af08d2d8-c4f1-4f85-9d6c-e3f4ffe475c6
Why this happen?
If possible, I'd like without the header LastBootUpTime too.
Invoke-Command will always return additional information, in this case where the command was run and the runspace id. You can always get results into a variable and simply print out the property you want.E.g.
$result = invoke-command {your-command}
$result.LastBootUpTime
or for short
(invoke-command {your-command}).LastBootupTime
Note that when you are using wmi, you do not need to necessarily use invoke-command, you can also directly pass -computer parameter to it to run the command against a remote computer:
Get-WmiObject win32_operatingsystem -computer "remote_computer_name"
Since you're ultimately only interested in the (transformed) property value, there's no need to use Select-Object (whose alias is select) at all - use ForEach-Object instead:
Get-WmiObject Win32_OperatingSystem |
ForEach-Object { $_.ConvertToDateTime($_.LastBootUpTime) }
Note: The extra properties you saw, added by a remote Invoke-Command call with a -ComputerName argument (described below), are still technically present on the result, but they won't display.
That said, the WMI cmdlets were deprecated in PowerShell version 3. Using Get-CimInstance in lieu of Get-WmiObject actually makes the .ConvertToDateTime() call unnecessary (the .LastBootUpTime now directly contains a [datetime] instance), in which case you can simply use Select-Object's -ExpandProperty parameter in order to return the property value only (rather than a [pscustomobject] instance with the requested property):
Get-CimInstance CIM_OperatingSystem | Select-Object -ExpandProperty LastBootUpTime
Note: Get-CimInstance directly supports a -ComputerName argument, so you don't need Invoke-Command -ComputerName for the invocation; unlike the firewall-unfriendly DCOM protocol that the WMI cmdlets use, the CIM cmdlets use the same, firewall-friendly transport as PowerShell remoting.
Or, more succinctly and efficiently, especially in a case such as this where the command returns only a single object, use direct property access:
(Get-CimInstance CIM_OperatingSystem).LastBootUpTime
This answer contrasts the pros and cons of these two approaches and shows other alternatives.
As for what you tried, which generally relates to:
Managing the origin properties automatically added by remote operations:
In remoting scenarios, PowerShell decorates the objects returned with additional properties that provide origin information. These properties are (mostly) of type NoteProperty and are added:
when PowerShell remoting is involved - such as via Invoke-Command -ComputerName in your case.
when CIM cmdlets such as Get-CimInstance are directly used remotely, such as with the -ComputerName parameter.
These properties are:
.PSComputerName (the name of the remote computer on which the code was executed)
Note: On objects returned from remote CIM calls, .PSComputerName appears as a regular property (type Property), not a NoteProperty.
The associated hidden .PSShowComputerName property, which defaults to $true, which explains why you saw a PSComputerName column in the display output.
If you capture the objects before printing them to the screen, you can set the property to $false on them, in which case their .PSComputerName property won't show (but will still be there) - however, the .RunspaceId property may - situationally - still show, and would have to be explicitly excluded - see below.
PowerShell remoting only (not remote CIM calls): .RunspaceId (the ID of the remote runspace)
To exclude these from local display / presence on the object, use the following techniques:
If you're only interested in select properties, make the Select-Object call locally, which, by virtue of locally constructing new [pscustomobject] instances with the properties of interest only, implicitly excludes the remoting-added properties:
Invoke-Command -ComputerName ... { ... } |
Select-Object Name, LastBootUpTime # LOCAL call to Select-Object
If you're interested in all properties except the remoting-added ones, use Select-Object -ExcludeProperty to eliminate them explicitly:
# Get remote output, then locally exclude the remoting-added properties.
Invoke-Command -ComputerName ... { ... } |
Select-Object * -ExcludeProperty PSComputerName, PSShowComputerName, RunSpaceId
Note: Select-Object generally returns [pscustomobject] instances whose properties are static copies of the input objects and which lack the input type's methods.
I found one way! if someone to need here is:
Get-WmiObject win32_operatingsystem | select #{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}|Select-Object -ExpandProperty lastbootuptime
Here is how I used (I'm creating a report in HTML for my database)
write-output "<p> Horario do Ultimo boot: $(Get-WmiObject win32_operatingsystem | select #{LABEL=’LastBootUpTime’;EXPRESSION={$_.ConverttoDateTime($_.lastbootuptime)}}|Select-Object -ExpandProperty lastbootuptime)</p>"
The output was (in my language and region):
Horario do Ultimo boot: 09/14/2019 10:41:50

What is the most efficient way on getting a list of files utilizing get-childitem

I have created a list of PowerShell commands for getting over 500,000 rows of directories. The goal is to get a list of the files in each of the directories specified in the PowerShell command. My syntax works perfectly if I run a small batch, but there are definitely performance issues when running them in a bulk manner. One thing I noticed is that if I run all these 500,000 rows together, I get extremely high usage (about 12GB and using 97% of memory) and it takes a while for me to even begin to generate a CSV file. Please see my code listed below on what I am using
I was thinking I can get a list of the directories I need to use into a CSV. And researching around here, I can use a CSV as a variable and a foreach. But I am stumped on putting all that together.
Get-ChildItem -Path \\MYIP\ARCHIVE\ArchiveVolumes\UniqueID\ -Exclude *.wav*,*.md5*,*.abc, -Recurse |
Select-Object FullName |
Add-Member -MemberType NoteProperty -Name Myfield -Value 123456 -PassThru |
Export-Csv -Append -Path C:\mypath\fileslist.csv -Encoding ascii -NoType
I'm hoping that I can better utilize what I am running here as I am still learning powershell. Any ideas?

How to column print only certain row parts of a list in powershell?

I have tried various ways to format the output from a poweshell command and would like to print only some of the row items in the list as part of a a column in one line.
Perhaps more easy to illustrate:
# I want the output from:
Get-CimInstance Win32_OperatingSystem | select Caption,Version,OSArchitecture,InstallDate | fl
Caption : Microsoft HAL 9000
Version : 6.3.9000
OSArchitecture : 64-bit
InstallDate : 2018-08-16 00:50:01
# To look like this:
Microsoft HAL 9000 (6.3.9000) 64-bit [2018-08-16 00:50:01]
How can this be easily accomplished?
(Coincidentally I want all the rows in this case, but a more general answer may be more useful, if it also include rows that we don't want.)
PowerShell usually returns objects and outputs a string representation of it to the host. You want a custom string format output to the host. You can achieve that in various ways, however the fastest way and my recommendation would be to use the -f operator.
$OS = Get-CimInstance Win32_OperatingSystem
'{0} ({1}) {2} [{3}]' -f $OS.Caption, $OS.Version, $OS.OSArchitecture, $OS.InstallDate
With here-strings use can do the same with multi-line.
$OS = Get-CimInstance Win32_OperatingSystem
#'
My OS is {0} {1})
Architecture --> {2}
Installation Date: [{3}]
'# -f $OS.Caption, $OS.Version, $OS.OSArchitecture, $OS.InstallDate
However, you should work with objects as much as - and as long as it is possible.
I would belive this should work for you:
$temp = (Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, OSArchitecture,InstallDate)
The Select-Object makes sure that you get the desired properties. Having a variable with all the details in it, we can concatenate it like this:
"$($temp.Caption) ($($temp.version)) $($temp.OSArchitecture) [$($temp.InstallDate.ToString("yyyy-MM-dd hh:mm:ss"))]"
Simply use Format-Table instead of Format-List. They both support a list of properties you want to see. So if you don't want all columns, list the ones you want.
# 'default' properties in a table
Get-CimInstance Win32_OperatingSystem | ft
# only some properties in a table
Get-CimInstance Win32_OperatingSystem | ft Caption, OSArchitecture
# without table headers
Get-CimInstance Win32_OperatingSystem | ft Caption, OSArchitecture -HideTableHeaders
# all properties in a list (because there are too many for a table)
Get-CimInstance Win32_OperatingSystem | fl *

Powershell script: List files with specific change date (Amount if possible)

For license porpuses I try to automate the counting process instead of having to login into every single server, go into directory, search a file name and count the results based on the change date.
Want I'm aiming for:
Running a powershell script every month that checks the directory "C:\Users" for the file "Outlook.pst" recursively. And then filters the result by change date (one month or newer). Then packing this into an email to send to my inbox.
I'm not sure if that's possible, cause I am fairly new to powershell. Would appreciate your help!
It is possible.
I dont know how to start a ps session on a remote computer, but I think the cmdlet Enter-PSSession will do the trick. Or at least it was the first result while searching for "open remote powershell session". If that does not work use the Invoke-Command as suggested by lit to get $outlookFiles as suggested below.
For the rest use this.
$outlookFiles = Get-ChildItem -Path "C:\Users" -Recurse | Where-Object { $_.Name -eq "Outlook.pst" }
Now you have all files that have this name. If you are not familiar with the pipe in powershell it redirects all objects it found with the Get-ChildItem to the next pipe section and here the Where-Object will filter the received objects. If the current object ($_) will pass the condition it is returned by the whole command.
Now you can filter these objects again to only include the latest ones with.
$latestDate = (Get-Date).AddMonths(-1)
$newFiles = $outlookFiles | Where-Object { $_.LastAccessTime -gt $latestDate }
Now you have all the data you want in one object. Now you only have to format this how you like it e.g. you could use $mailBody = $newFiles | Out-String and then use Send-MailMessage -To x#y.z -From r#g.b -Body $mailBodyto send the mail.

Grab the latest volume using PowerShell

I'm struggling trying to grab the latest volume/Drive using PowerShell
I have a result of a PowerShell look like this
PS C:\Users\me> Get-WMIObject Win32_Volume | select Name
Name
----
C:\
D:\
E:\
\\?\Volume{021a6bbd-0b97-4973-824a-7c635e362f09}\
\\?\Volume{bae1c1d6-59c3-44b1-9360-b7d3101c0e92}\
PS C:\Users\me>
If I want to access just this
E:
How can I filter out to :\ with the highest alphabetical order ?
I've been trying so many options using Select-String, but seems to get worse result.
The ones you want don't start with "\\". The drive letters may be returned in any order, so you need to sort them and take the last one:
Get-WMIObject Win32_Volume | Where-Object {$_.Name -NotLike '\\*'} | select Name | Sort-Object -Property Name | Select-Object -Last 1
Or, if the drive letter is known to be in the range A to Z, then it would be more sensible to use -Like '[A-Z]*' instead of -NotLike '\\*'.
Try something like this
Get-WMIObject Win32_Volume | where {$_.Name -eq "E:\"}
this should give you a list of objects wich you can access like an array. Also there is a lot of useful information here https://technet.microsoft.com/en-gb/library/2007.04.powershell.aspx

Resources