duplicates when using directorysearcher - powershell

I have a script that is using DirectorySearcher to query Active Directory for around ~13k users total every day.
I have been told that there are duplicates in my report, but I cannot figure out why.
The duplicates usually appear at the end of the report, and has been 6-7 users so far. The only difference between these users & their previous entry in the report is that their last logon time has changed (the time of which is seconds AFTER the script was initially started)
#Get date for 3months back in datetime format
$Date = (Get-Date).AddDays(-90)
# Correct for daylight savings.
If ($Date.IsDaylightSavingTime)
{$Date = $Date.AddHours(-1)}
# Convert the datetime value, in UTC, into the number of ticks since
# 12:00 AM January 1, 1601.
$Value = ($Date.ToUniversalTime()).Ticks - ([DateTime]"January 1, 1601").Ticks
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.PageSize = 30000
$Searcher.Filter = "(&(&(objectCategory=person)(objectClass=user))(lastLogonTimeStamp>=$value)(pwdLastSet>=$value)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
$Searcher.SearchRoot = 'LDAP://dc=contoso,dc=net'
$results = $Searcher.FindAll()
foreach ($result in $results)
{
# Fetches different attributes for each user
# which is then appended to a .csv file via Add-Content
}
It feels like I am identifying additional users based on the fact that their last logon time was changed.. does anyone know anything about this? Maybe
How I can disable this behavior?
The script runs at 06:00:00.
Here is the last logon time for the duplicate entries
10/31/2015 06:00:24
10/31/2015 06:00:32
10/31/2015 06:02:07
10/31/2015 06:05:01
10/31/2015 06:06:05
10/31/2015 06:08:19
10/31/2015 06:08:36

Related

Writing Foldernames in a Array Powershell

I would like to write the directory names of several folders in an array. However, only all directory names with a date <today should be read. The directory names contain a date in this form * YYYYMMDD *
So I would have to do the following:
Borrow the date
Write the date in the form of YYYYMMDD in a variable
Read out directory names and check against the variable
Write data to an array ... do something ...
Can someone tell me how I can solve this with Powershell please?
Thank you
Start by retrieving all the candidate directories, then use Where-Object to extract the date part and test that it describes a date prior to today:
# Define threshold
$Today = (Get-Date).Date
# Go through all candidate directories
$oldDirectories = Get-ChildItem .\path\to\root\folder -Directory |Where-Object {
$dt = 0
# Test if directory name contains 8 consecutive digits describing a valid date
if($_.Name -match '(\d{8})' -and [datetime]::TryParseExact($Matches[1], 'yyyyMMdd', , $null, 'None', [ref]$dt)){
# We only want the ones with a date prior to today
$dt.Date -lt $today
}
else{
# Not containing a properly formatted date, we're not interested
$false
}
}
# Now we can extract the names
$oldDirectoryNames = #($oldDirectories.Name) # or #($oldDirectories |Select -Expand Name)
Do these directorynames start with the date?
yes
What do you mean by Borrow the date? Is that the date of today or what?
Determine the Date, Yes of today.
I read out the date accordingly and wrote it in a variable:
$Timestamp = ([datetime]::now).tostring("yyyyMMdd")
Now I want to read out all directory names which have got a Date < 1 Day and would like to process it in a foreach for further processing
Understandable?

Powershell keep looping until condition is true then proceed

I have written a script that so far is able to check a file "latest.json" for the "created_at" object which shows the last date that a commit has occurred for software.
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
How part of latest.json looks like
"created_at":"2020-03-23 17:32:48"
How do I change this to keep looping until the date pull from latest.json matches then proceed to next step (would download and install software). Also, since "created at" has "17:32:48" will this cause the date check to fail since the time does not match?
. I want it to keep checking if dates match.
Thank you!
Right now, I'm not going to bother converting dates to match to make sure they're the same format, but what you need for your specific questions is just a do until loop. I might update this to check the date formats if you supply an example layout of the returned JSON.
Do{
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
start-sleep -s 60
}until($websiteJson -eq $todaysDate)
I believe this wont work right off the bat. You'll have to get the JSON date and $todaysDate to be the same format, then you can do this and it will work.
if you want to compare the date and/or time, use datetime objects instead of datetime strings. something like this ...
if you want to test for the actual time difference between two time objects ...
((Get-Date -Date '2020-03-23 18:11:22') - [datetime]'2020-03-23 17:32:48').TotalHours
# result = 0.642777777777778
you keep mentioning date as if you don't want the time, so this method would work for comparing the date parts of two timestamps ...
# the date at the time the code was run = 2020 April 03, Friday 4:30:34 PM
$Today = (Get-Date).Date
$Created_At = '2020-04-03 15:15:15'
$Today -eq ([datetime]$Created_At).Date
result = True

Counter number of times a user triggers failed logon in powershell

