I am trying to get RDP session event( event ID: 22 and 25) for a number of computers and export as a CSV file. I need to get the first instance of a RDP session the user has initiated on each day( There may be many RDP session reconnection/day) so I can create a report what time each user is initiating the first RDP session.
$week = (Get-Date) - (New-TimeSpan -Day 10)
$Events = Get-WinEvent -ComputerName $ComputerName -LogName $LogName | Where-Object { ($_.TimeCreated -ge $week) -and (($_.Id -eq '22') -or ($_.Id -eq '25')) }
foreach ($Event in $Events) {
$EventXml = [xml]$Event.ToXML()
$EventTime = $Event.TimeCreated.ToString()
$Username = $EventXml.Event.UserData.EventXML.User
}
The CSV file has the time column which contains the connection time in (mm/dd/yyyy HH:mm) format. I am struggling to get the group and sort command to get the first instance of a connection in each day.
Any help will be much appreciated.
I added lots of comments to help you with the thought process
$logFilter=#{
LogName='Microsoft-Windows-TerminalServices-LocalSessionManager/Operational'
ID=22,25
StartTime=[datetime]::Now.Adddays(-30)
}
# Get all events 22 & 25 for the past 30 days
$events=Get-WinEvent -FilterHashtable $logFilter
# Since we want the first Event per Date, we need to
# group all events by each Day
$groupByDay=$Events|Group-Object {$_.TimeCreated.ToShortDateString()}
# Looks like this
PS /> $groupByDay
Count Name Group
----- ---- -----
68 5/4/2021 {System.Diagnostics.Even...
76 5/3/2021 {System.Diagnostics.Even...
12 5/2/2021 {System.Diagnostics.Even...
22 5/1/2021 {System.Diagnostics.Even...
62 4/30/2021 {System.Diagnostics.Even...
46 4/29/2021 {System.Diagnostics.Even...
# Now we want to group each day by User and get the first log for each one of them
# To see an example of how it looks you can use this =>
$groupByDay[0].Group|Group-Object {$_.Properties.Value[0]}
# Note
$events[0].Properties.Value[0]
# Is the same as
([xml]$events[0].ToXml()).Event.UserData.EventXML.User
# Create a new export grid
$grid=[collections.generic.list[pscustomobject]]::new()
# For each day in all days logs
foreach($group in $groupByDay)
{
$groupByUsers=$group.Group|Group-Object {$_.Properties.Value[0]}
foreach($user in $groupByUsers)
{
# Logs are always sorted by newest to oldest
# we can assume that the first log we get from pipeline
# is the one we want for each user
$temp=$user.group|Select -First 1
# Add this object to our export grid
$grid.Add(
[pscustomobject]#{
Time=$temp.TimeCreated.ToString('MM/dd/yyyy HH:mm')
EventID=$temp.Id
User=$user.Name
})
}
}
Export should look something like this:
Time
EventID
User
05/04/2021 16:00
25
user.example1
05/04/2021 15:55
25
user.example2
05/04/2021 14:40
22
user.example3
05/03/2021 16:00
25
user.example1
05/03/2021 15:55
25
user.example2
05/03/2021 14:40
22
user.example3
I'm trying to compare two TICKS times, and i need the comparisons to be a little less precise and consider DateTime objects equal even if they were a few milliseconds apart (half minute tops) by removing any excess milliseconds and ticks from their DateTime objects (following jacubs guide).
problem is that my first ticks value ($date1) is generate from a performance counter, and i cannot convert him back to Date time again (Get-Date -Date ($date1)), getting the following error message:
Get-Date : Cannot bind parameter 'Date'. Cannot convert value
"636763462457113590" to type "System.DateTime". Error: "String was
not recognized as a valid dateTime"
This is my script:
$date1 = (Get-Counter -Counter '\TimeCheck\TIME').CounterSamples[0] | Select-Object -ExpandProperty RawValue
Get-Date $date1
Get-Date -Date ($date1) -Millisecond 0 | Select -ExpandProperty Ticks
$date2 = Get-Date
$date2.Ticks
Get-Date -Date ($date2) -Millisecond 0 | Select -ExpandProperty Ticks
$date1 -eq $date2
The only method this command works for me is if i wrote the TICKS time itself:
PS C:> Get-Date -Date 636763462457113590
Sunday, October 28, 2018 5:57:25 PM
What i'm doing wrong? even using out-string isn't working.
looks like $date1 in "Get-Date -Date ($date1)" is not numeric (based on error)
try Get-Date -Date ([int64]$date1) or [datetime][int64]$date1
this will convert from a tick count to a datetime object ...
$Ticks = 636763462457113590
$TimeFromTicks = [datetime]$Ticks
$TimeFromTicks
output = 2018 October 28, Sunday 5:57:25 PM
I'm trying to put in a .txt file the first day and the last day of the months using PowerShell.
In the exemple below i was trying to get the first and the last day of July, but i'm just getting the first day. The second line of the script isn't working.
#PowerShell "(Get-Date).AddMonths(1).ToString('01/MM/yyyy')" >>dates.txt
$LastDayInMonthString = "$($(get-date).AddMonths(1).ToString("dd/mm/yyy"))$LastDayInMonth" >>dates.txt
Someone can say me what is wrong?
I wanted a .txt file like it: 01/07/2018, 31/07/2018.
The first line write the first day of next month,
and second line write the last day of that month.
Much simpler solution is to call into the DaysInMonth function
[DateTime]::DaysInMonth(2018, 11)
For the current month that would look like:
$today = get-date
$lastDay = [DateTime]::DaysInMonth($today.Year, $today.Month)
$firstDate = [DateTime]::new($today.Year, $today.Month, 1)
$lastDate = [DateTime]::new($today.Year, $today.Month, $lastDay)
$firstDate
$lastDate
This also works around any hindering daylight savings changes and other weird things that can happen with timezones etc.
Or if pure strings are all you need:
(get-date -Format "yyyy/MM") + "/1"
(get-date -Format "yyyy/MM") + "/" + [DateTime]::DaysInMonth((get-date).Year, (get-date).Month)
An easy way is to take the last day of the previous year and add 1..12 months to it:
1..12 | % { (New-Object DateTime(2017,12,31)).AddMonths($_) }
Output will be in the user's date/time format, in my case Dutch:
woensdag 31 januari 2018 00:00:00
woensdag 28 februari 2018 00:00:00
zaterdag 31 maart 2018 00:00:00
maandag 30 april 2018 00:00:00
donderdag 31 mei 2018 00:00:00
zaterdag 30 juni 2018 00:00:00
dinsdag 31 juli 2018 00:00:00
vrijdag 31 augustus 2018 00:00:00
zondag 30 september 2018 00:00:00
woensdag 31 oktober 2018 00:00:00
vrijdag 30 november 2018 00:00:00
maandag 31 december 2018 00:00:00
If required you can format it as you need it, e.g.
1..12 | % { (New-Object DateTime(2017,12,31)).AddMonths($_).ToString("yyyyMMdd") }
20180131
20180228
20180331
20180430
20180531
20180630
20180731
20180831
20180930
20181031
20181130
20181231
This seems simple enough
$firstDate = [DateTime]::new($reportDate.Year, $reportDate.Month, 1)
$lastDate=$firstDate.AddMonths(1).AddDays(-1)
Edit removed the for only date unneccessary time adjustments
In PowerShell to get the first day and last of next month
$CIGB = New-Object System.Globalization.CultureInfo('en-GB')
'{0}, {1}' -f (Get-Date -Day 1).AddMonths(1).ToString('d',$CIGB),
(Get-Date -Day 1).AddMonths(2).AddDays(-1).ToString('d',$CIGB)|sc dates.txt
The $CIGB is neccessary for me because my local date separator overrides the /
If your short date format 'd' returns dd/MM/yyyy the first line and the ,$CIGB can be removed.
01/07/2018, 31/07/2018
This can be wrapped in a single (albeit quite long) line.
powershell -nop -c "$CIGB=New-Object System.Globalization.CultureInfo('en-GB');'{0}, {1}' -f (Get-Date -Day 1).AddMonths(1).ToString('d',$CIGB),(Get-Date -Day 1).AddMonths(2).AddDays(-1).ToString('d',$CIGB)">>dates.txt
> type dates.txt
01/07/2018, 31/07/2018
Strings can be passed to Get-Date. The -Format parameter also accepts strings/variables.
# Get the previous month
$LastMonth = (Get-Date).AddMonths(-1)
# Format the first day of the month
$FirstDayOfMonth = $LastMonth | Get-Date -Format "yyyy/MM/01"
# Calculate the number of days (last day) in the month
$LastDay = [DateTime]::DaysInMonth($LastMonth.Year, $LastMonth.Month)
# Use it in the format parameter
$LastDayOfMonth = $LastMonth | Get-Date -Format "yyyy/MM/$lastDay"
I used Get-WinEvent in Powershell to get eventlog in a time interval. To avoid data loss or repeat, I need to know the interval type of StartTime and EndTime.
In the following example in MSDN:
PS C:\> # Use the Where-Object cmdlet
PS C:\>$yesterday = (Get-Date) - (New-TimeSpan -Day 1)
PS C:\>Get-WinEvent -LogName "Windows PowerShell" | Where-Object {$_.TimeCreated -ge $yesterday}
# Uses FilterHashTable
PS C:\>$yesterday = (Get-Date) - (New-TimeSpan -Day 1)
PS C:\>Get-WinEvent -FilterHashTable #{LogName='Windows PowerShell'; Level=3; StartTime=$yesterday}
It seems that StartTime means ">=".
But I did not find any info about EndTime. what's it represent? "<" or "<="?
EndTime means <=. Just ran a test on my PC. When I set EndTime=(get-date -Date "03.08.2015 14:07:27") I get events on that precise time. Also the timestamps in the event log don't contain milliseconds, therefore filtering is done by 1 second precision.
I need to create a time-frame that is since 3 hours ago and before NOW by setting 2 string parameters:
[string] since
[string] before
whereas each parameter is in a DateTimeOffset format as : "yyyy-MM-dd HH:mm:ss z:00"
How can I set since and before parameters in PowerShell?
The DateTime structure contains useful methods, like .AddHours() and .ToString(). Just add -3 hours to current date. Use the standard date and time format strings to get desired output or roll a cusom one.
PS C:\> $now = get-date
PS C:\> $then = $now.AddHours(-3)
PS C:\> $now.ToString("u")
2013-06-03 18:43:29Z
PS C:\> $then.ToString("u")
2013-06-03 15:43:29Z