Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Powershell and scope

Closed Thread
 
Thread Tools Display Modes
Old 03-30-2007   #1 (permalink)
wkempf
Guest


 

Powershell and scope

about_scope seems to indicate that when you invoke powershell, a new child
scope is created. But it doesn't appear to be a child scope to me, just a
new scope. I have no access to a parent scope.

$foo = "bar"
powershell { write-host $foo }

Is this the proper behavior, and is there any way to get the expected
behavior instead?
Old 03-30-2007   #2 (permalink)
RichS
Guest


 

RE: Powershell and scope

you can use the scope labels of global, local and script. its explained in
about_scope with some examples
--
Richard Siddaway
Please note that all scripts are supplied "as is" and with no warranty
Blog: http://richardsiddaway.spaces.live.com/
PowerShell User Group: http://www.get-psuguk.org.uk


"wkempf" wrote:

> about_scope seems to indicate that when you invoke powershell, a new child
> scope is created. But it doesn't appear to be a child scope to me, just a
> new scope. I have no access to a parent scope.
>
> $foo = "bar"
> powershell { write-host $foo }
>
> Is this the proper behavior, and is there any way to get the expected
> behavior instead?

Old 03-30-2007   #3 (permalink)
Keith Hill
Guest


 

Re: Powershell and scope

"wkempf" <wkempf@discussions.microsoft.com> wrote in message
news:ED57875B-F98F-4337-A4EB-F32177A0C719@microsoft.com...
> about_scope seems to indicate that when you invoke powershell, a new child
> scope is created. But it doesn't appear to be a child scope to me, just a
> new scope. I have no access to a parent scope.
>
> $foo = "bar"
> powershell { write-host $foo }
>
> Is this the proper behavior, and is there any way to get the expected
> behavior instead?


Yep that behavior is expected. By default when you write to a variable that
happens to be defined in a parent scope without using any scope qualifier,
PowerShell creates a "copy on write" value unique to the current scope. If
PowerShell didn't do this then we wind up with essentially global variables
everywhere and it would be a nightmare to maintain/debug.

To work around this, you can specify a different scope for a variable if you
really intend to change the value of the variable in the parent scope. The
two options are $script:<varname> means that the variable can be changed at
the script level. If you are using dot-sourced functions then that doesn't
do you any good. In this case you can use the 'global' scope qualifier to
create truly global variables e.g. $global:__PscxCdBackwardStack.

If you really, really want finer control over which variable is modified in
a parent scope you can use Set-Variable with the -Scope parameter where 1 is
the immediate parent (calling) scope, 2 is that parent's parent, etc.
However for maintainability purposes I do *not* recommend doing this.

--
Keith

Old 04-02-2007   #4 (permalink)
wkempf
Guest


 

Re: Powershell and scope

The scope qualifiers don't make any difference here, and even if it did,
there would be no effect on the example I posted. Changing the scope
qualifier, if powershell created a child scope as the documentation seemed to
indicate, would only change whether or not I could modify the variable. The
example I posted was attempting only to read it.

In any event:

PS> $global:foo = "bar"
PS> powershell { Write-Host $global:foo }
PS> powershell { Write-Host $foo }
PS>

It seems that invoking powershell creates an entirely new scope, not a child
scope. I've found one work around, $env:foo is retained (makes sense).
However, that's not exactly a complete work around to my problem.

"Keith Hill" wrote:

> "wkempf" <wkempf@discussions.microsoft.com> wrote in message
> news:ED57875B-F98F-4337-A4EB-F32177A0C719@microsoft.com...
> > about_scope seems to indicate that when you invoke powershell, a new child
> > scope is created. But it doesn't appear to be a child scope to me, just a
> > new scope. I have no access to a parent scope.
> >
> > $foo = "bar"
> > powershell { write-host $foo }
> >
> > Is this the proper behavior, and is there any way to get the expected
> > behavior instead?

>
> Yep that behavior is expected. By default when you write to a variable that
> happens to be defined in a parent scope without using any scope qualifier,
> PowerShell creates a "copy on write" value unique to the current scope. If
> PowerShell didn't do this then we wind up with essentially global variables
> everywhere and it would be a nightmare to maintain/debug.
>
> To work around this, you can specify a different scope for a variable if you
> really intend to change the value of the variable in the parent scope. The
> two options are $script:<varname> means that the variable can be changed at
> the script level. If you are using dot-sourced functions then that doesn't
> do you any good. In this case you can use the 'global' scope qualifier to
> create truly global variables e.g. $global:__PscxCdBackwardStack.
>
> If you really, really want finer control over which variable is modified in
> a parent scope you can use Set-Variable with the -Scope parameter where 1 is
> the immediate parent (calling) scope, 2 is that parent's parent, etc.
> However for maintainability purposes I do *not* recommend doing this.
>
> --
> Keith
>

