Matt Miller
Matt Miller

Reputation: 318

Terminate vbscript after x minutes

I am working on a script with vbscript, and I would like it to terminate itself after x number of minutes.

I was thinking something like grabbing the time when the script starts and then keeping the whole thing in a loop until the time is x number of minutes after the start time, but I need it to keep checking in the background, and not just wait until a loop is complete.

I want a message or something that notifies the user they took too long, which I can do myself.

Is there any way to keep track of the time in the background, or will it be a bit of a drawn-out process to determine it?

Upvotes: 3

Views: 13121

Answers (4)

omegastripes
omegastripes

Reputation: 12602

Here is another short and elegant solution which allows to terminate both the script and the external executable ran asynchronously, via WScript.Timeout

Option Explicit

Dim oSmallWrapperWshExec

WScript.Timeout = 7
Set oSmallWrapperWshExec = New cSmallWrapperWshExec
' Some code here
MsgBox "Waiting timeout" & vbCrLf & vbCrLf & "You may close notepad manually and/or press OK to finish script immediately"

Class cSmallWrapperWshExec

    Private oWshShell
    Private oWshExec

    Private Sub Class_Initialize()

        Set oWshShell = CreateObject("WSCript.Shell")
        With oWshShell
            Set oWshExec = .Exec("notepad")
            .PopUp "Launched executable", 2, , 64
        End With

    End Sub

    Private Sub Class_Terminate()

        On Error Resume Next
        With oWshShell
            If oWshExec.Status <> 0 Then
                .PopUp "Executable has been already terminated", 2, , 64
            Else
                oWshExec.Terminate
                .PopUp "Terminated executable", 2, , 64
            End If
        End With

    End Sub

End Class

Upvotes: 4

Matt Miller
Matt Miller

Reputation: 318

I appreciate all of the answers here, but they are more complicated than I wanted to get in to.

I was very surprised to find out that there is a way to do it built into WScript.

WScript.Timeout = x_seconds

Upvotes: 2

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200203

Re-launching the script with //T:xx as suggested by Ekkehard.Horner is probably your best option. Another, slightly different, approach could look like this:

Const Timeout = 4 'minutes

timedOut = False

If WScript.Arguments.Named.Exists("relaunch") Then
  'your code here
Else
  limit = DateAdd("n", Timeout, Now)
  cmd = "wscript.exe """ & WScript.ScriptFullName & """ /relaunch"
  Set p = CreateObject("WScript.Shell").Exec(cmd)
  Do While p.Status = 0
    If Now < limit Then
      WScript.Sleep 100
    Else
      On Error Resume Next  'to ignore "invalid window handle" errors
      p.Terminate
      On Error Goto 0
      timedOut = True
    End If
  Loop
End If

If timedOut Then WScript.Echo "Script timed out."

You'd still be re-launching the script, but in this case it's your script killing the child process, not the script interpreter.

Upvotes: 7

Ekkehard.Horner
Ekkehard.Horner

Reputation: 38745

cscript
Usage: CScript scriptname.extension [option...] [arguments...]

Options:
 //B         Batch mode: Suppresses script errors and prompts from displaying
 //D         Enable Active Debugging
 //E:engine  Use engine for executing script
 //H:CScript Changes the default script host to CScript.exe
 //H:WScript Changes the default script host to WScript.exe (default)
 //I         Interactive mode (default, opposite of //B)
 //Job:xxxx  Execute a WSF job
 //Logo      Display logo (default)
 //Nologo    Prevent logo display: No banner will be shown at execution time
 //S         Save current command line options for this user
 **//T:nn      Time out in seconds:  Maximum time a script is permitted to run**
 //X         Execute script in debugger
 //U         Use Unicode for redirected I/O from the console

Update:

To help people who downvote a plain (and to the point) citation of cscript.exe's usage message (how can that be wrong?) to see the light through @PanayotKarabakalov's smoke screen:

The claim:

using //T switch not guarantee real time accuracy

that all 5 Echo command executed, even if the Sleep time between them is 1.5 second and the //T is set to 4

The evidence:

The script is restarted via:

CreateObject("WScript.Shell").Run "WScript " & _
    Chr(34) & WScript.ScriptFullName & _
    Chr(34) & " /T:4", 0, False

which does not contain the host-specific //T (as opposed to the script-specific /T) switch.

The (counter) argument:

Whatever way you start the first instance of the script (//T or no //T), the second/relaunched instance will never have a time out and will always run to the bitter end.

If you still have doubts, change the invocation in P.'s script to

 CreateObject("WScript.Shell").Run "WScript //T:4 " & _

and try it out.

Upvotes: 1

Related Questions