Export Eventlogs and send email - powershell

I have written a script to export specific Eventvwr logs based on Source and the script is working as expected, but i am trying to cut short the message form the Eventvwr, i dont to print entire message on the mail.
I am attaching the output of my code below
#
# This script exports consolidated and filtered event logs to CSV
#
#Application error and critical eventlogs for specific EventID:
#Email Details
$FromAddress = 'abc.com'
$ToAddress = '123.com'
$SmtpServer = 'xyz.com'
Set-Variable -Name EventAgeDays -Value 4 #we will take events for the latest 7 days
Set-Variable -Name CompArr -Value #("abcedf.com") # replace it with your server names
Set-Variable -Name LogNames -Value #("Application") # Checking app and system logs
Set-Variable -Name EventTypes -Value #("Information") # Loading only Errors and Warnings
Set-Variable -Name ExportFolder -Value "C:\xxx\"
Set-Variable -Name Source -Value #("123", "111")
$el_c = #() #consolidated error log
$now=get-date
$startdate=$now.adddays(-$EventAgeDays)
$ExportFile=$ExportFolder + "Out" + $now.ToString("yyyy-MM-dd---hh-mm-ss") + ".csv" # we cannot use standard delimiteds like ":"
foreach($comp in $CompArr)
{
foreach($log in $LogNames)
{
foreach ($src in $Source)
{
Write-Host Processing $comp\$log
$el = get-eventlog -ComputerName $comp -log $log -After $startdate -EntryType $EventTypes -Source $src -Newest 1 -InstanceId 30000
$el_c += $el #consolidating
#}
#}
$el_sorted = $el_c | Sort-Object TimeGenerated #sort by time
Write-Host Exporting to $ExportFile
}
}
}
$out = $el_sorted|Select MachineName, EntryType, TimeGenerated, Source, EventID, Message #| Export-CSV $ExportFile -NoTypeInfo #EXPORT
Write-Host Done!
$msgBody = $out
Send-MailMessage -from $FromAddress -to $ToAddress -SmtpServer $SmtpServer -Subject "TL Stage Ingester Status from $CompArr $startdate" -Body ( $msgBody | Out-String)

Related

Export windows logs to csv each 1 hour

I really need your help, I already make a script for export logs to csv file:
Set-Variable -Name EventAgeDays -Value 1
Set-Variable -Name CompArr -Value #("Localhost")
Set-Variable -Name LogNames -Value #("Security", "Application", "System")
Set-Variable -Name EventTypes -Value #("Information", "Error", "Warning", "FailureAudit", "SuccessAudit")
Set-Variable -Name ExportFolder -Value "C:\"
$el_c = #()
$now = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId($(Get-Date), [System.TimeZoneInfo]::Local.Id, 'GMT Standard Time')
$startdate=$now.adddays(-$EventAgeDays)
$ExportFile=$ExportFolder + "mx_sugus_poc_" + $now.ToString("yyyy.MM.dd_hh.mm") + ".csv"
foreach($comp in $CompArr)
{
foreach($log in $LogNames)
{
Write-Host Processing $comp\$log
$el = get-eventlog -ComputerName $comp -log $log -After $startdate -EntryType $EventTypes -Message "*"
$el_c += $el
}
}
$el_sorted = $el_c | Sort-Object TimeGenerated
Write-Host Exporting to $ExportFile
$el_sorted|Select TimeGenerated, EntryType, Source, EventID, MachineName, UserName, Message | export-CSV $ExportFile -NoTypeInfo
Additional I change the date for a GMT format.
I want to change the search in my logs instead of every day for every hour.
Can you help me with this ???
Thanks so much !!!
Change $startdate=$now.adddays(-$EventAgeDays) to $startdate=$now.addHours(-1)

How to read input through a csv file and write the output in an output file in power shell script?

