Is there a wscript.timeout equivalent in PowerShell?

This topic contains 6 replies, has 3 voices, and was last updated by Profile photo of Corey Thomas Corey Thomas 1 year, 9 months ago.

  • Author
    Posts
  • #23083
    Profile photo of Corey Thomas
    Corey Thomas
    Participant

    Q: Is there a powershell equivalent of wscript.timeout from vbscript?

    I'm writing a script that will run at the domain level during computer or user startup. I want to ensure that it doesn't hang around too long. In vbscript, I just used wscript.timeout to ensure the script never went past a maximum run time. Just wondering if there is a powershell equivalent.

  • #23087
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Wow... I don't know how many years I was writing VBScripts, and never knew about that feature.

    I don't know if there's a built-in way to do this in PowerShell, but it's certainly something that your script could do itself, using events and the Timer class. At first I tried to do this with Register-ObjectEvent, but it turns out that a long-running command can still hang a PowerShell script, and the event handler script block won't be invoked until after that command is done. However, embedding a bit of C# for the event handler seems to work just fine:

    Add-Type -TypeDefinition @'
        using System;
        using System.Timers;
        using System.Diagnostics;
    
        public static class TimerUtil
        {
            private static Timer timer;
            
            private static Timer GetTimer()
            {
                if (timer == null)
                {
                    timer = new Timer();
                    timer.Elapsed += (sender,eventArgs) => { Process.GetCurrentProcess().Kill(); };
                }
    
                return timer;
            }
    
            public static void KillThisProcessAfter(double interval)
            {
                GetTimer().Interval = interval;
                GetTimer().Start();
            }
        }
    '@
    
    [TimerUtil]::KillThisProcessAfter(5000)
    
    Start-Sleep -Seconds 20
    
    Write-Host 'Should not get here.'
    

    Quick note, though: this kills the whole process (powershell.exe or the ISE, typically), not just the current script.

  • #23091
    Profile photo of Don Jones
    Don Jones
    Keymaster

    Not really, no. You could track time internally, though, and write an abort clause.

  • #23092
    Profile photo of Corey Thomas
    Corey Thomas
    Participant

    That works. Was hoping for a one-liner like we had in vbscript (PS has me so spoiled with one-liners!)

    Thanks Dave!

  • #23093
    Profile photo of Corey Thomas
    Corey Thomas
    Participant

    Well I thought this Dave's solution was going to work but it's only v3+. I'm writing this in v2 for compatibility and it doesn't like Add-Type.

    I could add some internal checks like Don mentioned but I'm mostly worried about a cmdlet hanging.

  • #23094
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    All you need to do to make that example work in v2 is add -Language CSharpVersion3 to the call to Add-Type:

    Add-Type -Language CSharpVersion3 -TypeDefinition @'
        using System;
        using System.Timers;
        using System.Diagnostics;
    
        public static class TimerUtil
        {
            private static Timer timer;
            
            private static Timer GetTimer()
            {
                if (timer == null)
                {
                    timer = new Timer();
                    timer.Elapsed += (sender,eventArgs) => { Process.GetCurrentProcess().Kill(); };
                }
    
                return timer;
            }
    
            public static void KillThisProcessAfter(double interval)
            {
                GetTimer().Interval = interval;
                GetTimer().Start();
            }
        }
    '@
    
    [TimerUtil]::KillThisProcessAfter(5000)
    
    Start-Sleep -Seconds 20
    
    Write-Host 'Should not get here.'
    

    It just didn't like the lambda expression I used to set up the event handler. Could also revise the code so it uses an older method that's compatible with C# v2.

  • #23095
    Profile photo of Corey Thomas
    Corey Thomas
    Participant

    Kudos Dave! 😀

    Making this a snippet now. 🙂

You must be logged in to reply to this topic.