问题
Background: I've been writing a powershell script to migrate files from a Sharpoint 2010 instance on Windows Server '08 (with Powershell 2.x) to a Sharepoint 2013 instance on Windows Server '12 (with Powershell 3.x). I have that working but I noticed a change in how scope is handled.
Issue: I have the following code that gets run on both PSSessions ($param
is a hashtable of parameter values)
Invoke-Command -session $Session -argumentlist $params -scriptblock `
{
Param ($in)
$params = $in # store parameters in remote session
# need to run with elevated privileges to access sharepoint farm
# drops cli stdout support (no echo to screen...)
[Microsoft.SharePoint.SPSecurity]::RunWithElevatedPrivileges(
{
# start getting the site and web objects
$site = get-spsite($params["SiteURL"])
})
}
I noticed that in the PS 2.x remote session that assigning to $site
also assigned to the same variable in Invoke-Command
's scope, i.e. either scope gets passed or they share the same scope. BUT in the PS 3.x remote session assigning to $site
does not change the value in Invoke-Command
(true child scope).
My Solution: I wrote a function to compute the correct scope on each server which it calls and then uses the return value as an input to Get-Variable
and Set-Variable
's -Scope
option. This solved my problem and allows assignment and access of the variables.
Function GetCorrectScope
{
# scoping changed between version 2 and 3 of powershell
# in version 3 we need to transfer variables between the
# parent and local scope.
if ($psversiontable.psversion.major -gt 2)
{
$ParentScope = 1 # up one level, powershell version >= 3
}else
{
$ParentScope = 0 # current level, powershell version < 3
}
$ParentScope
}
The Question: Where, if anywhere, is this documented by Microsoft? (I couldn't find it in about_scope on TechNet, which says it applies to both 2.x and 3.x and is the standard reference I've seen in other questions).
Also, is there a better/proper way to do this?
回答1:
It is documented in the WMF 3 Release Notes in the section "CHANGES TO THE WINDOWS POWERSHELL LANGUAGE".
Script blocks executed as delegates run in their own scope
Add-Type @"
public class Invoker
{
public static void Invoke(System.Action<int> func)
{
func(1);
}
}
"@
$a = 0
[Invoker]::Invoke({$a = 1})
$a
Returns 1 in Windows PowerShell 2.0
Returns 0 in Windows PowerShell 3.0
来源:https://stackoverflow.com/questions/18515186/undocumented-changes-to-powershell-scope-handling-v2-v3