1

I have a Powershell file that's sending emails based on a list of input parameters from a CSV file.

I've calculated a delay between each email based on the total time it needs to run for, divided by the number of lines in the file. Unfortunately this doesn't take into account the length of time it takes to send each individual email, which can vary between 1 second and 60 seconds so can't be estimated.

The intention is to calculate the length of time it took to send the email and subtract this from the intended delay, giving a value to pause before sending the next email (where this would produce a negative value, the next email would be sent immediately.)

I can't get the time calculation working properly though... the current looping code is as below:

$StartTime = [datetime](get-date).ToShortTimeString()
Start-Countdown -Seconds $iDelay -Message ("Waiting to send email "+$i+" of "+$LinesinFile)
sendMail
$iTimeToRun = NEW-TIMESPAN –Start $StartTime -End [datetime(get-date).ToShortTimeString()
$iDelay = $Delay - $iTimeToRun

Delay is the intended delay required, so subtracting the time to send previous email should give me the required delay for the next one. Start-Countdown and sendMail are functions defined within the script... the sendMail function is the one that needs to be calculated specifically as it will have the most impact on the time to run.

Gallus
  • 335
  • 3
  • 21
  • It's not clear what you're trying to do. Is the delay supposed to be dynamic? Why can you not fix it? Why is it required at all? It might help to show the `sendMail` function to demonstrate more clearly what the issue is. Look at using the `Measure-Command` cmdlet to determine how long a command runs for. No need to create your own methods for determining this. – arco444 Jun 05 '15 at 09:05
  • The delay needs to be dynamic as each email takes a different time to send. The email server doesn't always respond in the same time to each request, so where you might want to send an email every 20 seconds, you actually want to delay the first by 15 seconds, as the previous email took 5 seconds to send, and then the second delay might be 10 seconds as the previous email took 10 seconds to send. – Gallus Jun 05 '15 at 09:41
  • So can't you just send your emails by using a loop? That way the next one won't be sent until the server responds and you don't need to worry about the delay at all. – arco444 Jun 05 '15 at 09:43
  • As always, someone already got there first... http://stackoverflow.com/questions/3513650/timing-a-commands-execution-in-powershell – Gallus Jun 05 '15 at 09:45
  • If you did that, you might end up with 100 sent within 1 hour, then the next 100 takes 2 hours etc. etc... that wouldn't spread them very evenly and would produce massive peaks and troughs dependent on the email server's response times. It specifically needs to have the delay between the emails, and they need to be as constant as possible. – Gallus Jun 05 '15 at 09:48

2 Answers2

3

Measure-Command will time PowerShell execution.

Richard
  • 106,783
  • 21
  • 203
  • 265
2

If you don't want to use Measure-Command, you can use the a StopWatch:

$Delay = New-TimeSpan -Seconds 120
Write-Verbose "sending mail"
$Watch = [System.Diagnostics.Stopwatch]::StartNew()
sendMail
$Watch.Stop()
Write-Verbose "Sending mail took $($Watch.Elapsed.TotalSeconds) seconds"
if(($Delay = $Delay - $Watch.Elapsed) -gt 0){
    Write-Verbose "Waiting another $($Delay.TotalSeconds) seconds before sending the next"
    Start-Sleep -Milliseconds $a.TotalMilliseconds
} else {
    Write-Verbose "Sending mail exceeded delay, right on to the next one!"
}
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Excellent... the stopwatch method is definitely the clearest and the output messages are useful to know what's going on. I'll give it a little testing but I'm sure this will work – Gallus Jun 05 '15 at 09:50