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

What is the scope of function declarations?

Update your Vista Drivers Update Your Drivers Now!!
Closed Thread
 
Thread Tools Display Modes
Old 05-10-2008   #1 (permalink)
Richard-Maw
Guest


 

What is the scope of function declarations?

I was writing a script to mimic T4 template transformation. I wanted to
handle any errors executing a block - I tried something like:

$scriptblock = 'function Assign { $script:y = 1;}'
try {
$ExecutionContext.InvokeCommand.InvokeScript( $scriptblock )
} -catch {
"blah blah"
}

This was based on page 247 of Bruce Payette’s book where he says that the
Invoke-Script method does the same thing as invoke-expression. And it was
also based on Adam Weigert’s Powershell function that mimics the syntax of a
try/catch block in C#.
(http://weblogs.asp.net/adweigert/arc...s-to-life.aspx).

What I noticed was that function definitions failed to work. In turns out,
for one thing, that there is an interesting difference between InvokeScript
and Invoke-expression. Consider:

$ExecutionContext.InvokeCommand.InvokeScript("function fun1 { 'have fun'}" )
fun1
The term 'fun1' is not recognized as a cmdlet, function, operable program,
or script file. Verify the term and try again.
At line:1 char:4
+ fun1 <<<<

However, using invoke-expression:
Quote:

>invoke-expression("function fun1 { 'have fun'}")
>fun1
have fun

As for the try/catch function, C# programmers might be caught out by the
following:

$x = 1
try { $x = 2 } -catch { "fail" }
$x
1

It turns out you need to specify the scope to affect the outer context:

$x = 1
try { $script:x = 2 } -catch { "fail" }
$x
2

However, trying to define a function in one of these try blocks:

try {
function fun3 { 'have yet more fun'}
} -catch { "or not" }
fun3
The term 'fun3' is not recognized as a cmdlet, function, operable program,
or script file. Verify the term and try again.
At line:1 char:4
+ fun3 <<<<

As far as I know there is no equivalent to setting the scope of the
function. I would have expected the function to be added to the “function
drive.”

So what I originally wrote turned out to be doubly wrong. Both the
InvokeScript method and the try context caught me out. What works is:

$scriptblock = 'function GoodFun { "Excellent" }'
trap {"blah blah"; continue;} invoke-expression( $scriptblock )
GoodFun
Excellent

$scriptblock = 'function BadFun { $bad one }'
trap {"blah blah"; continue;} invoke-expression( $scriptblock )
blah blah

But I don’t really understand what was wrong with the original.

As it stands I’m leaving out the trap until I’m sure I can do a better job
of error reporting than the default Powershell behavior. If you want to see
the full context my T4-like Powershell template processing it is posted at
http://richard-maw.spaces.live.com/b...3CE5!135.entry.

--
Richard Maw

My System SpecsSystem Spec
Old 05-11-2008   #2 (permalink)
Keith Hill [MVP]
Guest


 

Re: What is the scope of function declarations?

"Richard-Maw" <rmaw@xxxxxx-No.Spam> wrote in message news:70209E84-18D2-4FBD-B1FB-082A99D3F3AC@xxxxxx
Quote:

> As far as I know there is no equivalent to setting the scope of the
> function. I would have expected the function to be added to the “function
> drive.”
Functions are scoped similar to variables. That is the contents of the variable drive differ depending on which scope you are in. Same goes for the Function drive. For example:

2> function foo { function bar { "bar" } "foo calling $(bar)" }
3> foo
foo calling bar
4> ls Function:\foo

CommandType Name Definition
----------- ---- ----------
Function foo function bar { "bar" } "foo calling $(bar)"

5> ls Function:\bar
Get-ChildItem : Cannot find path 'bar' because it does not exist.
At line:1 char:4
+ dir <<<< Function:\bar

6> function foo { function bar { "bar" } "foo calling $(bar)"; ls function:\bar }
7> foo
foo calling bar

CommandType Name Definition
----------- ---- ----------
Function bar "bar"

--
Keith
My System SpecsSystem Spec
Old 05-11-2008   #3 (permalink)
Richard-Maw
Guest


 

Re: What is the scope of function declarations?

Thanks for your reply.

That gives me an idea as to what might be going on with invoke-expression.
Your example of functions within functions seems a bit of a different case
but I guess it all involves script blocks.

With variables you can define and reference them in an outer scope using
$script: or $global:. Would I be right in thinking this kind of facility is
not available for functions?
My System SpecsSystem Spec
Old 05-11-2008   #4 (permalink)
Kiron
Guest


 

Re: What is the scope of function declarations?

In the following examples Global and Script terms are equivalent, because the commands are executed interactively, don't mean to confuse you. Function, as Variables, can be declared with a scope definition.
For more on scope, function and scriptBlock:

help about_scope
help about_function
help about_sript_block

Try this code, examples are better explanations

# delete function Assign if exists
if ($function:Assign) {
ri function:Assign
}
$y = 0

# declare a function in a scriptBlock
&{function Assign {$script:y = 3}}

try {Assign} catch {
write-warning `
'errors because there is not an Assign function in Global/Script scope'
}

# $y is unaffected
$y

# set the function's scope to Script making it available in the
# scriptBlock's parent scope
&{function script:Assign {$script:y = 3}}
Assign
$y

# you can also dot-source the sriptBlock to make Assign available
.{function Assign {$script:y = 7}}
Assign
$y

# when using the InvokeScript method the command is executed in a lower
# scope and $y in the console's scope is not affected
$ExecutionContext.InvokeCommand.InvokeScript('$y = 11')
$y

# to affect $script:y change the scope of the variable
$ExecutionContext.InvokeCommand.InvokeScript('$script:y = 11')
$y

# or...
$ExecutionContext.InvokeCommand.InvokeScript('set y 15 -scope 1')
$y

# set the function's scope to Script so its available in the
# scriptblock's parent scope, in this case the console
$scriptblock = 'function script:Assign { $script:y = 1}'

try {
$ExecutionContext.InvokeCommand.InvokeScript($scriptblock)
} catch {
"blah blah"
}
Assign
$y

$ExecutionContext.InvokeCommand.InvokeScript("function script:fun1 {'have fun'}" )
fun1

# no need to specify $x's scope in the Try block
$x = 1
try { $x = 2 } catch { "fail" }
$x

# works fine
try {
function fun3 { 'have yet more fun'}
} catch { "or not" }
fun3

--
Kiron
My System SpecsSystem Spec
Old 05-11-2008   #5 (permalink)
Richard-Maw
Guest


 

Re: What is the scope of function declarations?

Thanks for a very complete answer to my question. I'm still digesting all the
information but I think you have covered everything.
My System SpecsSystem Spec
Old 05-11-2008   #6 (permalink)
Keith Hill [MVP]
Guest


 

Re: What is the scope of function declarations?

"Richard-Maw" <rmaw@xxxxxx-No.Spam> wrote in message news:8B11C801-DC9F-4255-97BB-099D3F6008C3@xxxxxx
Quote:

> Thanks for your reply.
>
> That gives me an idea as to what might be going on with invoke-expression.
> Your example of functions within functions seems a bit of a different case
> but I guess it all involves script blocks.
>
> With variables you can define and reference them in an outer scope using
> $script: or $global:. Would I be right in thinking this kind of facility is
> not available for functions?
The global/script/local/private modifiers only seem to be usable on variables. However you can overwrite at the global level like so:

142> function foo { "I'm foo" }
143> function bar { `
Quote:
Quote:

>> new-item function:\ -type Function -Name foo `
>> -Value { "I was foo until bar changed me" } -Force
>> }
>>
144> foo
I'm foo
145> bar

CommandType Name Definition
----------- ---- ----------
Function foo "I was foo until bar changed me"


146> foo
I was foo until bar changed me

--
Keith
My System SpecsSystem Spec
Old 05-11-2008   #7 (permalink)
Keith Hill [MVP]
Guest


 

Re: What is the scope of function declarations?

"Richard-Maw" <rmaw@xxxxxx-No.Spam> wrote in message news:8B11C801-DC9F-4255-97BB-099D3F6008C3@xxxxxx
Quote:

> Thanks for your reply.
>
> That gives me an idea as to what might be going on with invoke-expression.
> Your example of functions within functions seems a bit of a different case
> but I guess it all involves script blocks.
>
> With variables you can define and reference them in an outer scope using
> $script: or $global:. Would I be right in thinking this kind of facility is
> not available for functions?
Doh! You *can* use those modifiers (global,script,local,private) on functions like so:

147> function foo { "I'm foo" }
148> function bar { function global:foo { "I was foo until bar changed me" } }
149> foo
I'm foo
150> bar
151> foo
I was foo until bar changed me

--
Keith
My System SpecsSystem Spec
Old 05-11-2008   #8 (permalink)
Kiron
Guest


 

Re: What is the scope of function declarations?

Glad to help Richard.
You may find this blog post from Jeffrey Snover (PowerShellTeam) useful:
Controlling the Scope of Variables
http://blogs.msdn.com/powershell/arc...variables.aspx

--
Kiron
My System SpecsSystem Spec
Old 05-11-2008   #9 (permalink)
Richard-Maw
Guest


 

Re: What is the scope of function declarations?

That's really interesting. I'll play around with that. Thanks!
--
Richard Maw


"Keith Hill [MVP]" wrote:
Quote:

> "Richard-Maw" <rmaw@xxxxxx-No.Spam> wrote in message
> news:8B11C801-DC9F-4255-97BB-099D3F6008C3@xxxxxx
Quote:

> > Thanks for your reply.
> >
> > That gives me an idea as to what might be going on with
> invoke-expression.
Quote:

> > Your example of functions within functions seems a bit of a different
> case
Quote:

> > but I guess it all involves script blocks.
> >
> > With variables you can define and reference them in an outer scope using
> > $script: or $global:. Would I be right in thinking this kind of facility
> is
Quote:

> > not available for functions?
>
> Doh! You *can* use those modifiers (global,script,local,private) on
> functions like so:
>
> 147> function foo { "I'm foo" }
> 148> function bar { function global:foo { "I was foo until bar changed
> me" } }
> 149> foo
> I'm foo
> 150> bar
> 151> foo
> I was foo until bar changed me
>
> --
> Keith
>
My System SpecsSystem Spec
Old 05-11-2008   #10 (permalink)
Richard-Maw
Guest


 

Re: What is the scope of function declarations?

I'll check it out - tx
--
Richard Maw


"Kiron" wrote:
Quote:

> Glad to help Richard.
> You may find this blog post from Jeffrey Snover (PowerShellTeam) useful:
> Controlling the Scope of Variables
> http://blogs.msdn.com/powershell/arc...ing-the-scope-
> of-variables.aspx
>
> --
> Kiron
>
My System SpecsSystem Spec
Closed Thread

Thread Tools
Display Modes



Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: help needed converting c# array declarations to work inpowershell Oisin (x0n) Grehan [MVP] PowerShell 0 06-04-2008 08:00 AM
Using variable XPaths in Style declarations muchinger Avalon 0 10-25-2007 07:48 AM
Using a function to setup objects properties with scope of script Frank PowerShell 2 04-16-2007 11:45 AM
function scope confusion? William Stacey [C# MVP] PowerShell 1 02-05-2007 02:45 PM
Connecting a C# code behind file to the declarations of controlsin XAML. Jason Dolinger Avalon 2 01-10-2006 03:52 PM


Update your Vista Drivers Update Your Vista Drivers Now!!

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