YorSubs
YorSubs

Reputation: 4090

PowerShell Spawn a background process for keep alive

I have a simple keep-alive function that will press ScrollLock every 60 seconds to stop my work laptop from going to sleep (altering power-management settings is not an option here as those settings are restricted to me on this work system), but this script is dependent upon the console that starts the function from always being open. Can someone advise how to get this function to:

• spawn a completely independent process (i.e. not a child process) that will continue to exist even after the console that runs the function closes?

• Make that new process completely silent i.e. starts invisibly as a background process that I can only see by running Get-Process?

Being able to create independent (non-child) processes in this way would be good for many other situations I think - that ability to create an independent process that does not close with the calling console would be really useful.

function KeepAlive {
    $wsh = New-Object -ComObject WScript.Shell
    while($true) {
        $wsh.SendKeys('{SCROLLLOCK}')
        Start-Sleep 60
    }
}

Upvotes: 3

Views: 4428

Answers (2)

YorSubs
YorSubs

Reputation: 4090

I've confirmed that Start-Process seems to start a completely new process. I think this might be the correct approach. I guess that somehow I need to start a new powershell window, then get that process to run my code? A bit confused on the best approach here: should I take the Keypress code code and redirect it into a temp script file, and then call that script from the new Start-Process or is there a more efficient approach to do this do you think?

Upvotes: 1

Mathias R. Jessen
Mathias R. Jessen

Reputation: 175085

Easiest way - use a background job:

Start-Job {
    $wsh = New-Object -ComObject WScript.Shell
    while($true) {
        $wsh.SendKeys('{SCROLLLOCK}')
        Start-Sleep 60
    }
}

Background jobs will (transparently to you) result in the code running in a separate child process.

If you want to run your code in the background within the same process, you'll want to assign your code to run in a separate runspace - a runspace is somewhat analogous to a "thread" in low-level programming languages:

# Create (and open) a new runspace
$rs = [runspacefactory]::CreateRunspace([initialsessionstate]::CreateDefault2())
$rs.Open()

# Create a [powershell] object to bind our script to the above runspaces
$ps = [powershell]::Create().AddScript({
    $wsh = New-Object -ComObject WScript.Shell
    while($true) {
        $wsh.SendKeys('{SCROLLLOCK}')
        Start-Sleep 60
    }
})

# Tell powershell to run the code in the runspace we created
$ps.Runspace = $rs

# Invoke the code asynchronously
$handle = $ps.BeginInvoke()

The BeginInvoke() function will return immediately, and the code will start executing in our background runspace - meaning it doesn't block the default runspace, so you can continue using the shell in the mean time.

To end/halt execution again:

$ps.Stop()

Upvotes: 2

Related Questions