0

I'm invoking a script as described here and exemplified here. It's running and I can see the outputs to the console (both hazaa and shazoo). However, the method declared in it does not appear to be there, despite testing both versions below.

Invoke-Expression -Command $target
$target | Invoke-Expression

The contents of the file are like this.

Write-Host "Hazaa"
function TestPower { Write-Host "I got the power..." }
Write-Host "Shazoo"

When I execute the same function definition in the console, it's there, working fine. I'm not getting any errors on the manual execution nor the invokation from the other file. No warnings neither.

The weirdest part is that the function definitions done in the invoking script (i.d. the one that the invokes the execution not the one that in being targeted for the invokation).

Konrad Viltersten
  • 36,151
  • 76
  • 250
  • 438
  • "it does not appear to be there" - there's nothing in the file that would tell you either way, so how did you reach that conclusion? And what is `$target`? – Mathias R. Jessen Sep 21 '20 at 09:10
  • @MathiasR.Jessen I try to execute a function in the invoking script and it works, giving me the expected printout. Then, I execute a function contained in the invoked script and get an error telling me that it't not there. As for the second question, since the script is being invoked (which we know because there's a printout), the exact content of the path in *$target* seems irrelevant. Lets say it's *c:\temp\beep.ps1*. – Konrad Viltersten Sep 21 '20 at 15:21

1 Answers1

5

To rephrase your issue - a function defined in a script invoked with Invoke-Expression isn't available after the expression has executed, i.e.:

test.ps1

Write-Host "Hazaa"
function TestPower { Write-Host "I got the power..." }
Write-Host "Shazoo"

Interactive

PS> Invoke-Expression -Command "C:\src\so\test.ps1"
PS> TestPower
TestPower : The term 'TestPower' 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.
At line:1 char:1
+ testpower
+ ~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (testpower:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

You can fix this by dot-sourcing the script in the expression instead:

PS> Invoke-Expression -Command ". 'C:\src\so\test.ps1'"
Hazaa
Shazoo
PS> TestPower
I got the power...

Note that the documentation for script scope and dot sourcing says:

Each script runs in its own scope. The functions, variables, aliases, and drives that are created in the script exist only in the script scope. You cannot access these items or their values in the scope in which the script runs.

Which explains why TestPower isn't available outside of your Invoke-Expression because the script is running in its own scope.

By contrast, using dot sourcing:

The dot sourcing feature lets you run a script in the current scope instead of in the script scope. ... After the script runs, you can use the created items and access their values in your session.

mclayton
  • 8,025
  • 2
  • 21
  • 26
  • This is one kick-ass answer regarding clarity and consideration for the provided facts. If it works (I haven't tested yet but I'm sure it's going to resolve my issue), you not only helped me for this case but also educated me on dot-sourcing, which I've never heard of before. As such, i working, you'll be getting the sweet, sweet strike of bounty apart from greeny checky and plussy-one-y. – Konrad Viltersten Sep 21 '20 at 15:25
  • Absolutely kick-ass'y. Accepting as correct answer and smacking you with a bounty (in 2 days, though, due to limitation of SO). I'm cheap AF so it's the minimum 50 rep only but feel privileged - given how rarely I do it, it's like 500 in normal peoples rep. :) – Konrad Viltersten Sep 21 '20 at 15:29
  • Damn, I almost forgot. I had to wait two days to start the bounty. Now I have to wait additional day to award it. Just in case I forget, please do remind me. I'd hate to see it not awarded to you. You do deserve it and I'm forgetful AF, due to medical reasons. You will not be seen as a naggy beggar or rep junkie, whatsoever. – Konrad Viltersten Sep 23 '20 at 15:42