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

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

Related

PowerShell: How to display in full?

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.

how to get unidentified network adaptor name with batch

I already knew how to get all network adaptors names, but I can't tell the difference between normally using and not identified
By using
netsh interface ip show interfaces
or other commands ,you may get all adaptors names.
The necessary information can be obtained using the Win32_NetworkAdapter class.For example:
Get-CimInstance -ClassName Win32_NetworkAdapter -Filter #'
NetConnectionID = "Local Area Connection" AND
NetConnectionStatus=2 AND NetEnabled = True AND PhysicalAdapter = True
'# | Format-List *
The Get-WmiObject cmdlet can also be used, but starting in PowerShell 3.0, it has been superseded by Get-CimInstance.Starting with Windows 8, you can use the Get-NetAdapter cmdlet.

How to format CCM_UserAffinity output to tyoe Microsoft.PowerShell.Commands.LocalPrincipal

I am trying to create a deployment script which adds freshly deployed workstation primary users to local admin group. I utilized CCM_userAffinity class to obtain username, however - Add-LocalGroupMember does not accept its output.
Ive tried creating task sequence variable to pass into powershell script which adds to group with no success either. Preferably the solution would be integrated within deployment TS, however due to no success i have reverted to ps package deployment.
$computer = "LocalHost"
$namespace = "root\ccm\Policy\Machine"
$query = "ConsoleUser"
$PrimaryUser = Get-WmiObject -class CCM_UserAffinity -computername $computer -namespace $namespace | select-object $query | format-wide
i expected the output from -class CCM_UserAffinity to be accepted by Add-LocalGroupMember, however i get this instead -
Add-LocalGroupMember : Cannot bind parameter 'Member'. Cannot convert the "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" value of type
"Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" to type "Microsoft.PowerShell.Commands.LocalPrincipal".
As you plan on using the value you retrieve and not displaying it there is no need to use something like "format-wide" which only makes the output human readable and is the reason for your FormatStartData datatype.
You can just use :
$PrimaryUser = (Get-WmiObject -class CCM_UserAffinity -computername $computer -namespace $namespace).ConsoleUser
which returns a string and that is taken by the -Member argument of Add-LocalGroupMember
One thing to keep in mind is that in theory there can be more than one ConsoleUser per machine. So the ConsoleUser might be an Array or not. If you can guarantee that there is always only one user in your environment per machine (at the point where the ts runs) you can just use it as is. Otherwise you would have to specify which user you want to use and I can of course not tell you what a good rule for that for your environment would be.
Also I hope you checked that the WMI class CCM_UserAffinity is already populated at the stage where you want to run this script, I could not tell you if this is the case.

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 *

Why am I getting no output when I try to search for a deleted user in Active Directory through PowerShell?

I am trying to search Active Directory for deleted users with PowerShell, but am unable to return any results even though I have used the -IncludeDeletedObjects parameter. Here is the command that I used:
get-adobject -filter{Name -like "$user"} -includedeletedobjects -properties *
The answer that worked for me is the command below will list all the users that were deleted from the Active Directory if your AD recycle bin is enabled and if you have sufficient privileges on Active Directory
Get-AdObject -Filter 'ObjectClass -eq "user" -and IsDeleted -eq $True' -IncludeDeletedObjects -Properties * | Ft Name,IsDeleted,WhenCreated
If you don't have the AD Recycle Bin enabled, you won't be able to find deleted objects.
If $user is expected to an exact match, you should also be using the -eq operator, not -like. If you want a fuzzy match, -like is correct but you should surround $user with * like so: *${user}*.
If $user is supposed to be the logon name, and not the friendly name of the user, then Name isn't the correct property to filter on, you will want to check against SamAccountName, not Name:
Get-ADObject -Filter "SamAccountName -eq '$user'"
If you are only interested in user objects, and not other AD object types, consider usingGet-ADUser in lieu of Get-ADObject. The syntax for what you specified above is the same, but will guarantee you only get ADUser objects, not ADComputer, ADGroup, etc.
Also, you should avoid using -Properties * and -Filter { ScriptBlock } arguments when using the AD cmdlets. Only use the Properties you need to process later, and use a string based filter like so:
Get-ADObject -Filter "Name -like '*$user*'"
See my answer here for best practices when using the -Filter parameter with AD cmdlets (also explains why not to use -Properties *), and this answer here for more details on why you should not use ScriptBlock parameters for AD filters.

Resources