Old 04-02-2007   #5 (permalink)
Oisin Grehan
Guest


 

Re: Powershell and scope

On Apr 2, 8:56 am, wkempf <wke...@discussions.microsoft.com> wrote:
> The scope qualifiers don't make any difference here, and even if it did,
> there would be no effect on the example I posted. Changing the scope
> qualifier, if powershell created a child scope as the documentation seemed to
> indicate, would only change whether or not I could modify the variable. The
> example I posted was attempting only to read it.
>
> In any event:
>
> PS> $global:foo = "bar"
> PS> powershell { Write-Host $global:foo }
> PS> powershell { Write-Host $foo }
> PS>
>
> It seems that invoking powershell creates an entirely new scope, not a child
> scope. I've found one work around, $env:foo is retained (makes sense).
> However, that's not exactly a complete work around to my problem.
>
>
>
> "Keith Hill" wrote:
> > "wkempf" <wke...@discussions.microsoft.com> wrote in message
> >news:ED57875B-F98F-4337-A4EB-F32177A0C719@microsoft.com...
> > > about_scope seems to indicate that when you invoke powershell, a new child
> > > scope is created. But it doesn't appear to be a child scope to me, just a
> > > new scope. I have no access to a parent scope.

>
> > > $foo = "bar"
> > > powershell { write-host $foo }

>
> > > Is this the proper behavior, and is there any way to get the expected
> > > behavior instead?

>
> > Yep that behavior is expected. By default when you write to a variable that
> > happens to be defined in a parent scope without using any scope qualifier,
> > PowerShell creates a "copy on write" value unique to the current scope. If
> > PowerShell didn't do this then we wind up with essentially global variables
> > everywhere and it would be a nightmare to maintain/debug.

>
> > To work around this, you can specify a different scope for a variable if you
> > really intend to change the value of the variable in the parent scope. The
> > two options are $script:<varname> means that the variable can be changed at
> > the script level. If you are using dot-sourced functions then that doesn't
> > do you any good. In this case you can use the 'global' scope qualifier to
> > create truly global variables e.g. $global:__PscxCdBackwardStack.

>
> > If you really, really want finer control over which variable is modified in
> > a parent scope you can use Set-Variable with the -Scope parameter where 1 is
> > the immediate parent (calling) scope, 2 is that parent's parent, etc.
> > However for maintainability purposes I do *not* recommend doing this.

>
> > --
> > Keith- Hide quoted text -

>
> - Show quoted text -


Perhaps if you could elaborate on your problem a bit better, we might
be able to offer better help?

Incidentally, I would have thought it would be obvious to most that
invoking a new shell starts with a clean namespace, no? It's a
completely new win32 process/appdomain. Applications of any sort
rarely share information in this way, apart from clusters of
enterprise-level services using named pipes/shared memory. I aint'
never heard of a command-line shell cluster before... ;-)

- Oisin

Old 04-02-2007   #6 (permalink)
Keith Hill
Guest


 

Re: Powershell and scope

"wkempf" <wkempf@discussions.microsoft.com> wrote in message
news:515F015B-0C51-49AE-9D1F-95F318F42588@microsoft.com...
> The scope qualifiers don't make any difference here, and even if it did,
> there would be no effect on the example I posted. Changing the scope
> qualifier, if powershell created a child scope as the documentation seemed
> to
> indicate, would only change whether or not I could modify the variable.
> The
> example I posted was attempting only to read it.
>
> In any event:
>
> PS> $global:foo = "bar"
> PS> powershell { Write-Host $global:foo }
> PS> powershell { Write-Host $foo }
> PS>
>
> It seems that invoking powershell creates an entirely new scope, not a
> child
> scope. I've found one work around, $env:foo is retained (makes sense).
> However, that's not exactly a complete work around to my problem.


My bad. Yes, using env variables, paremeters passed to the new powershell
instance and exporting to clixml (or a generic file) and then reimporting
from the clixml in the new shell is about the only I can think of OTTOMH to
get info into the new shell.

--
Keith

Old 04-02-2007   #7 (permalink)
wkempf
Guest


 

Re: Powershell and scope

