kill a child process on windows using powershell - powershell

I have the below script but it seems it wont kill the child processes. How do i kill child processes?
When it runs, it looks fine but then there are dialog boxes left over and then when i check task manager the original processes are still running. Which makes me think if the script ran properly. The other weird part to this is that naturally I would see these processes (.exe programs) running active on the task bar but after the script runs they look like they aren't running. But again, I check task manager and sure enough, they are still running.
$ErrorActionPreference = "SilentlyContinue"
Stop-Transcript | Out-Null
$ErrorActionPreference = "Continue"
Start-Transcript -Path C:\Scripts\Errors\errors.log -Append
$process = Get-Process -Name "IVR1","IVR2","IVR3"
$IVR1path = "C:\IVR1"
$IVR2path = "C:\IVR2"
$IVR3path = "C:\IVR3"
if ($process) {
$Process | Stop-Process -Force
Start-Sleep -s 5
cd $IVR1path
Start-Process ".\IVR1.exe"
cd IVR2path
Start-Process ".\IVR2.exe"
cd IVR3path
Start-Process ".\IVR3.exe"
cd ..
cd ..
$From = "IVR1#example.com.au"
$To = "myemail#example.com.au"
$cc = "myemail#example.com.au"
$Subject = "**TEST** - IVR1 has been recovered"
$Body = "The IVR has been successfully recovered"
$SMTPServer = "mail.example.com.au"
Send-MailMessage -From $From -to $To -cc $cc -Subject $Subject -Body $Body -SmtpServer $SMTPServer
Stop-Transcript
}
Would anyone have any suggestions? Could it be due to child processes not being killed or the original process being hung?

