Partager via


管理沙箱方案的升級

管理沙箱方案的升級

本文:

沙箱方案是 SharePoint 2010 平台的一項強大功能。  不過由於這些方案是部署在伺服器陣列或網站集合的不同位置上,所以不免有管理上的問題。

我們提供了 PowerShell 指令碼,幫助您處理這個問題。  這個指令碼很簡單,不過可以擴大延伸,為您處理更多工作,以配合現行工具,來管理伺服器陣列及網站集合。

此指令碼所處理的事項如下: 

您部署的每個方案都有個相關聯的方案識別碼。  在該方案內,有一或多個功能具有功能識別碼及版本編號。   此指令碼會針對特定方案識別碼,巡查整個伺服器或網站集合,然後產生記錄檔,讓您知道該方案所在的所有位置。  接著,此指令碼會查看方案中的每個功能,並在記錄檔中新增記錄項目,表示部署的是該功能哪個版本。  若有提供該方案的新版本,此指令碼還會執行升級。  指令碼會認出此標幟,然後執行升級,或進行方案資訊收集。

此指令碼所用的參數如下:

·         要升級的檔案路徑及方案名稱 (.wsp 檔案)。

·         表示是否應執行升級的切換參數

權限:

·         指令碼會假設其執行者為沙箱管理員,並允許該管理員執行升級動作。

·         權限等級會修改成授與「完全控制」,以供該管理員使用。

·         完成升級之後,權限會還原成原始設定。

記錄檔格式如下:

·         詳列您所檢查之方案的檔案路徑及方案名稱 (也包括方案識別碼)。

·         提供每個所檢查的網站集合詳細資訊。

·         針對每個網站集合

o   提供關於是否找到相符方案的資訊

o   若找到相符方案,則提供正在移除的方案檔案詳細資訊,如此即可取代成新版本。

o   若正在執行升級,則提供升級成功或失敗的詳細資訊

·         摘要資訊包括

o   所檢查的網站集合個數

o   若未正在執行升級,則會有一份摘要清單列出需要升級的網站,及方案中每個功能 (識別碼) 的目前版本詳細資訊。

o   若已經執行升級,則提供功能及版本資訊,外加成功升級、成功新增安裝或功能保持不變 (因為已為最新版本) 的詳細資訊。

有幾點須注意:

若要對方案進行升級,SharePoint 2010 平台要求方案改用不同名稱。  如果新舊版方案檔案名稱相同,系統會顯示錯誤,表示該方案已在使用中。  進行方案升級時,系統會使用方案識別碼找出該方案現有版本,然後請查看版本詳細資訊。  升級作業只會升級到新版本,  並不能回復成舊版本。  如果版本都一樣,此指令碼就不會執行任何動作。

希望此指令碼可協助您管理所部署的方案,並更輕鬆地進行升級。

# SharePoint DLL

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint")

 

#Cmdlet Install

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

 

#Log file definition

$intro = "User Solution Upgrader v1.0 - Log File"

$date = (Get-Date).ToString('yyyyMMdd')

 

Set-Variable -Name ForReading -value 1 -Option Constant

Set-Variable -Name ForWriting -value 2 -Option Constant

Set-Variable -Name ForAppending -value 8 -Option Constant

 

#Assume that the current "Domain\User" is the box admin entitled to perform the reconaissance and upgrade actions.

$admin  = $env:UserDomain + "\" + $env:UserName

if ($env:UserDomain -eq $null)

{             

                $admin = $admin.substring(1)

}

 

# Get the script's parent folder. This is where the log file will be written.

$logFolder = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

$getACL = Get-Acl $logFolder

$access = $getACL.Access | Where { $_.IdentityReference -eq $admin }

if ($access -eq $null -or

    ($access.FileSystemRights -ne [System.Security.AccessControl.FileSystemRights]::FullControl -and

     ($access.FileSystemRights -ne [System.Security.AccessControl.FileSystemRights]::Write -and

      $access.FileSystemRights -ne [System.Security.AccessControl.FileSystemRights]::CreateFiles)))