[This is the powershell script to get the selected services status of servers,where list of servers are given through input csv file and the status of those server should be stored in an output file.
-----------Below is the script----------
$Servers = Get-Content "C:\temp\input.csv"
$Log = #()
foreach($Server in $Servers)
{
$Services = Get-Service *HRRA*, "SQL Server Reporting Services" -ComputerName $COMPUTERNAME
foreach ($Service in $Services)
{
$properties = #(
#{n='ServiceName';e={$Service.Name}}
#{n='Status';e={$Service.Status}}
#{n='ServerName';e={$Server}}
)
$Log += "" | select $properties
}
}
$Log | Format-Table -AutoSize | Out-File "D:\temp\test.txt" -Force
------------------------------------New Script----------------------------------
$Computers = Import-Csv "C:\Temp\Input.csv"
#$mailboxdata = Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName $ComputerName| select machinename,name, status | sort machinename |
#format-table -AutoSize |Out-File "D:\Temp\RRR.txt"
#LogWrite "$ComputerName"
foreach($row in $computers)
{
{
Add-Content -Path D:\Temp\SSRS.txt -Value $mailboxdata }
Get-Content -Path D:\Temp\SSRS.txt
$ComputerName= $row.ComputerName;
$mailboxdata = Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName $ComputerName| select machinename,name, status | sort machinename |
format-table -AutoSize |Out-File "D:\Temp\SSR.txt"
$fromaddress = "Reporting.Services#accenture.com"
$toaddress = "aditi.m.singh#accenture.Com"
#$toaddress1 = "s.ab.balakrishnan#accenture.com"
$Subject = "SSRS Services Status"
$body = "Please find attached - test"
$attachment = "D:\Temp\SSR.txt"
$smtpserver = "AMRINT.SMTP.ACCENTURE.COM"
$message = new-object System.Net.Mail.MailMessage
$message.From = $fromaddress
$message.To.Add($toaddress)
#$message.To.Add($toaddress1)
$message.IsBodyHtml = $True
$message.Subject = $Subject
$attach = new-object Net.Mail.Attachment($attachment)
$message.Attachments.Add($attach)
$message.body = $body
$smtp = new-object Net.Mail.SmtpClient($smtpserver)
$smtp.Send($message)
}
If i am running the script with static value its giving me output for both the servers---Below is the script----
Get-Service *HRRA*,"SQL Server Reporting Services" -ComputerName VW118627, VW118623 | select name, status, machinename | sort machinename | format-table -AutoSize |
Out-File "D:\Temp\Report.txt"
Looking at the screenshot, I can see the input csv is really a Comma Separated Values file. For these, you use the Import-Csv cmdlet to retrieve an array of computer names from the file.
$outputFile = "D:\temp\test.csv"
# make sure the field name matches what is in the CSV header
$Servers = (Import-Csv -Path "C:\temp\input.csv").ComputerName
$Log = foreach($Server in $Servers) {
# add a test to see if we can reach the server
if (Test-Connection -ComputerName $Server -Count 1 -Quiet -ErrorAction SilentlyContinue) {
Get-Service -Name *HRRA*, "SQL Server Reporting Services" -ComputerName $Server |
Select-Object #{Name = 'MachineName'; Expression = {$Server}},
#{Name = 'ServiceName'; Expression = {$_.Name}},
#{Name = 'Status'; Expression = {$_.Status}}
}
else {
Write-Warning "Server '$Server' is unreachable"
}
}
# if you want the log sorted, do
$Log = $Log | Sort-Object MachineName
# output on screen
$Log | Format-Table -AutoSize
# output to CSV file
$Log | Export-Csv -Path $outputFile -Force -NoTypeInformation
# mail the output csv file using Send-MailMessage
# collect the parameters in a hashtable
$mailParams = #{
SmtpServer = "AMRINT.SMTP.ACCENTURE.COM"
From = "Reporting.Services#accenture.com"
To = "aditi.m.singh#accenture.com"
Subject = "SSRS Services Status"
Body = "Please find attached - test"
BodyAsHtml = $true
Attachments = $outputFile
# add other parameters if needed
# see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/send-mailmessage
}
# use 'splatting' to send the email
# see https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_splatting
Send-MailMessage #mailParams
P.S. The Format-Table cmdlet is for displaying the object(s) on screen only.

Print Timestamp of Stop and Start Services into .txt file