I think that you've misused tools you have to achieve the goal. Use https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-process?view=powershell-4.0 and functions listed at the end of page ( all about process lifecycle ).
Side note: add more verbosity ( write-output variable values) to what your script does so you will know what is happening ( or use the debugger, because I`m not sure if most of code you pasted is even executed ).

Related

How to call a function when Get-Content reads a line

I am setting up a script that will send me an email every time a certain log file is written to but when Get-Content reads a new line, the pipe does not call the sendmail function.
The sendmail function is defined before the following line and successfully sends me an email by itself.
Get-Content -Tail 0 -Wait app.log | sendmail
You need to learn what a process block is. It runs for every element piped in. Put your code in the process block, and it will do what you want, as someone else already answered. Process blocks are really important in powershell.
function hi {
process {
'hi'
}
}
Get-Content -Tail 0 -Wait app.log | hi
hi
hi
hi
You should get the value from the pipeline through a process block:
function sendmail {
process {
$secpasswd = ConvertTo-SecureString "password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ("username", $secpasswd)
Send-MailMessage -SmtpServer mysmtp -Credential $cred -UseSsl -From 'myemail#domain.com' -To 'toemail#domain.com' -Subject 'TEST'
}
}
This will tell PowerShell that you want this section of code to run for every object passed on the pipeline (every line in this case). If you want to access the current object from inside the process block, use $_ as a variable.
See Piping Objects to Functions

Issue in Executing a batch script during -XX:OnOutOfMemoryError event

I have written a power shell script in my Win 2008 server, to execute the below mentioned 4 steps whenever an OutOfMemoryError occurs in the system.
Email users that the applications is going to be restarted.
stop the app service
clear cache and tmp files
start the service
email users that the service is started
The Script is given below and it is working like a gem when executed manually. I have added the below .ps1 script in a .bat file and updated the registry entry as
-server -Xms1024m -Xmx1536m -XX:MaxPermSize=256m -XX:+UseParallelOldGC -XX:OnOutOfMemoryError="D:\Support\UWD_OOM_restart.bat"
Issue: Whenever an OOM error occurs, the batch script invokes the power shell script, but only the first 3 steps are getting executed automatically. The last 2 steps( starting the service and emailing end users are not getting executed automatically). Need some assistance in this case
Power shell script:
$hostname = 'XXXXXX'
$smtpServer = 'xxxxxxxx'
$from = "xxxxxxxx#xxxxxxxx.com"
$recipients = 'xxxxxxxx#xxxxxxxx.com'
$Subject = "Restarting Apps - UWD Service on $hostname due to Java OUT OF MEMORY ERROR"
$body = "This is an automated message to confirm that the UWD service on xxxxxxxx server is about to be restarted, as the application has encountered Java out of memory error and went to unresponsive state. Kindly ignore any alerts for the next 10 minutes from this service."
Send-MailMessage -To $recipients -Subject $Subject -Body $body -From $from -SmtpServer $smtpServer
# Stop service
$service = 'xxxxxxxx"
Stop-Service -name $service -Verbose
do {
Start-sleep -s 5
}
until ((get-service $service).Status -eq 'Stopped')
# Folder delete
rm -r -fo 'D:\xxxxxxx\cache'
rm -r -fo 'D:\xxxxxxx\tmp'
# Start service
start-Service -name $service -Verbose
do {
Start-sleep -s 5
}
until ((get-service $service).Status -eq 'Running')
# Send confirmation that service has restarted successfully
$Subject = "UWD Service Restarted Successfully on $hostname"
$body = "This mail confirms that the UWD application service on $hostname is now running.
Application Team, Kindly smoke test your application and inform xxxxxx for any issues."
Start-Sleep -s 5
Send-MailMessage -To $recipients -Subject $Subject -Body $body -From $from -SmtpServer $smtpServer

Clearing files from Cloudflare API via Powershell randomly stops working

This is my first time making a script for an API call, so if I am making stupid or silly mistakes, please be nice about it :)
Brief overview:
I am monitoring for file system changes. When my monitor detects a file being changed in a certain directory (recursively), the script will fire off an API call to Cloudflare and clear the file from Cloudflare's caching servers.
The script is compiled into an EXE using PS2EXE. I then have the script installed as a service, using NSSM.
I have to make some unique adjustments and take the local filename, and convert it to the API specifications in Cloudflare's API Documentation
This system is running on Azure and uses Azure File Storage. This is why I need to test for the path when the service is started because Azure File Storage mapping needs specific settings (Lines 4-13). These machines are not joined to any domain. If anyone has a better method, I'm all ears.
Issue:
The script just... stops working after some time? Most of the time, my logs do not catch the error. It's almost like the file system watcher is just not "watching" anymore. The log merely stops and doesn't process any more calls. If I run into an error, I want the script to ideally stop immediately by restarting the service. If I cannot restart the service, I want the script to immediately tell me by capturing the error message and sending me an email and then stop running entirely.
If I do run into an error, the script fails to restart the service. I imagine this is because my logic is incorrect regarding restarting the service.
My question is:
Can I restart the service within the script? (Lines 48-55)
What can I do to make this stop becoming so inconsistent? Ideally I don't want to have to restart the job or the machine. (I've noticed if I restart the job, it doesn't necessarily kill the watcher jobs.)
Edit Note: I am temporarily using my smtp credentials in-script until I can figure out why its so inconsistent and then adjust this so the smtp credentials are properly secured with a keyfile and the like.
Here's the script:
Start-Transcript C:\Utilities\Transcript\filetranscript-errorchecking.txt -Append
# Check to see if file is mapped and correct the action if not.
switch (Test-Path S:\Root)
{
$false {
& cmdkey /add:azurefilestore.file.core.windows.net /user:AZURE\azurefileuser /pass:**passkey**
& net use S: \\azurefilestore.file.core.windows.net\web /u:AZURE\azurefileuser **passkey**
}
$true {
Write-Output "File is already mapped. Doing nothing."
}
}
### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "S:\Root"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true
#####CLOUDFLARE HEADERS#####
$auth_email = 'cloudflareuser#organization.com'
$zone_key = 'cloudflare-key'
$auth_token = 'cloudflare-auth-token'
$headers = #{'X-Auth-Key'=$auth_token;'X-Auth-Email'=$auth_email;'Content-Type'='application/json'}
$emailun = "smtprelayemail#organization.com"
$emailpw = "myemailsmtp" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($emailun,$emailpw)
$date = Get-Date
### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
$body = $event.SourceEventArgs.Fullpath -replace 'S\:\\Root\\','https://websiteurl.url.com/' -replace ' ','%20' -replace '\\','/'
# Re-enable below line for testing by removing comment. See next comment note #39.
# [string]$placedstring = 'break{"files":["' + $body + '"]}'
# IMPORTANT: Comment the below line when testing.
[string]$placedstring = '{"files":["' + $body + '"]}'
Write-Host "$placedstring"
Try
{
# We want the script to STOP and send us an e-mail if an issue is detected.
Invoke-RestMethod -uri "https://api.cloudflare.com/client/v4/zones/$zone_key/purge_cache" -Method DELETE -Headers $headers -body $placedstring -ErrorAction Stop -Verbose
# Write-Output $placedstring "is being removed."
}
Catch
{
$ErrorMessage = $_.Exception.Message
Send-MailMessage –From smtprelayemail#organization.com –To myemail#organization.com –Subject "Cloudflare API failure on Azure!" –Body "There was an issue with the Cloudflare API calls. The error was: $ErrorMessage. The Cloudflare API is now being restarted..." -SmtpServer smtp.server.com -Credential $cred -UseSsl -Port 587 -Verbose
try {
Restart-Service -Name "CloudflareAPI-Error" -Force -ErrorAction Stop
}
catch {
$ErrorMessage = $_.Exception.Message
Send-MailMessage –From smtprelayemail#organization.com –To myemail#organization.com –Subject "Unable to restart service for Cloudflare" –Body "The error was: $ErrorMessage." -SmtpServer smtp.server.com -Credential $cred -UseSsl -Port 587 -Verbose
}
}
}
### DECIDE WHICH EVENTS SHOULD BE WATCHED
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}
Sample log output:
{"files":["https://websiteurl.url.com/main.css"]}
VERBOSE: DELETE https://api.cloudflare.com/client/v4/zones/apit-zone-key/purge_cache with -1-byte payload
VERBOSE: received -1-byte response of content type application/json
{"files":["https://websiteurl.url.com/main.css"]}

Checking for a running process and if its not found, starting it

I'm trying to write a short script to run each morning on a machine to check for two programs and if they aren't running, to start them. I've made this:
$process = "ProcessToStart"
$check = Get-Process $process
$executable = "ProcessFilePath"
if (!($check)) {
Start-Process $executable
Send-MailMessage -From "Machine" -To "IT" -Subject "Program was restarted" -Body "The program wasnt running" -SMTP "mail.blah.com"
}
$process = "outlook"
$executable = "C:\Program Files\Microsoft Office 15\root\office15\outlook.exe"
if (!($check)) {
Start-Process $executable
Send-MailMessage -From "Machine" -To "IT" -Subject "Program was restarted" -Body "The program wasnt running" -SMTP "mail.blah.com"
}
The problem I have is, last week it worked, and only launched/emailed if the process wasn't running. I've retested it this week and it's launching and emailing even if the processes are already running and I can't figure out what's different.

Execute batch script from powershell with feedback

I need your valuable comments/advice on how we could implement powershell script to send feedback to users during its execution based on its runtime.
Powershell script will be executing a batch script.
Clear-Host
cmd.exe "/c G:\BEKDocs\Batch\Batch1.cmd"
Write-Host "The Exit code from Batch1 is " $LastExitCode
Batch script will do some processing on its own, i want the power shell script to provide the feedback to few set of users on the below occasions through mail communication using SMTP (I have SMTP configured in the server).
When the script starts (Mail should be sent).
If the script completes within a minute.
If the script runs for more than a hour.
If the script fails.
Regards,
Naga
Use Send-MailMessage to send mail. Use Measure-Command to measure the execution time of a command. Use $LASTEXITCODE to determine whether an external command succeeded or failed.
$from = 'sender#example.com'
$to = 'recipient#example.com'
Send-MailMessage -From $from -To $to -Subject 'script started'
$time = Measure-Command { & cmd.exe /c "G:\BEKDocs\Batch\Batch1.cmd" }
if ( $time.TotalMinutes -le 1 ) {
Send-MailMessage -From $from -To $to -Subject 'script completed within 1 min'
} elseif ( $time.TotalMinutes -gt 60 ) {
Send-MailMessage -From $from -To $to -Subject 'script ran longer than 1 hour'
}
if ( $LASTEXITCODE -ne 0 ) {
Send-MailMessage -From $from -To $to -Subject 'script failed'
}