{

                $logFolder = $env:userprofile

}

 

# Add the log file name to the path.

$logFileFullPath = Join-Path $logFolder "usersolutionupgrader-$date.txt"

 

# Open file

$fo = New-Object -com Scripting.FileSystemObject

$f = $fo.OpenTextFile($logFileFullPath, $ForAppending, $true)

 

if ($f -eq $null)

{

                $logFolder = $env:userprofile

                $logFileFullPath = Join-Path $logFolder "usersolutionupgrader-$date.txt"

                $f = $fo.OpenTextFile($logFileFullPath, $ForAppending, $true)

}

 

#Confirm log file on screen

Write-Host ("Log Path: " + $logFileFullPath)

 

#Write intro line

$f.WriteLine()

$f.WriteLine($intro)

 

function WriteLog

{

                $dt = Get-Date

                $logMsg = $dt.ToShortDateString() + "  " + $dt.ToShortTimeString() + "`t" + $args[0]

                $f.WriteLine($logMsg)

                Write-Output($logMsg)  #Turn this on when you need console output

}

 

function exitScript()

{

                if ($f -ne $null)

                {

                                $f.Close()

                }

                Write-Host "Exiting script due to error."

                exit

}

 

WriteLog ("Current user (admin):   $admin")

 

#solution details

$solFile = ""

$targetSolutionId = ""

$upgrade = $false

$myError = $null

 

$haveCurrentFeatures = $false

$haveNewFeatures  = $false

$numSites = 0

$oldFeatures = @{}

$newFeatures = @{}

$solSites = New-Object System.Collections.ArrayList

$solFailSites = New-Object System.Collections.ArrayList

 

#Parse the commandline parameters

if (($args -eq $null) -or ($args.Count -lt 2))

{

                WriteLog("Error: This script has been called without enough parameters. Listing your parameters below:")

                WriteLog($args)

                if ($f -ne $null)

                {

                                $f.Close()

                }

                exitScript

}

else

{

                $badParameters = $false

                foreach ($arg in $args)

                {

                                switch ($arg)

                                {

                                                "-upgrade"  {$upgrade = $true}

                                                "-path" {[void] $foreach.MoveNext(); $solFile = $foreach.Current}

                                                default {$badParameters = $true}

                                }

                }

 

                if ($badParameters -eq $true)

                {

                                WriteLog("You passed in a bad parameter.")

                                exitScript

                }                             

 

                #Validate parameters

                $extension = [IO.Path]::GetExtension($solFile)

                if (($extension -eq $null) -or ($extension -ne ".wsp") -or (!(Test-Path $solFile)))

                {

                                WriteLog("Error: The solution file name is not of WSP format or is an invalid file.")

                                exitScript

                }

 

                #Confirm parameter values captured

                $fileName = Split-Path $solFile -Leaf

                WriteLog("Solution Path is: `t" + $solFile)

                WriteLog("Solution Name is: `t" + $fileName)

                if ($upgrade)

                {

                                WriteLog "The tool will attempt to perform UPGRADE on the site collections"

                }

                WriteLog ""

}

 

#Get solution ID from given WSP

$tempPath = Join-Path $env:temp "upgrader" | Join-Path -ChildPath $fileName

$shell = New-Object -ComObject "Shell.Application" -ErrorAction:SilentlyContinue -ErrorVariable myError

if ($myError -ne $null)

{

                WriteLog("FAILED to create the Shell.Application object.")

                WriteLog("Error: " + $myError)

                $myError = $null

}

 

[IO.Directory]::CreateDirectory($tempPath)  | Out-Null

$tempFolder = $shell.NameSpace($tempPath)

$tempFolder.CopyHere($solFile)

 

#Take the file name ("yourfile.wsp") from the original path