I want timestamp when services is stopped/restarted then output to file. The file will become as attached and send to support.
I cannot output to file as my below query seems got error.
$hostname = $env:computername
$smtpServer = 'smtpServer'
$from = "from"
$recipients = 'recipients'
$Subject = "Services Restarted Successfully on $hostname $ipv4"
$body = "This mail confirms that the service on $hostname $ipv4 is now running."
$ipv4 = (Test-Connection -ComputerName $env:computername -count 1).ipv4address.IPAddressToString
$natip = Invoke-WebRequest ifconfig.me
$timestamp = (Get-Date)
$output = D:\Testing\Restart.txt
$attachment = $output
$service = 'Apache'
Stop service
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is stopped" | Out-file $output
}
until ((get-service $service).Status -eq 'Stopped')
Start service
start-Service -name $service -Verbose
do {
Start-sleep -s 5 | Write-Output "$timestamp Services is restarted" | Out-file $output
}
until ((get-service $service).Status -eq 'Running')
Send confirmation that service has restarted successfully
Start-Sleep -s 5
Send-MailMessage -To $recipients -Subject $Subject -Body $body ((gsv Apache) | out-string) -From $from -SmtpServer $smtpServer -Attachments $attachment
As stated in above comments, change your code to
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5
Write-Output "$timestamp Services is stopped" | Out-file $output
} until ((get-service $service).Status -eq 'Stopped')
Actually your Start-Sleep cmledt calls output is sent to the pipeline ( Start-sleep - s 5 |...). My guess is that Start-sleep doesn't returns anything, so nothing is send to the pipeline. Based on that Write-Output is not called.
Antoher guess: Assignment to $output fails since your path is not a string, Powershell may interpret the assignment in command mode. Change it to:
$output = "D:\Testing\Restart.txt"

Powershell Event Log Reporting

