Monday, 15 April 2013

Powershell parameter namespace collision -



Powershell parameter namespace collision -

i'm powershell beginner, although not programming n00b. i'm trying create idisposable/raii-style failsafe pattern, sort of in:

http://www.sbrickey.com/tech/blog/post/idisposable_in_powershell

so have:

function global:failsafeguard { param ( [parameter(mandatory=$true)] [scriptblock] $execute, [parameter(mandatory=$true)] [scriptblock] $cleanup ) seek { &$execute } { &$cleanup } }

i'm trying utilize perform bunch of tasks in different directory, using push-location on way in , pop-location on way out. have:

function global:push-location-failsafe { param ( $location, [scriptblock] $execute ) failsafeguard { push-location $location; &$execute } { pop-location } }

i find $execute param in push-location-failsafe collides $execute param in failsafe function.

push-location-failsafe "c:\" {dir} look after '&' in pipeline element produced invalid object. must result in command name, script block or commandinfo object. @ c:\temp\b807445c-1738-49ff-8109-18db972ab9e4.ps1:line:20 char:10 + &$ <<<< execute

the reason think it's name-collision if rename $execute $execute2 in push-location-failsafe, works fine:

push-location-failsafe "c:\" {dir} directory: c:\ mode lastwritetime length name ---- ------------- ------ ---- d---- 2011-08-18 21:34 cygwin d---- 2011-08-17 01:46 dell [snip]

what's wrong in understanding of parameters?

your problem scriptblocks , how handle variables. variables within scriptblock doesn't expand until executed. because of hitting loop. allow me show you:

when phone call push-location-failsafe method variable this:

[dbg]: ps c:\>> (get-variable execute).value dir

but phone call inner function failsafeguard, $execute variable changes this:

[dbg]: ps c:\>> (get-variable execute).value push-location $location; & $execute

now when you're try { } block starts executing, begins expand variables. when expands $execute this:

try { push-location $location; & $execute }

then expands $execute again. seek block now:

try { push-location $location; & { push-location $location; & $execute } }

and got infinite loop caused recursion. prepare this, can expand $execute variable within string, create scriptblock out of. this:

function global:push-location-failsafe { param ( $location, [scriptblock] $execute ) failsafeguard ([scriptblock]::create(" push-location $location; & $execute")) { pop-location } }

be aware particular solution have problem when $execute includes variables inside. e.g.: $execute = { $h = dir } because seek expand $h when creates scriptblock.

an easier , improve way solve utilize different variablenames there's no collision in first place :-)

powershell

No comments:

Post a Comment