21

I am really fond of python's capability to do things like this:

if __name__ == '__main__':
    #setup testing code here
    #or setup a call a function with parameters and human format the output
    #etc...

This is nice because I can treat a Python script file as something that can be called from the command line but it remains available for me to import its functions and classes into a separate python script file easily without triggering the default "run from the command line behavior".

Does Powershell have a similar facility that I could exploit? And if it doesn't how should I be organizing my library of function files so that i can easily execute some of them while I am developing them?

mklement0
  • 382,024
  • 64
  • 607
  • 775
Mark Mascolino
  • 2,227
  • 1
  • 15
  • 19

4 Answers4

8

$MyInvocation.Invocation has information about how the script was started.

If ($MyInvocation.InvocationName -eq '&') {
    "Called using operator: '$($MyInvocation.InvocationName)'"
} ElseIf ($MyInvocation.InvocationName -eq '.') {
    "Dot sourced: '$($MyInvocation.InvocationName)'"
} ElseIf ((Resolve-Path -Path $MyInvocation.InvocationName).ProviderPath -eq $MyInvocation.MyCommand.Path) {
    "Called using path: '$($MyInvocation.InvocationName)'"
}
Bacon Bits
  • 30,782
  • 5
  • 59
  • 66
6

$MyInvocation has lots of information about the current context, and those of callers. Maybe this could be used to detect if a script is being dot-sourced (i.e. imported) or executed as a script.

A script can act like a function: use param as first non-common/whitespace in the file to defined parameters. It is not clear (one would need to try different combinations) what happens if you dot-source a script that starts param...

Modules can directly execute code as well as export functions, variables, ... and can take parameters. Maybe $MyInvocation in a module would allow the two cases to be detected.

EDIT: Additional:

$MyInvocation.Line contains the command line used to execute the current script or function. Its Line property has the scrip text used for the execution, when dot-sourcing this will start with "." but not if run as a script (obviously a case to use a regex match to allow for variable whitespace around the period).

In a script run as a function

Richard
  • 106,783
  • 21
  • 203
  • 265
  • So something along the lines of: if (! $MyInvocation.Line.Trim().StartsWith(". ")) { #Scripty type invocation happens here } – Mark Mascolino Jan 14 '11 at 18:59
  • @MarkMascolino: after a quick test, can have `.script`, not just a space. I would use `-match '^\s+\.\s+'`. – Richard Jan 14 '11 at 23:17
2

As of now I see 2 options that work

if ($MyInvocation.InvocationName -ne '.') {#do main stuff}

and

if ($MyInvocation.CommandOrigin -eq 'Runspace') {#do main stuff}
esac
  • 24,099
  • 38
  • 122
  • 179
1

Disclaimer: This is only tested on Powershell Core on Linux. It may not work the same for Windows. If anyone tries it on Windows I would appreciate if you could verify in the comments.

function IsMain() {
  (Get-Variable MyInvocation -Scope Local).Value.PSCommandPath -Eq (Get-Variable MyInvocation -Scope Global).Value.InvocationName
}

Demonstrated with a gist

nathanchere
  • 8,008
  • 15
  • 65
  • 86