Steven
Steven

Reputation: 380

Powershell function call causes missing function error using powershell v7 on windows 10

I wrote a script to build all .net projects in a folder.

Issue

The issue is I am getting a missing function error when I call Build-Solution.

What I tried

I made sure that function was declared before I used it so I am not really sure why it said that it is not defined.

I am new to powershell but I would think a function calling another functions should work like this?

Thanks in advance!

Please see below for the error message and code.

Error Message

Line |
3 | Build-Solution $_
| ~~~~~~~~~~~~~~~
The term 'Build-Solution' 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.

Code for Build-Solution:

param (
    #[Parameter(Mandatory=$true)][string]$plugin_path,
    [string]$depth = 5
 )

 $plugin_path = 'path/to/solutions/'

function Get-Solutions {

  Get-ChildItem -File -Path $plugin_path -Include *.sln -Recurse  

}

function Build-Solution($solution) {

  dotnet build $solution.fullname

}

function Build-Solutions($solutions) {

  $solutions | ForEach-Object -Parallel {

    Build-Solution $_

  }

}


$solutions_temp = Get-Solutions
Build-Solutions $solutions_temp

Upvotes: 0

Views: 1311

Answers (2)

7cc
7cc

Reputation: 1169

From PowerShell ForEach-Object Parallel Feature | PowerShell

Script blocks run in a context called a PowerShell runspace. The runspace context contains all of the defined variables, functions and loaded modules.

...

And each runspace must load whatever module is needed and have any variable be explicitly passed in from the calling script.

So in this case, the easiest solution is to define Build-Solution inside Build-Solutions

Upvotes: 1

postanote
postanote

Reputation: 16096

As for this...

I am new to powershell but I would think a function calling another functions should work like this?

... you cannot use the functions until you load your code into memory. You need to run the code before the functions are available.

If you are in the ISE or VSCode, if the script is not saved, Select All and hit use the key to run. In the ISE use F8 Selected, F5 run all. In VSCode, F8 run selected, crtl+F5 run all. YOu can just click the menu options as well.

If you are doing this from the consolehost, the run the script using dot sourcing.

. .\UncToYourScript.ps1

It's ok to be new, we all started somewhere, but it's vital that you get ramped up first. so, beyond what I address here, be sure to spend time on Youtube and search for Beginning, Intermediate, Advanced PowerShell for videos to consume. There are tons of free training resources all over the web and using the built-in help files would have given you the answer as well.

about_Scripts

SCRIPT SCOPE AND DOT SOURCING 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.

To run a script in a different scope, you can specify a scope, such as Global or Local, or you can dot source the script.

The dot sourcing feature lets you run a script in the current scope instead of in the script scope. When you run a script that is dot sourced, the commands in the script run as though you had typed them at the command prompt. The functions, variables, aliases, and drives that the script creates are created in the scope in which you are working. After the script runs, you can use the created items and access their values in your session.

To dot source a script, type a dot (.) and a space before the script path.

See also:

'powershell .net projects build run scripts'

'powershell build all .net projects in a folder'

Simple build script using Power Shell

Update

As per your comments below:

Sure the script should be saved, using whatever editor you choose.

The ISE does not use PSv7 by design, it uses WPSv5x and earlier.

The editor for PSv7 is VSCode. If you run a function that contains another function, you have explicitly loaded everything in that call, and as such it's available.

However, you are saying, you are using PSv7, so, you need to run your code in the PSv7 consolehost or VSCode, not the ISE.

Windows PowerShell (powershell.exe and powershell_ise.exe) and PowerShell Core (pwsh.exe) are two different environments, with two different executables, designed to run side-by-side on Windows, but you do have to explicitly choose which to use or write your code to branch to a code segment to execute relative to the host you started.

For example, let's say I wanted to run a console command and I am in the ISE, but I need to run that in Pwsh. I use a function like this that I have in a custom module autoloaded via my PowerShell profiles:

# Call code by console executable
Function Start-ConsoleCommand
{
    [CmdletBinding(SupportsShouldProcess)]

    [Alias('scc')]

    Param  
    ( 
        [string]$ConsoleCommand,
        [switch]$PoSHCore
    )

    If ($PoSHCore)
    {Start-Process pwsh -ArgumentList "-NoExit","-Command  &{ $ConsoleCommand }" -PassThru -Wait}
    Else {Start-Process powershell -ArgumentList "-NoExit","-Command  &{ $ConsoleCommand }" -PassThru -Wait}
}

All this code is doing is taking whatever command I send it and if I use the PoSHCore switch...

scc -ConsoleCommand 'SomeCommand' -PoSHCore

... it will shell out to PSCore, run the code, otherwise, it just runs from the ISE>

If you want to use the ISE with PSv7 adn not do the shell out thing, you need to force the ISE to use PSv7 to run code. See:

Using PowerShell Core 6 and 7 in the Windows PowerShell ISE

Upvotes: 1

Related Questions