Script to check files at a server for a certain time - powershell

I'd created below script to check files remaining at a particular path in server.
I've below question please help me out.
How to change file.CreationTime to 12 hours format.
How to export the entire contents to file or email.
Kindly help me in fine tuning the below script
$fullPath = "\\server\D$\fn_1"
$numdays = 0
$numhours = 0
$nummins = 1
function ShowOldFiles($path, $days, $hours, $mins)
{
$files = #(get-childitem $path -include *.* -recurse | where {($_.LastWriteTime -lt (Get-Date).AddDays(-$days).AddHours(-$hours).AddMinutes(-$mins)) -and ($_.psIsContainer -eq $false)})
if ($files -ne $NULL)
{
for ($idx = 0; $idx -lt $files.Length; $idx++)
{
$file = $files[$idx]
write-host ("File Name: " + $file.Name, ", Pending Since : " + $file.CreationTime) -Fore Red
}
}
}
ShowOldFiles $fullPath $numdays $numhours $nummins

To dump to a file, replace your whole for loop with this:
$files | select-object Name,#{name="Pending Since";Expression={$_.CreationTime}}|export-csv -notypeinfo -path c:\output.csv;
This will produce a CSV file with all of your files listed, along with their creation time. Save the formatting for your final delivery/presentation to the user (in this case, you could format the columns in Excel & then save as XLSX).
To send via email, you'll probably want to convert it to HTML.
$filesForEmail = $files | select-object Name,#{name="Pending Since";Expression={$_.CreationTime}} | convertto-HTML;
send-mailmessage -to RECIPIENT -from FROM -subject "Your file listing" -body $filesForEmail -BodyAsHTML -smtpserver smtp.yourcompany.com

You can format the CreationTime value by running it through get-date and using the -format command and the standard DateTime formatting options (http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo(VS.85).aspx). Try this line:
write-host ("File Name: " + $file.Name, ", Pending Since : " + $(get-date $file.CreationTime -format "dddd, MMMM d, yyy h:mm tt")) -Fore Red
The main bit here is replacing $file.CreationTime with $(get-date $file.CreationTime -format "dddd, MMMM d, yyy h:mm tt"). That is a fairly standard date/time format with 12 hour formatting. You could get more detailed if you wanted and define the format earlier and only put out relevant info (such as, if days = 0 exclude that from the date format).

Related

How to do time "HH:mm" comparison in Powershell?

Apparently my code is like this and it is now working. I think the logic is already there. the $openTime and $closeTime is read from csv using import-csv in "HH:mm" form.
$openTime = $ip.openTime
$closeTime = $ip.closeTime
$time = Get-Date -UFormat "%R"
if (($time -ge $openTime) -and ($time -le $closeTime)) {
Write-Host "Store is Open!" -ForegroundColor Green
}else{
Write-Host "Store is outside open hours!" -ForegroundColor Red
}
powershell 7
$csv = #"
store, openTime, closeTime
Wallmart, 08:00, 18:00
Ikea, 10:00, 20:30
"# | ConvertFrom-Csv
Get-Date
$csv | ForEach-Object{
[int]([datetime]::Now - [datetime]::Today).TotalMinutes -in (.{[int]$args[0][0]*60 + [int]$args[0][1]} $_.openTime.split(":"))..(.{[int]$args[0][0]*60 + [int]$args[0][1]} $_.closeTime.split(":")) ? "Store {0} is Open! " -f $_.store : "Store {0} is outside open hours!" -f $_.store
}
16 февраля 2021 г. 8:52:42
Store Wallmart is Open!
Store Ikea is outside open hours!
powershell 5
$csv = #"
store, openTime, closeTime
Wallmart, 08:00, 18:00
Ikea, 10:00, 20:30
"# | ConvertFrom-Csv
Get-Date
$csv | ForEach-Object{
("Store {0} is outside open hours!", "Store {0} is Open! ")[[int]([datetime]::Now - [datetime]::Today).TotalMinutes -in (.{[int]$args[0][0]*60 + [int]$args[0][1]} $_.openTime.split(":"))..(.{[int]$args[0][0]*60 + [int]$args[0][1]} $_.closeTime.split(":"))] -f $_.store
}
Try it online!
I find it's much easier to work with date and times if I convert them to [DateTime] objects. We can use the DateTime class method ParseExact to convert the time into [DateTime] objects for us. This object will actually contain today's date as well as the time we supply, but for our purposes this is fine since the $time object also will be today's date. For the current time ($time) just let Get-Date return to us a [DateTime] object that will represent the current date and time (now). After that the rest of your code works as expected. Hurray!
# this $ip hashtable object just represents data similar to your csv import
$ip = #{
openTime = "09:00"
closeTime = "21:00"
}
$openTime = [datetime]::ParseExact($ip.openTime, 'HH:mm', $null)
$closeTime = [datetime]::ParseExact($ip.closeTime, 'HH:mm', $null)
$time = Get-Date
if (($time -ge $openTime) -and ($time -le $closeTime)) {
Write-Host "Store is Open!" -ForegroundColor Green
}
else {
Write-Host "Store is outside open hours!" -ForegroundColor Red
}
If you are working with the time are imported from csv, make sure the time format in the csv file is in "HH:mm"