$tempSolPath = Join-Path $tempPath $fileName

 

if (!(Test-Path $tempSolPath))

{

                WriteLog "Error: Failed to copy WSP file to temp location."

                exitScript

}

 

#Rename the WSP file to have CAB extension in order to facilitate CAB extraction

$cabFileName = [System.IO.Path]::GetFileNameWithoutExtension($fileName) + ".cab"

 

Rename-Item $tempSolPath $cabFileName

$cabPath = Join-Path $tempPath $cabFileName

 

$sourceWsp = $shell.NameSpace($cabPath).items()

$tempFolder.CopyHere($sourceWsp)

$manifestPath = Join-Path $tempPath "manifest.xml"

[xml]$manifest = Get-Content $manifestPath

$targetSolutionId = $manifest.Solution.SolutionId

 

#Validate Solution GUID

[Guid]$testGuid = "B80D56EC-5899-459d-83B4-1AE0BB8418E4"

if (($targetSolutionId -eq $null) -or ($targetSolutionId.Length -lt 36) -or

    ([System.ComponentModel.TypeDescriptor]::GetConverter($testGuid).ConvertFromString($targetSolutionId) -eq $null))

{

                WriteLog("Error: Target solution ID is invalid: " + $stringSolutionId)

                exitScript

}

 

WriteLog("Extracted solution ID: $targetSolutionId from manifest.xml")

WriteLog("")

 

#Now delete temp folder.

Remove-Item $tempPath\*

Remove-Item $tempPath

 

#Go through Content DBs

WriteLog ("Looking for Solution Id: " + $targetSolutionId + " in all Content Databases`n")

$dbs = Get-SPContentDatabase

 

foreach ($contentdb in $dbs)

