Reputation: 32192
I have a function written in PowerShell:
function replace([string] $name,[scriptblock] $action) {
Write-Host "Replacing $name"
$_ = $name
$action.Invoke()
}
and would be used as:
$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
(cat templates\buildAgent.dist.properties.tpl) `
-replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
-replace '@@name@@', $name `
> $_
}
However I've discovered that within the scriptblock the variable $name
is overwritten by the $name
param from within the replace
function.
Is there a way to execute the script block so that only the variable $_
is added to the scope of the scriptblock but nothing else is?
Upvotes: 1
Views: 818
Reputation: 32192
I preface my answer by claiming that powershell is only for sadists. The trick is that if you put the function into a module the local variables become private and are not passed to the script block. Then to pass in the $_
variable you have to jump some more hoops.
The gv '_'
get's the powershell variable $_
and passes it to the context via InvokeWithContext
.
Now I know more than I ever wanted to :|
New-Module {
function replace([string] $name,[scriptblock] $action) {
Write-Host "Replacing $name"
$_ = $name
$action.InvokeWithContext(@{}, (gv '_'))
}
}
and as before
$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
(cat templates\buildAgent.dist.properties.tpl) `
-replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
-replace '@@name@@', $name `
> $_
}
Upvotes: 1
Reputation: 58981
You could use the $global:
prefix for the $name
variable within your scriptblock:
$name = "tick"
replace $agentPath\conf\buildAgent.dist.properties {
(cat templates\buildAgent.dist.properties.tpl) `
-replace '@@serverurl@@', 'http:/localhost:8080/teamcity' `
-replace '@@name@@', $global:name `
> $_
}
Upvotes: 0