Obvious, no, for several reasons:

Traditional shells have an environment that is shared with sub-shells.
Powershell, on the other hand, has a hybrid environment that leads to lots of
"not quite what you'd expect" scenarios, including this one. The traditional
environment, which you can access via the env logical drive, is shared. The
Powershell environment itself, however, is not. Another classic example here
is the "current directory" which is not consistent across the boundaries (the
current directory in PS is not the same current directory known by other
processes, most notably seen when using COM objects).

The documentation, as I stated, seemed to indicate that the powershell
command would create a child scope. I can see how it can be interpreted
multiple ways, so really it's more just unclear than wrong, but still.

Any way, back to specifics. What I'm trying to do is create a script that
behaves much as Powershell itself behaves, but that sets up a specialized
environment for specific tasks. So, invoked by itself I'd wind up in a new
shell ready to invoke commands but the environment will have been modified
for specific needs. If invoked with a script block, it would set up that
specialized environment, run the script block and then exit the sub-shell.

I can't fully implement this idea, and one reason for it is the behavior here.

"Oisin Grehan" wrote:

> On Apr 2, 8:56 am, wkempf <wke...@discussions.microsoft.com> wrote:
> > The scope qualifiers don't make any difference here, and even if it did,
> > there would be no effect on the example I posted. Changing the scope
> > qualifier, if powershell created a child scope as the documentation seemed to
> > indicate, would only change whether or not I could modify the variable. The
> > example I posted was attempting only to read it.
> >
> > In any event:
> >
> > PS> $global:foo = "bar"
> > PS> powershell { Write-Host $global:foo }
> > PS> powershell { Write-Host $foo }
> > PS>
> >
> > It seems that invoking powershell creates an entirely new scope, not a child
> > scope. I've found one work around, $env:foo is retained (makes sense).
> > However, that's not exactly a complete work around to my problem.
> >
> >
> >
> > "Keith Hill" wrote:
> > > "wkempf" <wke...@discussions.microsoft.com> wrote in message
> > >news:ED57875B-F98F-4337-A4EB-F32177A0C719@microsoft.com...
> > > > about_scope seems to indicate that when you invoke powershell, a new child
> > > > scope is created. But it doesn't appear to be a child scope to me, just a
> > > > new scope. I have no access to a parent scope.

> >
> > > > $foo = "bar"
> > > > powershell { write-host $foo }

> >
> > > > Is this the proper behavior, and is there any way to get the expected
> > > > behavior instead?

> >
> > > Yep that behavior is expected. By default when you write to a variable that
> > > happens to be defined in a parent scope without using any scope qualifier,
> > > PowerShell creates a "copy on write" value unique to the current scope. If
> > > PowerShell didn't do this then we wind up with essentially global variables
> > > everywhere and it would be a nightmare to maintain/debug.

> >
> > > To work around this, you can specify a different scope for a variable if you
> > > really intend to change the value of the variable in the parent scope. The
> > > two options are $script:<varname> means that the variable can be changed at
> > > the script level. If you are using dot-sourced functions then that doesn't
> > > do you any good. In this case you can use the 'global' scope qualifier to
> > > create truly global variables e.g. $global:__PscxCdBackwardStack.

> >
> > > If you really, really want finer control over which variable is modified in
> > > a parent scope you can use Set-Variable with the -Scope parameter where 1 is
> > > the immediate parent (calling) scope, 2 is that parent's parent, etc.
> > > However for maintainability purposes I do *not* recommend doing this.

> >
> > > --
> > > Keith- Hide quoted text -

> >
> > - Show quoted text -

>
> Perhaps if you could elaborate on your problem a bit better, we might
> be able to offer better help?
>
> Incidentally, I would have thought it would be obvious to most that
> invoking a new shell starts with a clean namespace, no? It's a
> completely new win32 process/appdomain. Applications of any sort
> rarely share information in this way, apart from clusters of
> enterprise-level services using named pipes/shared memory. I aint'
> never heard of a command-line shell cluster before... ;-)
>
> - Oisin
>
>

Old 04-02-2007   #8 (permalink)
Keith Hill [MVP]
Guest


 

Re: Powershell and scope

"wkempf" <wkempf@discussions.microsoft.com> wrote in message
news:E69705D0-7641-4D76-AA21-013969B5BFC3@microsoft.com...
> Any way, back to specifics. What I'm trying to do is create a script that
> behaves much as Powershell itself behaves, but that sets up a specialized
> environment for specific tasks. So, invoked by itself I'd wind up in a
> new
> shell ready to invoke commands but the environment will have been modified
> for specific needs. If invoked with a script block, it would set up that
> specialized environment, run the script block and then exit the sub-shell.