{

                #Web App Level

                $webAppUrl = $contentdb.WebApplication.Url

 

                #Get WebApp

                $webApp = Get-SPWebApplication -Identity $webAppUrl

 

                $policy = $webApp.Policies[$admin]

                $policyAdded = $false

                $roleAdded = $false

 

                #If the admin doesn't have Full Control, it will be granted as follows:

                if ($policy -eq $null)

                {

                                $policy = $webApp.Policies.Add($admin, "") 

                                $webAppModified = $true

                                $policyAdded = $true

                                WriteLog "Added a policy entry for user '$admin'."

                }

 

                $fullRole = $webApp.PolicyRoles.GetSpecialRole([Microsoft.SharePoint.Administration.SPPolicyRoleType]::FullControl)

                if ($policy.PolicyRoleBindings[$fullRole] -eq $null)

                {

                                $policy.PolicyRoleBindings.Add($fullRole) 

                                $webAppModified = $true

                                $roleAdded = $true

                                WriteLog "Full Control added for '$admin' to Web Application '$webAppUrl'"

                }

 

                if ($webAppModified)

                {

                                $webApp.Update()

                                $webAppModified = $false

                }

 

                #Done. Have Full Control

                WriteLog ("Entering Web Application '$webAppUrl'.`n")

                Get-SPSite -WebApplication $webApp -Limit ALL | % {

                                $site = $_

                                $solution = $null

                                $foundSolution = $false

 

                                #Scan for solution here

                                Get-SPUserSolution -Site $_ | Where { $_.Status -eq [Microsoft.Sharepoint.SPUserSolutionStatus]::Activated -and $_.SolutionId -eq $targetSolutionId } | % {

                                                if ($foundSolution -eq $false)

                                                {

                                                                $foundSolution = $true

                                                                $solution = $_

 

                                                                if ($haveCurrentFeatures -eq $false)

                                                                {                             

                                                                                Get-SPFeature -Sandboxed -Site $site | Where { $_.SolutionId -eq $targetSolutionId } | % {$oldFeatures.Add($_.Id, $_)}

                                                                                $haveCurrentFeatures = $true

                                                                }

 

                                                                if ($upgrade -eq $false)

                                                                {             

                                                                                $solSites.Add($site.Url)  | Out-Null         

                                                                }

                                                                $solutionHash = $_.Signature

                                                                WriteLog ("Found site collection: " + $site.Url)

                                                }

                                }

                                $numSites ++

                               

                                #DoUpgrade here

                                if ($upgrade -and $foundSolution)

                                {

                                                $successAdd = $false

                                                WriteLog ("Uploading new solution file as: $fileName")

 

                                                #Add + Upgrade solution

                                                $myError = $null

                                                Add-SPUserSolution -LiteralPath $solFile -Site $site -ErrorAction:SilentlyContinue -ErrorVariable myError -Confirm:$false

                                                if ($myError -ne $null)

                                                {

                                                                WriteLog("Site collection '" + $site.Url + "' FAILED to upload the new solution.")

                                                                WriteLog("Error: " + $myError)

                                                                $myError = $null

                                                }

                                                else

                                                {

                                                                $successAdd = $true

                                                }

                                               

                                                $addedSolution = Get-SPUserSolution -Identity $fileName -Site $site

                                                if ($addedSolution -ne $null)

                                                {

                                                                WriteLog ("Found solution $fileName in the Solutions Gallery. Attempting to use it...")

 

                                                                #First check for already updated solution

                                                                if ($addedSolution.Signature -eq $solutionHash) 

                                                                {

                                                                                #This means we have the same version installed. Just skip it. And delete our copy!

                                                                                WriteLog ("New solution is already active on this site collection.")

               

                                                                                if ($successAdd -eq $true)

                                                                                {

                                                                                                #Remove the new solution (the dupe)

                                                                                                WriteLog ("Removing file: $fileName")

                                                                                                Remove-SPUserSolution -Identity $addedSolution -Site $site -Confirm:$false

                                                                                                if (!($solFailSites.Contains($site.Url)))

                                                                                                {

                                                                                                                $solFailSites.Add($site.Url) | Out-Null

                                                                                                }

                                                                                }

                                                                }

                                                                else

                                                                {

                                                                                #Perform upgrade

                                                                                Update-SPUserSolution -Identity $solution -Site $site -ToSolution $addedSolution -ErrorAction:SilentlyContinue -ErrorVariable myError -Confirm:$false

                                                                                if ($myError -ne $null)

                                                                                {

                                                                                                WriteLog("Site collection '" + $site.Url + "' FAILED to upgrade to the new solution.")

                                                                                                WriteLog("Error: " + $myError)

                                                                                                if (!($solFailSites.Contains($site.Url)))

                                                                                                {

                                                                                                                $solFailSites.Add($site.Url) | Out-Null

                                                                                                }

                                                                                                $myError = $null

                                                                                }

 

                                                                                if (!($solFailSites.Contains($site.Url)))

                                                                                {

                                                                                                #Upgrade succeeded

                                                                                                WriteLog("Site collection '" + $site.Url + "' has been upgraded to the new solution.")

                                                                                                WriteLog ""

                                                                                                $solSites.Add($site.Url)  | Out-Null

 

                                                                                                #Record results AFTER upgrade

                                                                                                if ($haveNewFeatures -eq $false)

                                                                                                {                             

                                                                                                                Get-SPFeature -Sandboxed -Site $site | Where { $_.SolutionId -eq $targetSolutionId } | %{$newFeatures.Add($_.Id, $_)}

                                                                                                                $haveNewFeatures = $true

                                                                                                }

                                                                                }

                                                                }

                                                }

                                                else

                                                {

                                                                if (!($solFailSites.Contains($site.Url)))

                                                                {

                                                                                $solFailSites.Add($site.Url) | Out-Null

                                                                }

                                                }

                                }

                                $site.Close();

                }             

 

                #Close permissions and webApp

                if ($roleAdded)

                {

                                $policy.PolicyRoleBindings.RemoveById($fullRole.Id)

                                $webAppModified = $true

                        WriteLog "Removed Full Control for '$admin' from Web Application '$webAppUrl'"

                }

                if ($policyAdded)

                {

                                $webApp.Policies.Remove($admin)

                                $webAppModified = $true

                                WriteLog "Removed the policy entry for user '$admin'."

                }

                if ($webAppModified)

                {

                                $webApp.Update()

                                $webAppModified = $false

                }

                WriteLog ""

                WriteLog "Done with Web Application."

                WriteLog ""

}

 

