Reputation: 1423
The help document says that the script will be executed in 'dot-sourced' mode, but it doesn't. why?
I read the full text of the help document and couldn't find the reason, so I came for help.
PS> PowerShell.exe -File '.\dot-source-test.ps1'
PS> $theValue
PS> . '.\dot-source-test.ps1'
PS> $theValue
theValue
PS>
The content of 'dot-source-test.ps1' is $theValue = 'theValue'
.
If the value of File is a file path, the script runs in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session.
about_PowerShell_exe - PowerShell | Microsoft Docs
Upvotes: 3
Views: 4707
Reputation: 438198
To prevent conceptual confusion:
In order to dot-source a script, i.e. execute it directly in the caller's scope (as opposed to a child scope, which is the default), so that the script's variables, function definitions, ... are seen by the caller:
In the current PowerShell session, just use .
, the dot-sourcing operator, directly:
# Dot-source in the caller's scope.
# When executed at the prompt in an interactive PowerShell session,
# the script's definitions become globally available.
. '.\dot-source-test.ps1'
Via powershell.exe
, the Windows PowerShell CLI[1]:
Note: Whatever dot-sourcing you perform this way is limited to the child process in which powershell.exe
runs and its PowerShell session; it has no impact on the caller's session.
Dot-sourcing via the CLI makes sense only in two scenarios:
Scenario A: You're passing commands via the (possibly positionally implied) -Command
(-c
) parameter that relies on definitions that must first be dot-sourced from a script file, and you want the session to exit automatically when the commands have finished executing.
Scenario B: You're entering a (possibly nested) interactive PowerShell session into which you want to dot-source (pre-load) definitions from a script file; as any interactive session, you will need to exit it manually, typically with exit
.
Scenario A: Pre-load definitions, execute commands that rely on them, then exit:
The following starts a (new) PowerShell session as follows:
Script file .\dot-source-test.ps1
is dot-sourced, which defines variable $theValue
in the caller's (here: the global) scope.
The value of $theValue
is output.
The new session is automatically exited on completing the commands.
PS> powershell -c '. .\dot-source-test.ps1; $theValue'
theValue
Scenario B: Enter a (new) interactive session with pre-loaded definitions:
Simply add the -noexit
switch in order to enter an interactive session in which script file .\dot-source-test.ps1
has been dot-sourced:
powershell -noexit -c '. .\dot-source-test.ps1'
# You're now in a (new) interactive session in which $theValue is defined,
# and which you must eventually exit manually.
Note:
If neither -File
nor a command (via explicit or implied -Command
/ -c
) are specified, -noexit
is implied.
Because -c
is needed here for dot-sourcing, -noexit
must be specified to keep the session open.
While using -File
for dot-sourcing instead - powershell -noexit -File '.\dot-source-test.ps1'
- works too, I suggest avoiding it for conceptual reasons:
While it is technically true that a script passed to -File
is dot-sourced in the new session, that is (a) unexpected, given that scripts executed from inside a session are not (they run in a child scope) and (b) by far the most typical use case for -File
is to execute a given script and then exit - in which case the aspect of dot-sourcing is irrelevant.
As such, it is better to think of this behavior as an implementation detail, and it is unfortunate that the CLI help mentions it so prominently - causing the confusion that prompted this question.
[1] The same applies analogously to the PowerShell [Core] 7+ CLI, pwsh
, except that it defaults to -File
rather than -Command
.
Upvotes: 7
Reputation: 472
It's about the way the path to the file is passed through the command line. See the below example when used in Command Prompt. (test.ps1 contains the line $theValue = 'theValue'
)
Without using the "-File" toggle, it's treated differently, as an argument to be passed to the PowerShell process being triggered.
Seeing the same thing when calling in PowerShell.
The specific part you reference is under the " -File" toggle, which needs to be used.
If the value of File is "-", the command text is read from standard input. Running powershell -File - without redirected standard input starts a regular session. This is the same as not specifying the File parameter at all.
If the value of File is a file path, the script runs in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session.
(source: Microsoft Docs > About PowerShell.exe)
Upvotes: 2