22

I have a powershell script that parses a file and send an email if it detects a certain pattern. I have the email code setup inside a function, and it all works fine when I run it from the ISE, but I used PS2EXE to be able to run the script as a service but it does not recognize the function "email". my code looks similar to this

#Do things | 
foreach{
    email($_)
}

function email($text){
    #email $text
}

When I convert it to exe and run it I get this error:

The term 'email' is not recognized as teh 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.
laitha0
  • 4,148
  • 11
  • 33
  • 49
  • I'm not sure why, but powershell was giving me an error based on the casing in the *function* keyword. `function` didn't work, but `Function` (with an uppercase F) did – KyleMit Sep 28 '18 at 20:38
  • 1
    The reason "why" (probably) is, because you ran it TWICE in the Powershell ISE and after the first run the functions where already in the memory (and hence found). Since Keywords (like "function") are NOT case-sensitive, your change didn't matter at all. – Florian Mar 03 '19 at 21:14

2 Answers2

55

Powershell processes in order (top-down) so the function definition needs to be before the function call:

function email($text){
    #email $text
}

#Do things | 
foreach{
    email($_)
}

It probably works fine in the ISE because you have the function definition in memory still from a prior run or test.

JNK
  • 63,321
  • 15
  • 122
  • 138
  • Thank you especially for the mention of ISE, couldn't figure out why it was running the old version after I changed the function! – Amos Baker Aug 03 '21 at 17:00
6

When it comes to the Function-Calls, PowerShell is fairly different from other programming-languages in the following ways:

  1. When passing the arguments to a function, parentheses are NOT allowed (and will raise a parse error if Set-StrictMode is set to -version 2.0 or above/Latest), however, Parenthesised arguments must be used to call a method, which can either be a .NET method or a user defined method (defined within a Class - in PS 5.0 or above).

  2. Parameters are space-separated and not comma separated.

  3. Be careful in where you define the function. As PowerShell sequentially processes line-by-line in top-down order, hence the function must be defied before that function is called:

        Function func($para1){
              #do something
        }
        func "arg1"  #function-call
    

In Windows PowerShell ISE (or Visual Studio Code) if a function-call appears to be working even though the function-definition is defined below the function-call, (beware) this is because it's cached in memory from a previous execution(s), which too will fail as soon as you update the function-definition.

Eddie Kumar
  • 1,216
  • 18
  • 20