#Final tally of site collections

WriteLog("Analysis of site collection upgrades for solution ID $targetSolutionId ...")

WriteLog("We have processed a total of $numSites site collections.")

WriteLog("")

 

if ($upgrade)

{

                #Site Collection Summary

                if ($solSites.Count -eq 0)

                {

                                WriteLog("No site collections were upgraded. Refer to this log for any upgrade errors.")

                }

                else

                {

                                WriteLog("Listing site collections that have been upgraded:")

                                foreach ($siteUrl in $solSites)

                                {

                                                WriteLog($siteUrl)

                                }

                }

 

                if ($solFailSites.Count -ne 0)

                {

                                WriteLog("Listing site collections that FAILED to upgrade:")

                                foreach ($siteUrl in $solFailSites)

                                {

                                                WriteLog($siteUrl)

                                }

                }

 

                #Feature Upgrade Summary

                if ($newFeatures.Count -gt 0)

                {

                                WriteLog ""

                                WriteLog "Feature upgrade summary for the New User Solution:"

                                foreach($fKey in $newFeatures.Keys)  

                                {

                                                $fDef = $oldFeatures[$fKey]

                                                $fDef2 = $newFeatures[$fKey]

                               

                                                #Feature ID and DisplayName

                                                WriteLog("Feature ID: " + $fDef2.Id + "`t DisplayName: " + $fDef2.DisplayName)

 

                                                #Feature Version

                                                if ($fDef -eq $null)

                                                {

                                                                #New feature added.

                                                                WriteLog("This feature has been newly added.`t`t`t Version " + $fDef2.Version)

                                                }

                                                else

                                                {

                                                                if ($fDef.Version -eq $fDef2.Version)

                                                                {

                                                                                WriteLog("This feature has been unchanged.`t`t`t Version " + $fDef2.Version)

                                                                }

                                                                else

                                                                {

                                                                                WriteLog("Feature went from Version " + $fDef.Version + " to Version " + $fDef2.Version)

                                                                }

                                                }                             

                               

                                                WriteLog ""

                                }

                                WriteLog ("The new solution holds a total of " + $newFeatures.Count + " feature(s).")

                }

}

else

{

                if ($solSites.Count -eq 0)

                {

                                WriteLog("No site collections have been found.")

                }

                else

                {

                                WriteLog("We have found " + $solSites.Count + " site collections, as follows (no upgrade action performed):")

                                foreach ($siteUrl in $solSites)

                                {

                                                WriteLog($siteUrl)

                                }

                }

 

                WriteLog ""

                WriteLog "Feature summary for current User Solution:"

                foreach($fKey in $oldFeatures.Keys)

                {

                                $fDef = $oldFeatures[$fKey]

                                WriteLog ("Feature DisplayName: `t" + $fDef.DisplayName)

                                WriteLog ("Feature Version: `t" + $fDef.Version)

                                WriteLog ("Feature Id: `t`t" + $fDef.Id)

                }

 

                WriteLog ""

                WriteLog ("Found a total of " + $oldFeatures.Count + " feature(s).")

                WriteLog ""

}

WriteLog ""

 

#Close the file handle.

if ($f -ne $null)

{

                $f.Close()           

}

 

發佈日期: 8/15/2010 11:30 PM

這是翻譯後的部落格文章。英文原文請參閱 Managing Upgrades on Sandbox Solutions