Why do I need to have my functions written first in my PowerShell script?

前端 未结 6 960
忘掉有多难
忘掉有多难 2020-12-29 01:06

I have a script that I am utilizing functions to wrap parts of the code that allow me to move through the sections at a specified point. What I have found is that I have to

相关标签:
6条回答
  • 2020-12-29 01:20

    A solution from Microsoft blog, Enclose the main code in a block and call in the end,

    $MainFunction={
       $stepChoice = read-host 'Where would you like to start.'
       switch($stepChoice)
       {
           1{Step1}
           2{Step2}
           3{Step3}
       }
    }
    # Steps.ps1 
    function Step1 { 
      'Step 1' 
       Step2 
    } 
    function Step2 { 
      'Step 2' 
       Step3 
    } 
    function Step3 { 
      'Step 3' 
      'Done!' 
    }
    #This line executes the program
    & $MainFunction
    
    0 讨论(0)
  • 2020-12-29 01:24

    Reorder your script

    PowerShell is a script, not a compiled language. Therefore, it goes through the script line-by-line, top to bottom, (after tokenizing the script) and evaluates each command along the way. If it hasn't gotten to the definition of a function yet and you're already attempting to invoke that function, PowerShell will throw an error.

    Therefore, in this case you must move the function definitions before the switch statement - as you've discovered.

    Forward declarations

    Even some compiled languages behave this way, most notably C/C++, and require forward declarations to work around this issue.

    Other compiled languages like C# do multiple passes over the code during compilation so that forward declarations aren't required.

    0 讨论(0)
  • 2020-12-29 01:28

    Sorry, I had to comment. CMD\Batch does allow you to declare the functions below the main method just like C#.

    @ECHO OFF
    ::Main
    CALL :Function1
    CALL :Function2
    EXIT /b
    
    ::Functions
    :Function1
        (ECHO Hello) & (ECHO World) 
    EXIT /b
    
    :Function2
        (ECHO Foo) & (ECHO Bar) 
    EXIT /b 
    
    0 讨论(0)
  • 2020-12-29 01:29

    In addition to what Keith said about the interpreter order, its also part of Powershell design. Its really meant to behave as an interface to CLR Objects and even its own cmdlets. So in powershell "scripting" you are less constructing this massively complex list of actions to take, and more putting together a collection of other, smaller pieces of logic, and defining how to interact with them.

    Without getting into a quasi-religious Powershell and OOP discussion, the easiest way to accomplish what you want is to bury all your functions in a separate file (call it functions.ps1) then include that at the beginning.

    So assuming everything was in functions1.ps1

    do a

    $functions = "$($MyInvocation.MyCommand.path | split-path)\functions.ps1"
    . $functions
    

    then

    switch($stepChoice)
    {
        1{Step1}
        2{Step2}
        3{Step3}
    
    }
    

    Would work just fine

    0 讨论(0)
  • 2020-12-29 01:32

    You can also source your function definitions from a separate file:

    Steps-Lib.ps1

    # Since this is just function definitions it is safe to source
    function Step1 { 
        'Step 1' 
        Step2 
    } 
    function Step2 { 
        'Step 2' 
        Step3 
    } 
    function Step3 { 
        'Step 3' 
        'Done!' 
    }
    

    Steps.ps1

    # This sources the Steps-Lib.ps1 so that the functions are available
    . "./Steps-Lib.ps1"
    
    $stepChoice = read-host 'Where would you like to start.'
    
    switch($stepChoice)
    {
        1{Step1}
        2{Step2}
        3{Step3}
    }
    
    0 讨论(0)
  • 2020-12-29 01:36

    Remember that in general, what works in a script should work at the command line.

    This was not true in CMD. GOTO and FOR %I IN (...) DO %%I are two examples.

    In PowerShell, I can run commands at the command line until I get the result I want, then paste the history in to a script, then edit out the extraneous bits.

    Also, I can take a script that isn't working correctly, paste it in to an interactive shell, and study the resulting state.

    At the interactive command line, there's no way you could write this:

    F
    function F { "Hello, World!" }
    

    However, when reading a script, I want to read the top-level code first, and then see more detail as I scroll down. One approach is:

    function Main 
    {
        F
    }
    
    function F
    {
        "Hello, World!"
    }
    
    Main
    
    0 讨论(0)
提交回复
热议问题