TomG
TomG

Reputation: 291

Modifying variable in parent script using child script in powershell

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

Answers (2)

mklement0
mklement0

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

Manuel Batsching
Manuel Batsching

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

Related Questions