PowerShell Downloading Files from a List with the latest Date

I'm new to using PowerShell and Scripting Overall but i tried to solve my Problem for a few Days now and even with researching stackoverflow and the Web i can't find a solution.
I try to write a script to Download a fixed amount of files (.jdb, .exe) from a Website.
One Part of the filename is Always the same ex: -061-IPS_IU_SEP_14RU1.jdb
But the full filename is 20201120-061-IPS_IU_SEP_14RU1.jdb
The first part is the date where the files have been created.
So far i was able to download all the files using following Code:
$filename = #(
"-061-IPS_IU_SEP_14_0.exe",
"-061-IPS_IU_SEP_14_0.jdb",
"-061-IPS_IU_SEP_14_0_MP2.exe",
"-061-IPS_IU_SEP_14_0_MP2.jdb",
"-061-IPS_IU_SEP_14RU1.exe",
"-061-IPS_IU_SEP_14RU1.jdb",
"-061-IPS_IU_SEP_14.2_RU1.exe",
"-061-IPS_IU_SEP_14.2_RU1.jdb",
"-061-IPS_IU_SEP_14.2_RU2.exe",
"-061-IPS_IU_SEP_14.2_RU2.jdb"
)
# Zielverzeichnis
$output = "C:\IPS14\"
$url = "http://definitions.symantec.com/defs/ips/"
$Date = Get-Date -format yyyyMMdd ((Get-Date).AddDays(0))
$fullurl = ("$url" + $Date + $filename[0])
for ($i=0; $i -lt $filename.Length; $i++){
$fullurl = ("$url" + ($Date-1) + $filename[$i])
Try{
Start-BitsTransfer -Source $fullurl -Destination $Output
Write-Host ("$url" + $Date + $filename[$i] + " Downloading")
}
Catch{}
The current Problem is that some Files are not updated daily. Some are from 1 Day ago others are 3 or more Days old.
I only need the latest updated files.
Well because Downloading the files weren't my Problem i tried something like
$IPSindex = 'https://definitions.symantec.com/defs/download/symantec_enterprise/ips/index.html'
(Invoke-WebRequest –Uri $IPSindex).Links | Sort-Object href -Unique | Format-List innerText, href
to list all files on the Page. But now i need to filter the latest href using the $filename Array.
Acutally I'm stuck. Hope you can help me.
Greetings
I have modified your snippet to extract the date part of the filename and converting it into a datetime array.Sorting the datetime array to fetch recent update.
$IPSindex = 'https://definitions.symantec.com/defs/download/symantec_enterprise/ips/index.html'
$links = ((Invoke-WebRequest –Uri $IPSindex).Links).href
$dates =#()
foreach ($link in $links){
if($link -like "*IPS*"){
$dates += $link.split("/")[-1].split("-")[0]
}
}
$dates = $dates |Get-Unique | foreach {[datetime]::ParseExact($_,"yyyyMMdd",$null)} | Sort-Object -Descending
Write-Output "The latest available definition date: $($dates[0])"

How can I append data in powershell to a different file depending on what month the data came from?

I am pulling data on adoption of Office 365 products on a daily basis. I don't know how to convert my current logic to write to a new file based on file size to one based on the report date.
My original thought process was to use an if statement to split the data out by month and have 12 files already ready to append to (depending on the month of data) but this seems inefficient.
$name = "O365SPSiteActivity.csv"
$auth=Get-AuthCode
$accesstoken=$auth[1]
### data pulling process has been omitted ###
if ($report -ne $null)
{
###New section for making the new files
#Get current file
$source = "D:\O365Data\"+ $name
$File = Get-Item $source
If (((Get-Item $file).Length/1MB) -ge 700)
{
$date = (get-date -Format dd-MM-yyyy)
$RenamedFileName = "O365SPSiteActivity-$date.csv"
Rename-Item $file.FullName -NewName $RenamedFileName
$FileName = "D:\temp\" + $name
Send-MailMessage –From svc_sps10#kbslp.com –To shelby.cundiff#kbslp.com –Subject “New File Has been Created" –Body “New File Name: $RenamedFileName " -SmtpServer kbslp-com.mail.protection.outlook.com -Port 25
}
Else
{
$FileName = "D:\temp\" + $name
Copy $File $FileName
}
#########################################################################
$Data=#()
$c=1
foreach ($row in $report)
{ Write-Progress -Activity $row.'User Principal Name' -PercentComplete (($c/$report.count)*100) -ID 4
$string = "" | Select "???Report Refresh Date","User Principal Name","Is Deleted","Deleted Date","Last Activity Date","Viewed or Edited File Count",
"Synced File Count","Shared Internally File Count","Shared Externally File Count","Visited Page Count","Report Period"
$string.'???Report Refresh Date' = Get-Date($row.'Report Refresh Date') -Format "yyyy-MM-dd"
$string.'User Principal Name' = $row.'User Principal Name'
$string.'Is Deleted' = $row.'Is Deleted'
$string.'Deleted Date' = $row.'Deleted Date'
$string.'Last Activity Date' = $row.'Last Activity Date'
$string.'Viewed or Edited File Count' = $row.'Viewed or Edited File Count'
$string.'Synced File Count' = $row.'Synced File Count'
$string.'Shared Internally File Count' = $row.'Shared Internally File Count'
$string.'Shared Externally File Count' = $row.'Shared Externally File Count'
$string.'Visited Page Count' = $row.'Visited Page Count'
$string.'Report Period' = $row.'Report Period'
$Data += $string
$c++
}
$Data | Export-Csv -Append -Path $FileName -NoTypeInformation -Force
#$FolderUrl = $teamSitePath + "/" + $ListName
#$UploadFileInfo = New-Object System.IO.FileInfo($FileName)
#Upload-SPOFile -WebUrl $teamSiteUrl -spCredentials $SPOCreds -FolderUrl $FolderUrl -FileInfo $UploadFileInfo
$newFile = Get-Item $FileName
Copy $newFile $File.FullName
}
$report = $null
$Data = $null
Ideally, i'd like to change this script to write to a file like:
O365SPSiteActivity-2019-Oct.csv during October, then O365SPSiteActivity-2019-Nov.csv during November, etc. depending on when the data is from.
Why would you write to a temporary file first and copy if over a (possibly existing) file when done?
If I understand the question, you would like to create a new report csv each month.
Then, why not simply do something like this:
# create a filename for this month
$currentReport = 'O365SPSiteActivity-{0:yyyy-MMM}.csv' -f (Get-Date)
and export -Append your data into that? If the file does not already exist, it will be created, otherwise the new data will be appended to it.
Are you looking for the current date, or the date from the spreadsheet?
$date = (get-date -Format dd-MM-yyyy)
will output to O365SPSiteActivity-2019-Oct.csv if you run it today.
If you're looking to chunk up the CSV based on dates within the data, I might move the export-CSV inside the foreach loop, and modify it to use a name similar to above instead of appending it to the $Data array.
$Data = "2019-May-31"
Get-Date -Format yyyy-MMM -Date ([datetime]::parseexact($Data, 'yyyy-MMM-dd', $null))
$FileName = "O365SPSiteActivity-$date.csv"
$Data | Export-Csv -Append -Path $FileName -NoTypeInformation -Force
That'll write each line to the appropriate CSV file- you'll end up with a different CSV file for every months worth of data.
Note that the 'yyyy-MMM-dd' in parseexact will need to match the format of the date that you're feeding it. For example, if you're sorting it based on $row.'Report Period' that has the date as 12/31/19, it would be 'MM/dd/yy' instead (notice I changed from - to / as the separator). Here's the documentation listing what each letter in that means.

Best Practice - If match return result

Use Case
The below script is to be placed in a scheduled task to notify me if my public IP Address changes
The IF match condition is not the correct behaviour
What would be the best way to match if the IP Address changed and output that to host?
Code
$ip = Invoke-RestMethod http://ipinfo.io/json | select -ExpandProperty ip
$date = (get-date).date
$value = "{0} - {1}" -f ($date),($ip)
Add-Content -Value $value -Path "C:\users\Sumeet\Documents\WindowsPowerShell\ip.txt"
$file = Get-Content -Path "C:\users\Sumeet\Documents\WindowsPowerShell\ip.txt"
if ($file | Select-String -Pattern $ip) {
clear-host
write-host "Match found at $_ your public IP interface has changed"
}
File Output
Date - IP
9/06/2018 12:00:00 AM - 121.211.177.20
9/06/2018 12:00:00 AM - 121.211.177.20
Output
I think something similar would be more helpful, as #LotPings suggested. You should update the file only if there is a change and follow up with notification as needed.
Also note, that change of IP can occur at anytime, but your scheduled task will let you know only whenever it is scheduled to run.
$ip = Invoke-RestMethod http://ipinfo.io/json | select -ExpandProperty ip
$date = (get-date).date
$value = "{0} - {1}" -f ($date),($ip)
$file = Get-Content -Path "E:\Code\powershell\myPS\2018\Jun\checkPublicIP\ip.txt"
if ($file | Select-String -Pattern $ip) {
Write-Host "IP is not changed"
}
else {
#Adding current IP to the file
Add-Content -Value $value -Path "E:\Code\powershell\myPS\2018\Jun\checkPublicIP\ip.txt"
#Add more code as needed for notification / email / alert.
}
Handling of data is IMO done easier when using csv files as columns/properties are assigned on import.
Because of my locale which doesn't support the date separator / or tt for AM/PM I had to use a CultureInfo object.
## Q:\Test\2018\06\09\SO_50771712.ps1
$File = "$Env:USERPROFILE\Documents\WindowsPowerShell\ip.csv"
$CIUS = New-Object System.Globalization.CultureInfo("en-US")
$Actual = [PSCustomObject]#{
Date = (get-date).ToString("d/M/yyyy hh:mm:ss tt",$CIUS)
IP = (Invoke-RestMethod http://ipinfo.io/json).ip
}
if (!(Test-Path $File)){'"Date","IP"'|Set-Content $File}
$Last=Import-Csv $File|Sort-Object {[DateTime]$_.Date}|Select-Object -Last 1
If ($Last.ip -ne $Actual.ip){
Write-Host ("Last ip : {0} from: {1}" -f $LAst.IP,$Last.date)
Write-Host ("New ip : {0} from: {1}" -f $Actual.IP,$Actual.date)
Export-Csv $File -InputObject $Actual -Append -NoTypeInformation
}
Sample output:
> Q:\Test\2018\06\09\SO_50771712.ps1
Last ip : 92.123.13.83 from: 9/6/2018 09:19:21 PM
New ip : 92.123.13.84 from: 9/6/2018 09:34:59 PM
> gc $file
"Date","IP"
"9/6/2018 08:51:00 PM","92.123.13.82"
"9/6/2018 09:19:21 PM","92.123.13.83"
"9/6/2018 09:34:59 PM","92.123.13.84"

Compare current date to date string in a file using powershell

I am writing some PS scripts to log times into a text file, login.txt, using the following code:
$logdir = "C:\FOLDER"
$logfile = "$logdir\LastLogin.txt"
$user = $env:USERNAME
$date = Get-Date -Format "dd-MM-yyyy"
if (!(Test-Path $logdir)){New-Item -ItemType Directory $logdir}else{}
if (!(Test-Path $logfile)){New-Item $logfile}else{}
if (Get-Content $logfile | Select-String $user -Quiet){write-host "exists"}else{"$user - $date" | Add-Content -path $logfile}
(Get-Content $logfile) | Foreach-Object {$_ -replace "$user.+$", "$user - $date"; } | Set-Content $logfile
This creates an entry in the text file like:
UserName - 01-01-1999
Using Powershell, I want to read the text file, compare the date, 01-01-1999, in the text file to the current date and if more than 30 days difference, extract the UserName to a variable to be used later in the script.
I would really appreciate any hints as to how I could do the following:
Compare the date in the text file to the current date.
If difference is more than 30 days, pick up UserName as a variable.
I would really appreciate any advice.
Checking all dates in the file with the help of a RegEx with named capture groups.
$logdir = "C:\FOLDER"
$logfile = Join-Path $logdir "LastLogin.txt"
$Days = -30
$Expires = (Get-Date).AddDays($Days)
Get-Content $logfile | ForEach-Object {
if ($_ -match "(?<User>[^ ]+) - (?<LastLogin>[0-9\-]+)") {
$LastLogin = [datetime]::ParseExact($Matches.LastLogin,"dd-MM-yyyy",$Null)
if ( $Expires -gt $LastLogin ) {
"{0} last login {1} is {2:0} days ago" -F $Matches.User, $Matches.LastLogin,
(New-TimeSpan -Start $LastLogin -End (Get-Date) ).TotalDays
}
}
}
Sample output
username last login 31-12-1999 is 6690 days ago
There is a way of doing that using regex (Regular Expressions). I will assume that the username which you get in your text file is .(dot) separated. For example, username looks like john.doe or jason.smith etc. And the entry in your text file looks like john.doe - 01-01-1999 or jason.smith - 02-02-1999. Keeping these things in mind our approach would be -
Using a regex we would get the username and date entry into a single variable.
Next up, we will split the pattern we have got in step 1 into two parts i.e. the username part and the date part.
Next we take the date part and if the difference is more than 30 days, we would take the other part (username) and store it in a variable.
So the code would look something like this -
$arr = #() #defining an array to store the username with date
$pattern = "[a-z]*[.][a-z]*\s[-]\s[\d]{2}[-][\d]{2}[-][\d]{4}" #Regex pattern to match entires like "john.doe - 01-01-1999"
Get-Content $logfile | Foreach {if ([Regex]::IsMatch($_, $pattern)) {
$arr += [Regex]::Match($_, $pattern)
}
}
$arr | Foreach {$_.Value} #Storing the matched pattern in $arr
$UserNamewithDate = $arr.value -split ('\s[-]\s') #step 2 - Storing the username and date into a variable.
$array = #() #Defining the array that would store the final usernames based on the time difference.
for($i = 1; $i -lt $UserNamewithDate.Length;)
{
$datepart = [Datetime]$UserNamewithDate[$i] #Casting the date part to [datetime] format
$CurrentDate = Get-Date
$diff = $CurrentDate - $datepart
if ($diff.Days -gt 30)
{
$array += $UserNamewithDate[$i -1] #If the difference between current date and the date received from the log is greater than 30 days, then store the corresponding username in $array
}
$i = $i + 2
}
Now you can access the usernames like $array[0], $array[1] and so on. Hope that helps!
NOTE - The regex pattern will change as per the format your usernames are defined. Here is a regex library which might turn out to be helpful.