Take a look at the Export-Console cmdlet. It might help with what you are
trying to accomplish.

export-console -path SpecialConsole.psc1

powershell.exe -PsConsoleFile SpecialConsole.psc1

--
Keith


Old 04-02-2007   #9 (permalink)
wkempf
Guest


 

Re: Powershell and scope

AFAICT, this has diddly squat to do with any PS variables.

PS> $global:foo = "bar"
PS> export-console test.psc1
PS> powershell -psconsole test.psc1 { write-host $foo }
PS> get-content test.psc1
<?xml version="1.0" encoding="utf-8"?>
<PSConsoleFile ConsoleSchemaVersion="1.0">
<PSVersion>1.0</PSVersion>
<PSSnapIns />
</PSConsoleFile>
PS>

Looks like the version and snappins are all that's persisted here.

"Keith Hill [MVP]" wrote:

> "wkempf" <wkempf@discussions.microsoft.com> wrote in message
> news:E69705D0-7641-4D76-AA21-013969B5BFC3@microsoft.com...
> > Any way, back to specifics. What I'm trying to do is create a script that
> > behaves much as Powershell itself behaves, but that sets up a specialized
> > environment for specific tasks. So, invoked by itself I'd wind up in a
> > new
> > shell ready to invoke commands but the environment will have been modified
> > for specific needs. If invoked with a script block, it would set up that
> > specialized environment, run the script block and then exit the sub-shell.

>
> Take a look at the Export-Console cmdlet. It might help with what you are
> trying to accomplish.
>
> export-console -path SpecialConsole.psc1
>
> powershell.exe -PsConsoleFile SpecialConsole.psc1
>
> --
> Keith
>
>
>

Old 04-02-2007   #10 (permalink)
Oisin Grehan
Guest


 

Re: Powershell and scope

On Apr 2, 10:48 am, wkempf <wke...@discussions.microsoft.com> wrote:
> Obvious, no, for several reasons:
>
> Traditional shells have an environment that is shared with sub-shells.


I guess this is where the confusion starts for most beginners to
powershell. Psh is anything but traditional. It might try to give
that "feel," and I guess its doing that job pretty well if people
expect it to behave a certain way and they are misled.

> Powershell, on the other hand, has a hybrid environment that leads to lots of
> "not quite what you'd expect" scenarios, including this one. The traditional
> environment, which you can access via the env logical drive, is shared
> The Powershell environment itself, however, is not. Another classic example here
> is the "current directory" which is not consistent across the boundaries (the
> current directory in PS is not the same current directory known by other
> processes, most notably seen when using COM objects).


Yes, and this is where I see people trip up most with powershell.
Unlike "traditional" shells, there is no implied global location
within powershell. The filesystem is a provider, and is treated
equally to all other providers it exposes. bash/csh/tcl/ksh, tcl,
perl, ruby, python etc all have a single implied current "location" in
the shell. A global "current directory" makes sense for them, because
there is only one context when it comes to a path. In powershell,
there can be multiple current locations, in multiple providers. It
tries not to "special case" the filesystem provider (for the most
part). I also see this in development of cmdlets, people assume path =
filesystem path, that is not always true.

> The documentation, as I stated, seemed to indicate that the powershell
> command would create a child scope. I can see how it can be interpreted
> multiple ways, so really it's more just unclear than wrong, but still.


Where exactly did you read this? "powershell" is not a command (a la
pscmdlet) provided by the shell itself. If you type "powershell," it
is picked up from the envath and invokes a new powershell.exe
process, just like any other win32 executable will be picked up.

I sympathise nonetheless. Powershell is very like, yet completely
unlike any other shell out there. That's what makes it special, and so
utterly loveable once you get stuck in. ;-)

- Oisin

Closed Thread

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Last Post
Is this a bug in the scope? Joel (Jaykul) Bennett PowerShell 1 2 Weeks Ago 11:33 AM
Scope of objects in scripts Alastair French PowerShell 8 02-26-2008 02:10 AM
Variable scope Altraf PowerShell 6 12-13-2007 10:41 AM
trap scope Bob Butler PowerShell 9 10-27-2007 08:41 PM
function scope confusion? William Stacey [C# MVP] PowerShell 1 02-05-2007 02:45 PM








Vistax64.com is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media 2005-2008

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50