I am new to powershell and I am trying to write a script that will email me whenever someone moves or deletes a file or folder from a shared drive. I already set up the task scheduler to execute the script when one of those events happen. The problem that I have is that I execute script from the shell it provides me with all the information regarding the last entry in the event logs. However, when it runs from the task scheduler it does not execute. I believe that it has to do with the body line. Any suggestions or insights will be greatly appreciated.
This is my code:
$events = Get-EventLog -Logname Security -Newest 1
$From = $env:COMPUTERNAME + "#company.com"
$To = "me#company.com"
$Subject = $env:COMPUTERNAME + " " + $env:UserName + " " + $_.eventID
$Body = $events | format-list -property * | out-string
$SMTPServer = "exch"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SMTPServer $SMTPServer
Related
I would like to ask for help if there is a way to send an e-mail notification when a scheduled ms access macro in task scheduler is in "Running" state for more than 20 minutes?
First thing that comes to mind is writing a second scheduled tasks to poll the runtime of the MS Access macro task.
If the task is over 20 minutes send out an email.
Another option might be to start a background job (Start-Job) in the MS Access code that will send the email after 20 minutes. And in your code, if the MS Access job succeeds you can cancel (Stop-Job) the email background task.
(There are many ways to skin a cat so just finding the best solution for the problem really)
Finally got it using powershell.
$ScheduledTaskName = "full path of your scheduled task e.g Folder1\Folder2\taskname"
$Result = (schtasks /query /FO LIST /V /TN $ScheduledTaskName | findstr "Result")
$Result = $Result.substring(12)
$Code = $Result.trim()
If ($Code -gt 0) {
$From = "MacroFails#DoNotReply.com"
$To = "Admin#Domain.com"
$Subject = "Scheduled task 'AppendCreatedSO' failed on SERVER"
$Body = "Error code: $Code"
$SMTPServer = "your SMTP Server"
$SMTPPort = "SMTP erver port"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -BodyAsHtml -SmtpServer $SMTPServer -Port $SMTPPort #-UseSsl -Credential (Get-Credential) #-Attachments $Attachment
}
We (our company) are runnning several scheduled tasks on a server. Recently some of the tasks started to fail on running. We'd like to query all the scheduled jobs reporting anyone whose last run result isn't 0x0 using powershell.
I've tried a lot of research for finding an easy way to do so, but only found scripts, that can query scheduled task by name (only to check one single task) but not by last run result. It wouldn't be helpful to add a new codeline for every newly intstalled scheduled task.
There is a quite similar entry on that topic, but as described above with the task name as parameter. (How to send email when SPECIFIC scheduled task fails to run)
$ScheduledTaskName = "Taskname"
$Result = (schtasks /query /FO LIST /V /TN $ScheduledTaskName | findstr "Result")
$Result = $Result.substring(12)
$Code = $Result.trim()
If ($Code -gt 0) {
$User = "admin#company.com"
$Pass = ConvertTo-SecureString -String "myPassword" -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential $User, $Pass
$From = "Alert Scheduled Task <task#servername>"
$To = "Admin <admin#company.com>"
$Subject = "Scheduled task 'Taskname' failed on SRV-001"
$Body = "Error code: $Code"
$SMTPServer = "smtp.company.com"
$SMTPPort = "25"
Send-MailMessage -From $From -to $To -Subject $Subject `
-Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl `
-Credential $Cred
}
The code should be something like that, I guess
Get-ScheduledTask | where LastTaskResult -NE "0x0"
Use Get-ScheduledTaskInfo.
Get-ScheduledTask -TaskPath "\" | Where State -ne "Disabled" | Get-ScheduledTaskInfo | Where LastTaskResult -ne 0
In my example, I've just assumed you want tasks in the Task root, not any in the MS subfolders. If you store or care about tasks in the subfolders, then obviously modify the taskpath or identify the tasks you want some other way.
Get-ScheduledTaskInfo returns a bunch of properties that you can search/select. Excluding the Cim (WMI) properties, they are:
TaskName,TaskPath,LastRunTime,LastTaskResult,NextRunTime,NumberofMissedRuns
I tried several Scripts to email the status of HDD or RAM but its not working,
1st Time using PowerShell.
Windows Server 2012 R2
Script would get triggered by the event (when the Memory is low) and send the email with the details.
to get the Disk Stats i used
Get-EventLog -LogName System | Where-Object {$_.EventID -eq 2013}
How can i add this event to the email and make it appear in the message, i tried giving it a name like
$event Get-EventLog -LogName System | Where-Object {$_.EventID -eq 2013}
but i don't know how to add it to the message body its not like java or
$message.body = $body + $event
to send email this script works,
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
$Username = "username#gmail.com"
$Password = "zxc"
$to = "help#x.com"
$cc = "help#x.ae"
$subject = "Low Disk Space"
$body = "The Server Disk is Low on memory"
$message = New-Object System.Net.Mail.MailMessage
$message.Subject = $subject
$message.Body = $body
$message.To.add($to)
$message.Cc.add($cc)
$message.From = $username
$smtp = New-Object System.Net.Mail.SmtpClient($SMTPServer, $SMTPPort);
$smtp.EnableSSL = $true
$smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
$smtp.Send($message)
Write-Host "Mail Sent"
I read that the email alerts were discontinued by MS but people still have ways of doing it, unfortunately I didn't get it to work.
Something to help you get started on this:
# We first need to know which command to use
Get-Command '*mail*'
# We use the splatting technique to provide the parameters
$Params = #{
SmtpServer = 'smtp.gmail.com'
Port = '587'
From = $username
To = 'help#x.com'
Cc = 'help#x.ae'
Subject = 'Low Disk Space'
Body = 'The Server Disk is Low on memory.'
}
# Get-Help explains what this CmdLet does
Get-Help Send-MailMessage
# Get-Help can also give you examples on how to use the CmdLet
Get-Help Send-MailMessage -Examples
# Retrieve only events of the last 24 hours and select the first one
$Today = Get-Date
$Past = $Today.AddDays(-1)
$Event = Get-EventLog -LogName System -After $Past | Where-Object {$_.EventID -eq 6013} | Select-Object -First 1
# Add the event to the mail body
$Params.Body += ' ' + $Event.Message
# Send the mail
Send-MailMessage #Params
This script can then be added to the Task-Scheduler to run once a day.
SCHTASKS /Create /RU "SYSTEM" /SC DAILY /ST 17:30 /TN DailyHDDMemReport /TR "powershell -NoProfile -NoLogo -ExecutionPolicy Unrestricted -File 'C:\Temp\file.ps1'" /F
This will create a daily task that runs a powershell script specified at 5:30 as SYSTEM in conjunction with DarkLite1's answer.
After many writing may scripts and working on it, due to increased requirements script after script, the feature requirement made me in the end use the free option of the following tool.
Has more than needed
https://www.manageengine.com/network-monitoring/
Regards
How can I format my output to PowerShell's script
My output looks like
Hello #{SamAccountName=user1} is locked out
#{SamAccountName=user2} is locked out
My PowerShell code is
if ($users)
{
foreach($user in $users)
{
$message = $message + " " + $user + " is locked out" + "`r`n"
Write-Host $user
}
Send-MailMessage -To $to -Subject "Locked Accounts" -BodyAsHtml $message -From $from -Credential $cred -SmtpServer $server -Debug
}
Thank you
I would like my output to look like
Hello Administrator,
The following accounts are locked as of 10:31 AM on the 13th of April,
2015.
User1 User2
Thank You Automated System
As you can see in my current output, I can't figure out how to get a new line and it outputs #{SamAccountName=user1} instead of user1
Thank you
Here, try this approach instead. If you use a here-string (which is depicted like so:
$message = #"
So
this
keeps
track of spaces?
"#
You can put any amount of text inside and preserve the spacing of the message, while still having the ease of using this in your script by putting any variables inside that you might need.
As you'll see in the finished answer below, the line spacing is preserved. I'm using the $($variableName) format to allow me to pluck out one value of an object from within a bigger string. If I didn't use that format, the whole object would be listed, including all AD properties, which is not what we want.
if ($users)
{
$message = #"
Hello Administrator,
The following accounts are locked as of $((get-date).DateTime).
$($users | select -expand SamAccountName)
Thank You,
Automated System
"#
Send-MailMessage -To $to -Subject "Locked Accounts" -BodyAsHtml $message -From $from -Credential $cred -SmtpServer $server -Debug
}
The message will look like this:
Hello Administrator,
The following accounts are locked as of Monday, April 13, 2015 10:22:30 AM.
localadmin Guest Stephen RDV GRAPHICS SERVICE Jim SCVMM81221tqYYJ stephen.owen krbtgt _svc_sccm azure_adfs
Thank You,
Automated System
You need to directly access the sAMAccountName property on the $user object:
if ($users)
{
foreach($user in $users)
{
$message = $message + " " + $user.SamAccountName + " is locked out" + "`r`n"
}
Send-MailMessage -To $to -Subject "Locked Accounts" -BodyAsHtml $message -From $from -Credential $cred -SmtpServer $server -Debug
}
If you wanted to make something pretty, save the user names to an array first:
$lockedUsers = #()
foreach($user in $users)
{
$lockedUsers += ,$user.SamAccountName
}
Then you can construct your message like:
$message = #"
Hi Admin,
The following accounts are locked as of $(get-date)
$($lockedUsers -join ", ")
Thank you, Automated System
"#
I figured it out. Since the Body is HTML, I used standard HTML tags when forming the strings
<br> = new line
<strong></strong> = bold
<font color='red'></font> = red font
For the account names, I did
$message = $message + " " + $user.SamAccountName.ToLower() + " is locked out" + "<br>"
Here is my code that checks when users passwords will expire and emails them if it will expire in less than 14 days. Since the link in the body of the email has spaces in it, the link does not encompass the whole file name.
#Add the Quest PowerShell snapin
Add-PsSnapIn Quest.ActiveRoles.ADManagement -ErrorAction SilentlyContinue
#Clear the placeholder log file
Clear-Content O:\logs\network\passwordchangeemails.txt
#Set Email Variables
$today = Get-Date
$logdate = Get-Date -format yyyyMMdd
$emailFrom = "my.name#mycompany.com"
$body = "Good Morning, `n`n"
$body += "As a courtesy reminder, your Company password will be expiring soon. `n`n"
$body += "If you allow your password to expire, you will be unable to access our network, mail or QAD until you recieve assistance from the Helpdesk. `n`n"
**$body += "To avoid this, please change your network password as soon as possible. (Remote users, please follow the password change procedure for remote users. Click Here -> " + "\\mydfsshare.net\share\helpdesk\guides\Passwords - Change procedure for remote users.pdf ) `n`n"**
$body += "Feel free to contact the Help Desk by phone at 555-555-5555 or by email at Helpdesk#mycompany.com `n"
$body += "Thanks!"
#Get Active Directory Information
Get-QADUser -SizeLimit 0 | Select-Object samAccountName,mail,PasswordStatus |
Where-Object {$_.PasswordStatus -ne "Password never expires" -and $_.PasswordStatus -ne "Expired" -and $_.PasswordStatus -ne "User must change password at next logon." -and $_.mail -ne $null} |
#For each user, get variables
ForEach-Object {
$samaccountname = $_.samAccountName
$mail = $_.mail
$passwordstatus = $_.PasswordStatus
$passwordexpiry = $passwordstatus.Replace("Expires at: ","")
$passwordexpirydate = Get-Date $passwordexpiry
$daystoexpiry = ($passwordexpirydate - $today).Days
#If days to expire is lessthan 14 days, send email to user
if ($daystoexpiry -lt 14) {
$emailTo = "$mail"
$subject = "Company IT Notification: Your Network password will expire in $daystoexpiry day(s). "
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191
Write-Host "Email was sent to $mail on $today"
Add-Content O:\logs\network\passwordchangeemails.txt "Email was sent to $mail on $today"
}
}
$recipients = "my.name#mycompany.com"
#Copy contents of log file to email and send to IT Department
$content = [IO.File]::ReadAllText("O:\logs\network\passwordchangeemails.txt")
Send-MailMessage -To $recipients -From "my.name#mycompany.com" -Subject "Password change log for $today" -Body "This is the log from $today, $content" -SmtpServer 111.111.111.111
Sorry I can't test this right now but if HTML is OK to use, try wrapping the link as follows...
"Text you want the users to see goes here<br>`n
Then set -BodyAsHtml on Send-Mailmessage:
Send-MailMessage -To $emailTo -From $emailFrom -Subject $subject -Body $body -SmtpServer 192.168.1.191 -BodyAsHtml