My plan is to create a script that will gather each previous day's worth of failed logins from the security log. I want a way to count the number of times the same user triggers an alert since the end goal is to build a simple web site that displays the username, the number of failed logons they triggered and the name of the server where the alert was triggered. I have the start below:
#get a list of all disabled user email address and store it in
disabledUsers variable
$disabledUsers = Get-ADUser -filter * -SearchBase
"OU=Users,OU=Disabled,OU=COMPANY,DC=example,DC=local" -Properties mail | select -expandproperty mail
#empty array that will store all the usernames parsed below
$userArray = #()
#iterate through each user account in the disabledUsers variable
foreach ($user in $disabledUsers){
#for every email address, split the value based at the # symbol and retrieve the first field/index and add that to the userArray array
$userArray += $user.Split("#")[0]}
#sets the previous day's time and date
$yesterday = (Get-Date).AddDays(-1)
#get all failed login attempts since yesterday and extract the time of the error, server where error was logged, and user account that triggered the error
$failedLogins = get-eventlog -LogName Security -After $yesterday -EntryType FailureAudit -InstanceId 4625 | select timewritten,machinename,#{n='account';e={$_.replacementstrings[5]}}
#iterate through each entry in the failedLogins variable
foreach ($failedLogin in $failedLogins) {
<# define a counter variable to increment the check between the username in each failed event log against each
username defined in the userArray array. Loop keeps checking until $i is greater than or equal to the number of
entries in the userArray array
#>
for ($i=0; $i -lt $userArray.Length; $i++) {
#everytime $i is not equal or greater than # of counts in userArray, check and see if the
#username in the event log matches the current username in the userArray index (represented by the $i)
if ($failedLogins.account -match $userArray[$i]) {
#if there is a match......
} else {
}
}
}
I'm not sure how best to build this counter. In case anyone is wondering, the use case for this is because we started noticing a bunch of failed login attempts from a disabled user account about once every 1-2mins. Trying to build a way to monitor this.

How to get the next business day in powershell

I have the following test code. Basically I am checking when a new file is created in folder. I need to know that if the file was created after 4pm display the next business day. Currently my code displays the next day, but I need to display the next business day. Any help would be appreciated.
$formatteddate = "{0:h:mm:ss tt}" -f (get-date)
if ($formatteddate -gt "4:00:00 PM"){
$(Get-Date).AddDays(1).ToString('MMM d yyyy')
}
Adding to what jisaak said: "business day" is organization specific. Some organizations don't work on holidays that other organizations do. If you want to handle holidays correctly you'll need an explicit list of holidays for your business
Omitting the formatting details (which OP seems to understand) this should do it:
# $date is input date
$nextBizDay = $date.adddays(1)
# You would probably want to generate the follow list programmatically,
# instead of manually as done here
$holidays = 1, <# New Years #>
18, <# MLK day 2016 #>
<# other holidays encoded as Day Of Year #>
360 <# Christmas in a Leap Year #>
# An alternative to a list of holidays like this is to find a web service
# you can query to get the holidays for a given year
while ($nextBizDay.DayOfWeek -eq 'Saturday' -or
$nextBizDay.DayOfWeek -eq 'Sunday' -or
$nextBizDay.DayOfYear -in $holidays) {
if ($nextBizDay.DayOfYear -gt 366) {
throw "No next business day this year. Need to add additional logic"
}
$nextBizDay = $nextBizDay.adddays(1)
}

How to get retrieve relevant calendar events through Google Calendar API?

I have come this far with my script, which is simply supposed to retrieve the entries for a particular calendar for a specific time period (i.e. exactly what I see in the calendar).
#Powershell
ls (join-path $Script:scriptpath .\GDataCmdLet-master\Binaries\*.dll) | % {
[System.Reflection.Assembly]::LoadFile($_)
}
$service=new-object Google.GData.Calendar.CalendarService('Test')
$cred = New-Object Google.GData.Client.GDataCredentials('joe#gmail.com', '1234')
$service.credentials=$cred
$eventquery=new-object Google.GData.Calendar.EventQuery
$eventquery.uri='http://www.google.com/calendar/feeds/joe#gmail.com/private/full'
$eventquery.StartDate = (Get-Date -Date '2014-02-10')
$eventquery.EndDate = (get-date -date '2014-02-20')
$eventfeed=$service.query($eventquery)
The DLLs I got from https://github.com/robertj/GDataCmdLet
All events from the calendar have actually been removed (i.e. I don't see any in the webinterface), but I keep on getting these as a result.
Questions, an answer to either one would suffice:
Is there a flag in the results, which distinguishes deleted from non-deleted events?
Is there a way to retrieve only the non-deleted events in the first place? (the parameter ?showhidden=false on the query didn't help)
Thank you!
Sandro
Solved it! The following seems to work, not sure exactly why tough
ls (join-path $Script:scriptpath .\GDataCmdLet-master\Binaries\*.dll) | % {
[System.Reflection.Assembly]::LoadFile($_)
}
$service=new-object Google.GData.Calendar.CalendarService('Test')
$cred = New-Object Google.GData.Client.GDataCredentials('joe#gmail.com', '1234')
$service.credentials=$cred
$eventquery=new-object Google.GData.Calendar.EventQuery
$eventquery.uri='http://www.google.com/calendar/feeds/joe#gmail.com/private/basic'
#don't use StartDate and EndDate this way
#they just didn't have the expected effect
$eventquery.StartTime = (Get-Date -Date '2014-02-10')
$eventquery.EndTime = (get-date -date '2014-02-30')
#that does the trick to get the actual occurences, not just the events
#and it also removed the non-deleted ones
$eventquery.SingleEvents = $true
$eventfeed=$service.query($eventquery)
Now I don't know where to get the start and end times of the occurences from, but that is for another question to answer...