I'm working on a PS script to collect on certain Event IDs and spit them back every hour or so. I'm doing this because I want to spit it out to email for ease of reading.
My problem right now is that the script will run up to a certain point and hang. If I remove the date filters, it runs well. As soon as I re-add them (either through variables or hard-coded) it does it's hanging thing again. I need the date filters, however, because otherwise I'm getting everything when I'm looking for hourly chunks.
Looking for advice as I'd like to use variables for the one-offs or modifications! I'd also like to use spinoffs for other side reporting as well.
$filedate = (get-date).ToString("MM_dd_yy-hh_mm")
$filename = "bad_logins_DC01 " + $filedate + "_log.txt"
$after = (get-date).addhours(-1)
$before = (get-date)
$eventlog = Get-EventLog -ComputerName DC01 -LogName Security -After $after -Before $before
$eventlog | ?{$_.EventID -eq 4771 -or $_.EventID -eq 4776 } | Select #{Name="Event ID";Expression={$_.InstanceID}},#{Name="UserName";Expression={$_.ReplacementStrings[0]}},#{Name="Failure Code";Expression={$_.ReplacementStrings[4]}},#{Name="Host";Expression={$_.ReplacementStrings[6]}},#{Name="Port";Expression={$_.ReplacementStrings[7]}}, #{Name="Time";Expression={$_.TimeGenerated}} | ft | Out-File $filename -append -noclobber
$to = itsupport#ourdomain.com
$from = itsupport#ourdomain.com
$subject = $filename
$smtp = exchange.ourdomain.com
$contents = cat $filename
$body = $contents
Send-MailMessage -SmtpServer $smtp -To $to -From $from -Subject $subject -Body $body -Attachments $filename
Got it!
Big thanks to TheMadTechnicial for the assist on Get-WinEvent instead of Get-EventLog
$query_sec = #"
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*`
[System[Provider[#Name='Microsoft-Windows-Security-Auditing'] and `
TimeCreated[timediff(#SystemTime) <= 7200000] and `
(EventID=4771 or EventID=4776)]]</Select>
</Query>
</QueryList>
"#
$time = (Get-Date).ToString("dd-MM_hh-mm")
$to = "itsupport#mydomain.com"
$from = "me#mydomain.com"
$smtpServer = "mxserver.mydomain.com"
Try
{
$domain_controller = "DC01","C02","DC03"
ForEach ($dc in $domain_controller)
{
$Events = Get-WinEvent -ComputerName $dc -FilterXml $query_sec -ErrorAction Stop
ForEach ($event in $Events)
{
$eventXML = [xml]$Event.ToXml()
For ($i=0; $i -lt $eventXML.Event.EventData.Data.Count; $i++)
{
Add-Member -InputObject $Event -MemberType NoteProperty -Force `
-Name $eventXML.Event.EventData.Data[$i].Name `
-Value $eventXML.Event.EventData.Data[$i].'#text'
}
}
$filename = "C:\temp\"+$dc+"_failed_logins_"+$time+".txt"
$Events | Select-Object #{Name="UID";Expression={$_.TargetUserName}},`
ServiceName,`
#{Name="Error";Expression={$_.Status}},`
#{Name="IP";Expression={$_.IpAddress}},`
#{Name="Port";Expression={$_.IpPort}},`
#{Name="Event ID";Expression={$_.ID}},`
#{Name="Source";Expression={$_.MachineName}}`
| FT `
| Out-File $filename
$subject = "Bad Logins on " + $dc + " at " + $time
$body = Get-Content -Path $filename -Raw
Send-MailMessage -To $to -Subject $subject -From $from -SmtpServer $smtpServer -Body $body
}
}
Catch [Exception]
{
Write-Output " "
Write-Output "$dc has no relevant event logs!"
}

App_Pool_Alert Powershell Script

I have written a power shell script which is used to monitor the status of IIS app pools. With current method whenever any pool goes down it throws me an alert that pool is stopped and after that it starts the pool again send email stating that pool is up. Since i have around 50 servers so number of mails are coming in bulk which causes spam sometimes. Could some one help me here so that script will scan the pool directory and place the result in a text/html file and send me the list that these pools are down in mail. Please find script below:-
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\Users\Desktop\server.txt
################ Scans each server and import IIS web-administration module##################################
$Servers | ForEach-Object {
Invoke-Command -ComputerName $_ -ScriptBlock {
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Down on $CompName " -Body "$ApplicationPoolName is down. Please check IIS/Event logs for RCA." -SmtpServer ###########
Start-WebAppPool -Name $ApplicationPoolName
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool:- $ApplicationPoolName is Up on $CompName " -Body "$ApplicationPoolName is Up and running fine." -SmtpServer #############
}
}
}}
##################################### End of Script ##########################################################
This is how I would rewrite the script:
###################################Declear Servers in text file##############################################
$Servers = Get-Content C:\server.txt
################ Scans each server and import IIS web-administration module##################################
$SMPTServer = "mail.server.com"
$result = "The following application pools were restarted:`n`n" # default output
$Servers | ForEach-Object {
$result += Invoke-Command -ComputerName $_ -ScriptBlock { # add output of scriptblock to $result
Import-Module WebAdministration
cd IIS:/AppPools
$CompName = (Get-WmiObject -Class Win32_ComputerSystem).Name
$ApplicationPools = dir
foreach ($item in $ApplicationPools)
{
$ApplicationPoolName = $item.Name
$ApplicationPoolStatus = Get-WebAppPoolState $ApplicationPoolName
If($ApplicationPoolStatus.value -eq "Stopped")
{
Write-Output "Server $CompName - Application pool $ApplicationPoolName is Down - Restarting`n" # any action is added to otput
Start-WebAppPool -Name $ApplicationPoolName
}
}
}
}
if ($result -ne "The following application pools were restarted:`n`n") { # If any action was taken send mail with $result
send-mailmessage -to "vvv#gmail.com" -from "xxx#gmail.com" -subject "Application Pool Maitenance" -Body $result -SmtpServer $SMPTServer
}
##################################### End of Script ##########################################################
First define a $result variable, in this case just a string.
Withing your scriptblock, you can write anything to piped output using Write-Output. This output is returned from Ivoke-Command and added to the $result variable.
At the end of your script check if $result variable has changed and send it as a body of an email if required.