Reputation: 291
I have two powershell scripts. I have to assign the parent variable using child script The child powershell script is called using parent powershell script
parent.ps1
$count = $Null
child.ps1
$count = 10
How do I make sure that the change in child script gets reflected in parent script?
Upvotes: 1
Views: 1810
Reputation: 437718
Manuel Batsching's answer shows you how to use dot-sourcing to solve your problem indirectly: by executing the child script directly in the parent script's scope, all of the child script's (script-level) variables (among other definitions, namely functions and aliases) are created directly in the parent script's scope, which may be undesirable.
PowerShell does offer mechanisms to selectively modify variables in other scopes, but it's best to avoid them, because you're creating a tight coupling between your scripts that makes them difficult to maintain; instead, use other mechanism to communicate information between your scripts, in the simplest form via output.
If you still want to solve your problem by modifying a variable in the parent scope, you can use the following:
# When run in child.ps1 that was invoked (normally) by parent.ps1,
# sets $count to 1 in the scope of *parent.ps1*.
Set-Variable -Scope 1 -Name count -Value 10
Scope -1
refers to the parent scope of the calling scope (2
would refer to the grandparent scope, and so on) - see Set-Variable
.
Complementarily, scope modifiers $script:
and $global:
may be used with variable names to target variables in the (same) script scope and the global scope (for instance, $script:foo = 'bar'
could be used to set a script-level variable from inside of a function defined in the same script; creating or modifying global variables should be avoided, as they linger even after a script exits) - see about_Scopes
.
For the sake of completeness:
Scope modifier $local:
allows you to refer to the current (local) scope explicitly; it is rarely used, because the current scope is implied when you assign to a variable by mere name (e.g., $foo = 'bar'
creates a local $foo
variable).
However, on getting a variable $local:foo
isn't necessarily the same as just $foo
: due to PowerShell's dynamic scoping, $foo
returns the value of a variable in an ancestral scope, if any, if no such variable exists in the current scope; by contrast, $local:foo
strictly returns the value of a variable by that name in the current scope, if defined there.
To suppress dynamic scoping for a given variable, i.e. to prevent descendant scopes from seeing it (by default), create it with the $private:
scope modifier.
See this answer for more information about PowerShell's dynamic scoping and the $private:
scope.
Scope modifier $using:
is used in the context of remoting and jobs; it doesn't actually reference a variable per se in the caller's context, but its value - see about_Remote_Variables
.
Upvotes: 2
Reputation: 3596
By using the dot sourcing operator .
you can run your child.ps1 script in the same scope as your parent.ps1 script. That will preserve all changes to variables, that your child script does (see: script scope and dot sourcing).
Let the content of your parent.ps1 be like:
$count = $null
. .\child.ps1
$count
This will return 10
.
Upvotes: 2