サンドボックス ソリューションのアップグレードの管理



サンドボックス ソリューションのアップグレードの管理

Body:

サンドボックス ソリューションは、SharePoint 2010 プラットフォーム上の非常に優れた機能です。  しかし、これらのソリューションは、ファームやサイト コレクションを越えてさまざまな場所に展開されるため、その管理方法が問題となります。

この問題に対処するために、PowerShell スクリプトが提供されています。  このスクリプトはいたって単純なものですが、ファームやサイト コレクションを管理するために既に使用しているツールに合うように拡張できます。

それでは、このスクリプトの動作について説明しましょう。 

展開される各サンドボックス ソリューションには、ソリューション ID が関連付けられています。  そのソリューション内には、機能 ID とバージョン番号を持つ複数の機能があります。   このスクリプトは、指定されたソリューション ID について、ファームまたはサイト コレクション全体を調べて、そのソリューションが見つかったすべての場所を示すログを生成します。  次に、ソリューション内の各機能を調べて、展開されているその機能のバージョンを示すログ エントリを追加します。  また、ソリューションの新バージョンが提供されたときにはアップグレードも実行できます。  これはフラグであり、スクリプトはアップグレードを実行したり、ソリューションに関する情報を収集するための手段として使用したりできます。

スクリプトでは以下のパラメーターを使用します。

·         アップグレードするソリューション (.wsp ファイル) のファイル パスおよびファイル名

·         アップグレードを実行するかどうかを示す Switch パラメーター

権限に関する以下のことに注意してください。

·         スクリプトを実行するユーザーがサンドボックス環境の管理者で、アップグレード操作の実行が許可されていることが前提です。

·         管理者にフル コントロールが付与されるように権限レベルが変更されます。

·         アップグレードが完了すると、権限は元の設定に戻されます。

ログの形式は以下のとおりです。

·         ソリューション ID を含めて、調べているソリューションのファイル パスおよびファイル名に関する詳細情報。

·         調べられる各サイト コレクションに関する詳細情報。

·         サイト コレクションごとに、以下の情報が記録されます。

o   一致するソリューションが見つかったかどうかに関する情報

o   見つかった場合は、削除されて新バージョンに置き換えられる可能性があるソリューション ファイルに関する詳細情報

o   アップグレードが実行される場合は、成功または失敗に関する詳細情報

·         サマリーには、以下の情報が含まれます。

o   調べられたサイト コレクションの数

o   アップグレードが実行されない場合は、アップグレードが必要なサイトと、ソリューション内の各機能 (ID) の現在のバージョンに関する詳細情報のサマリー リスト

o   アップグレードが実行される場合は、機能とバージョン情報、および、成功したアップグレード、成功した新規インストール、または既に最新なため変更が行われなかった機能に関する詳細情報

注意事項:

ソリューションのアップグレードの際、SharePoint 2010 プラットフォームではソリューションの異なるファイル名を予期しています。  そのため、ファイル名が同じだと、ソリューションは既にアクティブであるというエラー メッセージが表示されます。  ソリューションをアップグレードする場合、ソリューション ID を使ってそのソリューションの既存のバージョンが検索され、その後でバージョンの詳細情報が調べられます。  アップグレードは新バージョンに移行するだけです。  旧バージョンにはロール バックしません。  そしてバージョンが同じ場合は、何も行われません。

このスクリプトが、展開しているソリューションの管理に役立ち、アップグレードも簡単になれば幸いです。

# 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"

$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()           

}

 

投稿日: 2010 年 8 月 15 日午後 11:30

これはローカライズされたブログ投稿です。原文の記事は、「Managing Upgrades on Sandbox Solutions」をご覧ください。



Skip to main content