3

Works fine in powershell ISE, but in console I get:

The term 'MainAction' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

How to fix?

function MainAction () {
    $test = "123"
    Write-Host $test
}

MainAction

$action = {
    try {
        Write-Host in action
        MainAction
    } catch {
        Write-Host $Error    
        $timer.Stop()
        Unregister-Event thetimer
    }
}

$timer = New-Object Timers.Timer    
Register-ObjectEvent -InputObject $timer -EventName elapsed `
                     -SourceIdentifier thetimer -Action $action -OutVariable out
$timer.Interval = 5000
$timer.AutoReset = $true
$timer.Start()

EDIT:

I found that I can use profile to store function definitions. To create profile use:

New-Item -path $profile -itemType file -force

But I'am still intrested why powershell ISE don't need profile to store and use functions in action of Register-ObjectEvent.

2
  • 3
    function MainAction -> function global:MainAction Commented Feb 11, 2017 at 11:10
  • you right, this works and more convinient than profile, thank you Commented Feb 11, 2017 at 11:14

1 Answer 1

7

When you register -Action with Register-ObjectEvent, PowerShell will create new dynamic module to host the action. Thus, as result of that, only global scope is shared between event handler and rest of the code. So, you should put all needed functions in global scope:

function global:MainAction {
    Write-Host 'Do something'
}

$Action = { MainAction }

$Timer = New-Object Timers.Timer
$EventJob = Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action $Action

$Timer.Interval = 5000
$Timer.AutoReset = $true
$Timer.Start()

Or explicitly add them in scope of that dynamic module, created by PowerShell:

$Action = { MainAction }

$Timer = New-Object Timers.Timer
$EventJob = Register-ObjectEvent -InputObject $Timer -EventName Elapsed -Action $Action

. $EventJob.Module {
    function MainAction {
        Write-Host 'Do something'
    }
}

$Timer.Interval = 5000
$Timer.AutoReset = $true
$Timer.Start()
Sign up to request clarification or add additional context in comments.

1 Comment

I also want to add now that it can be convinient to use dynamic module to store your functions and variables if they must be accessible from main thread too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.