I'm using this code below to retrieve the value for the TimeGenerated on a win32 event log on a remote server.
$event = Get-WMIObject -ComputerName $server -Query "SELECT * FROM Win32_NTLogEvent WHERE LogFile='Application' AND CategoryString = 'Server Startup'" |
Select -ExpandProperty TimeGenerated -First 1
The return value is:
20160123155933.000000-000
but the event log via the event viewer shows this as the value:
Logged: 1/23/2016 10:59:33 AM
How would I extract the correct date in the format above?
As an aside, if you run your command in the ISE, you can discover properties and commands on the objects returned using IntelliSense.
That said, this article talks a lot about "eventlog" and "TimeGenerated" (the 2 terms I searched on the find this answer).
Don't use -ExpandProperty, but rather call ConvertToDateTime() something similar to what I show below (I modified your call to just grab the first event in my log).
$obj = Get-WMIObject -Query "SELECT * FROM Win32_NTLogEvent WHERE LogFile='Application'" | Select -First 1
$obj.ConvertToDateTime($obj.TimeGenerated).ToString()
This outputs a formatted date converted from raw UTC to local time.
TimeGenerated : 20160124010615.134877-000
becomes
1/23/2016 5:06:15 PM
I think with this info, you have a workable solution to build upon.
Related
I had some old code for documenting the particulars of my machines when I came across Get-ComputerInfo. So I tried to use it (unsuccessfully) and was almost ready to give up when I came across a way to get what I wanted. But now I'm wondering if anyone can help me understand WHY it works the way it does.
It's pretty simple to illustrate:
$OSName1 = Get-ComputerInfo -Property OSName
$OSName2 = (Get-ComputerInfo).OSName
Write-Host $OSName1
Write-Host $OSName2
The above yields:
#{OsName=Microsoft Windows 11 Pro}
Microsoft Windows 11 Pro
I was expecting the 2nd result from the 1st variable. So what's happening differently in those 2 variables? I was expecting them to be the same.
Thanks in advance!
Mark
While the comments do explain what you're already seeing, which is that Get-ComputerInfo -Property OSName returns an object with that property, what isn't obvious is why the command would do that, instead of returning what you expected: the same thing as (Get-ComputerInfo).OSName.
The reason becomes more clear when looking at the help:
Get-Help Get-ComputerInfo
NAME
Get-ComputerInfo
SYNTAX
Get-ComputerInfo [[-Property] <string[]>] [<CommonParameters>]
ALIASES
gin
In the syntax, we can see that -Property takes a String array and not just a single string.
So you can pass an array of property names to return, like this for example:
$info = Get-ComputerInfo -Property OSName, TimeZone, OSProductType
Write-Host $info
And then get:
#{TimeZone=(UTC-05:00) Eastern Time (US & Canada); OsName=Microsoft Windows 10 Enterprise; OsProductType=WorkStation}
Now, I did it that way to match your question, but if you just output the value naturally, or via Write-Output, it would look a lot nicer:
$info
Write-Output $info
TimeZone OsName OsProductType
-------- ------ -------------
(UTC-05:00) Eastern Time (US & Canada) Microsoft Windows 10 Enterprise WorkStation
Or you could format it:
$info | Format-List
TimeZone : (UTC-05:00) Eastern Time (US & Canada)
OsName : Microsoft Windows 10 Enterprise
OsProductType : WorkStation
So the answer why it returns an object with a single property, it's for consistency for when you request multiple properties (or request none and get them all).
This property selection works exactly the same as if you had used Select-Object:
$info = Get-ComputerInfo | Select-Object -Property TimeZone, OSName, OSProductType
It's also worth noting that Get-ComputerInfo is quite slow, and that selecting individual properties does not speed it up in any way, so there is no particular advantage to using the built-in selection vs. selecting after the fact, other than conciseness and readability.
If you need multiple properties, it's definitely not a good idea to make multiple calls to Get-ComputerInfo with different properties selected, as you're retrieving all the same info on every call and then discarding most of it that way.
If you're unsure which properties you need in the first call, just get them all, and choose them later:
$info = Get-ComputerInfo
if ($condition1) {
# do thing with $info.OSName
}
if ($condition2) {
# do thing with $info.TimeZone
}
# etc.
I am trying to query multiple servers with WMI, but I don't always have access to the servers.
The code is below. Alas, it returns "access is denied" to the console, but I can't seem to get rid of it. Oh well.
However, I am trapping the servers that I can't connect to, so that I can tell someone else to look at them, or request access.
But when I run the code, it only returns the first list of servers; even if $failed_servers has values, nothing is returned. If I tell both to pipe to ogv, then two windows pop up.
Why won't both "$variable|select" work? If I remove the select on $failed_servers, then it shows up, albeit just sitting immediately underneath the successful ones. Which is okay-but-not-great.
$list = ("servera","serverb","serverc")
$failed_servers = #()
$final = foreach ($server_instance in $list)
{
$errors=#()
gwmi -query "select * from win32_service where name like '%SQLSERVER%'" -cn $server_instance -ErrorVariable +errors -ErrorAction SilentlyContinue
if ($errors.Count -gt 0) {$failed_servers += $server_instance
}
}
$final|select pscomputername, name, startmode, state |where {$_.pscomputername -ne $null}
$failed_servers |select #{N='Failed Servers'; E={$_}}
What you're experiencing is merely a display problem:
Both your Select-Object calls produce output objects with 4 or fewer properties whose types do not have explicit formatting data associated with them (as reported by Get-FormatData).
This causes PowerShell's for-display output formatting system to implicitly render them via the Format-Table cmdlet.
The display columns that Format-Table uses are locked in based on the properties of the very first object that Format-Table receives.
Therefore, your second Select-Object call, whose output objects share no properties with the objects output by the first one, effectively produces no visible output - however, the objects are sent to the success output stream and are available for programmatic processing.
A simple demonstration:
& {
# This locks in Month and Year as the display columns of the output table.
Get-Date | Select-Object Month, Year
# This command's output will effectively be invisible,
# because the property set Name, Attributes does not overlap with
# Month, Year
Get-Item \ | Select-Object Name, Attributes
}
The output will look something like this - note how the second statement's output is effectively invisible (save for an extra blank line):
Month Year
----- ----
9 2021
Note the problem can even affect a single statement that outputs objects of disparate types (whose types don't have associated formatting data); e.g.:
(Get-Date | Select-Object Year), (Get-Item \ | Select-Object Name)
Workarounds:
Applying | Format-List to the command above makes all objects visible, though obviously changes the display format.
Intra-script you could pipe each Select-Object pipeline to Out-Host to force instant, pipeline-specific formatting, but - given that the results are sent directly to the host rather than to the success output stream - this technique precludes further programmatic processing.
Potential future improvements:
GitHub issue #7871 proposes at least issuing a warning if output objects effectively become invisible.
I have declared 2 PowerShell variables
$prm=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" | Select-Object Name, Vendor, Version
$rgteng=Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'WKFS'" | Select-Object Name, Vendor, Version
I want the output of this variable to a text file o/p #{Name=Wolters Kluwer Financial Services Regulatory Reporting FRA Param 11.2.0; Vendor=Wolters Kluwer Financial Services; Version=11.2.0}, I want this o/p to a text file.
I have tried using Write-Output and Write-Host, but none of them gives right o/p
What happens there looks like this (just the big picture):
Get-WmiObject Win32_Product -Computer . -Filter "vendor = 'Wolters Kluwer Financial Services'" creates an WMI object and pipes it to the next command
Select-Object Name, Vendor, Version transforms that object into a new PSCustom type object (more like a table version of your WMI object wtih only the desired information)
Then it gets messy :
if you use write-host or display it on the screen , the output will be formatted according the the powershell's settings (those settings can be changed by altering xml files)
if you use export-csv you basically use a convertto-csv | out-file c:\sometheing.txt + some formatting rules that are applied. (I think the UTF-8 type of the file is changed but I am not sure...)
So if you want to know exactly how your variable / file will look like, without having powershell formatting interfering with your work, use convertto-csv | out-file.
I am calling the following PowerShell command and assigning the output to a variable:
$my_variable = (Get-Counter -Counter "\Process(process1)\Working Set - Private") | Out-String
The output is:
> Timestamp CounterSamples
> --------- --------------
> 4/7/2015 3:54:00 PM \\smachine101\process(process1)\working set - private :
> 15298560
All I need is '15298560' from the output.
Can you recommend a way to accomplish this?
First thing would be to use Out-String with caution. In doing so you have destroyed the object into a string. String manipulation to extract the wanted data is possible but a waste of good PowerShell-ing when the original object contains that data in a property.
You are just looking for the cooked value? This would work in PowerShell 2.0
Get-Counter -Counter "\Process(chrome)\Working Set - Private" |
Select-Object -ExpandProperty CounterSamples |
Select-Object -ExpandProperty CookedValue
Of course you could write that with aliases and shortened property names but it gives you an idea of what the full command looks like. If you have PowerShell 3.0 you could use dot notation like this
(Get-Counter -Counter "\Process(chrome)\Working Set - Private").CounterSamples.CookedValue
Using a combination of Get-Member and viewing individual properties of objects would have been an approach to figure out this issue.
I need a query that returns the SourceName, Logfile, EventIdentifier, Type, NumberOfEvents from Win32_NTLogEvent where NumberOfEvents is the number of events that share common SourceName, LogFile and EventIdentifier (I am not sure about Type). I would like to use the query in a PowerShell script using Get-CimInstance.
Other solutions to the same problem that can be used in PowerShell is also much appreciated!
Try following:
$Logs = Get-WmiObject -class Win32_NTLogEvent -filter "(logfile='Application')"
Write-Host $logs
of course, filter you can change. If you prefer other "format" of result you can for example to something like:
$Logs | Format-Table EventCode, EventType, Message -auto
UPDATE:
I just read your question again :) To do grouping just invoke:
$logs | Group-Object Type,LogFile,EventCode