Introduction
This article helps you with simple steps to package an entire Sharepoint 2010 site with its features and how to deliver/deploy them on the client environment or on a different testing server.
Using Powershell to Export the Site
We are going to use Powersell file(.ps1) for the export operation of the site. The content of the file is shown below. You can copy paste the following code into a Notepad, name it as Export-Operation.ps1 and save it in the local drive of the Sharepoint server.
Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
[System.Reflection.Assembly]::LoadWithPartialName
("Microsoft.SharePoint.Administration") > $null
[System.Reflection.Assembly]::LoadWithPartialName("System.Collections.Generic") > $null
$currentDir=Convert-Path (Get-Location -PSProvider FileSystem)
$newSiteUrl=$args[0]
function WriteHost ([string] $Msg)
{
Write-Host $Msg -foregroundcolor yellow
}
$errorActionPreference = 'Inquire'
function ExportSite ([string] $NewSiteUrl)
{
$formattedurl=$NewSiteUrl.Replace("http://","")
$formattedurl=$formattedurl.Replace("/","-")
$formattedurl=$formattedurl.Replace(":","")
$path=$currentDir+"\"+$formattedurl+".cmp"
WriteHost " "
WriteHost "-------------------------------------------"
WriteHost "Exporting site",$NewSiteUrl,"- capturing user security..."
Export-SPWeb -Identity $NewSiteUrl
-path $path -Confirm:$false -Force -ErrorVariable errors
-IncludeUserSecurity -IncludeVersions All
if ($errors.Count -eq 0)
{
WriteHost "Export of site",$NewSiteUrl,"complete!"
}
WriteHost "-------------------------------------------"
WriteHost " "
}
if ($args[0] -ne $null)
{
if(!(test-path logs -pathtype container)){new-item logs -type directory}
$operationName="export-operation."
$currentdatetime = get-date -format "yyyy-MM-d.hh-mm-ss"
$logname=$operationName+$currentdatetime+".log"
$logfile=$currentDir + "\logs\" + $logname
Start-Transcript $logfile
ExportSite $newSiteUrl
Stop-Transcript
}
else
{
WriteHost "Invalid arguments supplied"
WriteHost "Arg 1 = New Site Url"
}
Now we are going to use our Export-Operation.ps1 file to export site to a .cmp file. This operation takes site url as its parameter
Step 1: Open Sharepoint 2010 Management Shell in your sharepoint server as shown:
Step 2: In the command prompt that opens, navigate to the path where the file Export-Operation.ps1 is saved using cd command.
Step 3: Execute the following command after that:
.'[path]/Export-Operation.ps1' [site url]
eg : .'C:\RiskportalMigratio n2010\PhaseIII\SolutionPackages/Export-Operation.ps1'
http://80pd8devsp10:1122
Step 4: Once the command is successfully executed, you will find you package file .cmp in the same location. The name of the cmp file will be driven from your site URL, you can very well rename it for the better understanding. Here we are going to rename it as Riskportal.cmp.
So now, we have successfully exported the site.
Using Powershell to Import the Site
Before doing this process, I just want to make it clear that the cmp file will have only the site and its content, not the features. We are going to use two Powershell files(.ps1) for the import operation of the site. One Import-Operation.ps1 file to import the site, two Deploy-Solutions-InCurrentFolder.ps1 file to deploy all the features(.wsp file) kept in the current folder.The content of the Import-Operation.ps1 file is shown below. You can copy paste the following code into a Notepad, name it as Import-Operation.ps1 and save it.
Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
[System.Reflection.Assembly]::LoadWithPartialName
("Microsoft.SharePoint.Administration") > $null
[System.Reflection.Assembly]::LoadWithPartialName("System.Collections.Generic") > $null
$currentDir=Convert-Path (Get-Location -PSProvider FileSystem)
$newSiteUrl=$args[0]
$importFileName=$args[1]
if ($args[2] -eq "-IncludeUserSecurity")
{
$includesecurity=$true
}
else
{
$includesecurity=$false
}
function WriteHost ([string] $Msg)
{
Write-Host $Msg -foregroundcolor yellow
}
$errorActionPreference = 'Inquire'
function ImportSite ([string] $NewSiteUrl, [string] $ImportFilePath)
{
$contentdbweburl="http://"+$urlServerName
WriteHost " "
WriteHost "-------------------------------------------"
if ($includesecurity -eq $true)
{
WriteHost "Importing site",$NewSiteUrl,"- overwriting user security..."
Import-SPWeb -Identity $NewSiteUrl
-path $ImportFilePath -Confirm:$false
-Force -ErrorVariable errors -IncludeUserSecurity
-UpdateVersions Overwrite
}
else
{
WriteHost "Importing site",$NewSiteUrl,"
- user security will not be modified..."
Import-SPWeb -Identity $NewSiteUrl
-path $ImportFilePath -Confirm:$false
-Force -ErrorVariable errors -UpdateVersions Overwrite
}
if ($errors.Count -eq 0)
{
WriteHost "Import of site",$siteUrl,"complete!"
}
WriteHost "-------------------------------------------"
WriteHost " "
}
if ($args[0] -ne $null -and $args[1] -ne $null)
{
if(!(test-path logs -pathtype container)){new-item logs -type directory}
$operationName="import-operation."
$currentdatetime = get-date -format "yyyy-MM-d.hh-mm-ss"
$logname=$operationName+$currentdatetime+".log"
$logfile=$currentDir + "\logs\" + $logname
Start-Transcript $logfile
$filePath=$currentDir + "\" + $importFileName
ImportSite $newSiteUrl $filePath
Stop-Transcript
}
else
{
WriteHost "Invalid arguments supplied"
WriteHost "Arg 1 = New Site Url"
WriteHost "Arg 2 = Import File Name"
}
The content of the Deploy-Solutions-InCurrentFolder.ps1 file is shown below. You can copy paste the following code into a Notepad, name it as Deploy-Solutions-InCurrentFolder.ps1 and save it.
Add-PsSnapin "Microsoft.SharePoint.PowerShell" -ErrorAction SilentlyContinue
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SharePoint") > $null
[System.Reflection.Assembly]::LoadWithPartialName
("Microsoft.SharePoint.Administration") > $null
[System.Reflection.Assembly]::LoadWithPartialName("System.Collections.Generic") > $null
$currentDir=Convert-Path (Get-Location -PSProvider FileSystem)
$operationType = $args[0]
$SiteUrl = $args[1]
$currentdatetime = get-date -format "yyyy-MM-d.hh-mm-ss"
$logname="wsp-deployment."+$currentdatetime+".log"
$wspLogFile=$currentDir + "\" + $logname
$searchPath = $currentDir + "\*.*"
function WriteHost ([string] $Msg)
{
Write-Host $Msg -foregroundcolor yellow
}
function WaitForJobToFinish([string]$SolutionFileName)
{
$JobName = "*solution-deployment*$SolutionFileName*"
$job = Get-SPTimerJob | ?{ $_.Name -like $JobName }
if ($job -eq $null)
{
WriteHost "Timer job not found"
}
else
{
$JobFullName = $job.Name
Write-Host -NoNewLine "Waiting to finish job $JobFullName"
while ((Get-SPTimerJob $JobFullName) -ne $null)
{
Write-Host -NoNewLine .
Start-Sleep -Seconds 2
}
Write-Host -NoNewLine ". Finished waiting for job"
WriteHost " "
}
}
function RetractRemoveAdd
{
param (
[String]$PackageName,
[String]$OperationType
)
# RetractRemoveAdd -PackageName PackageName [-OperationType OperationType]
# OperationType is optional and "update", "deploy",
or "redeploy" are the only supported options.
# The default is to "update", unless solution does not exist.
if (($OperationType -eq $null) -or ($OperationType -eq "")){
$OperationType = "update"
} elseif ($OperationType -eq "deploy") {
$OperationType = "redeploy"
}
if (($OperationType -ne "update") -and ($OperationType -ne "redeploy")){
$OperationType = $null
WriteHost "Incorrect parameter for OperationType.
Use update, deploy, or redeploy"
}
WriteHost "Performing",$OperationType,"on",$PackageName
$solution = Get-SPSolution | where-object {$_.Name -eq $PackageName}
# check if solution already deployed
if (($solution -ne $null) -and ($OperationType -eq "redeploy"))
{
Write-Host "Uninstalling previous version of",
$PackageName -foregroundcolor yellow
if ($solution.Deployed -eq $true)
{
if($solution.ContainsWebApplicationResource)
{
Uninstall-SPSolution -Identity $PackageName
-WebApplication $SiteUrl -Confirm:$false
}
else
{
Uninstall-SPSolution -Identity $PackageName -Confirm:$false
}
while ($Solution.JobExists)
{
Start-Sleep 2
}
WriteHost "SOLUTION HAS BEEN UNINSTALLED SUCCESSFULLY."
Remove-SPSolution -Identity $PackageName -Confirm:$false -Force:$true
$solution = $null
WriteHost "SOLUTION HAS BEEN REMOVED SUCCESSFULLY."
}
}
$SolutionPath=$CurrentDir + "\" + $PackageName
if (($solution -ne $null) -and ($OperationType -eq "update"))
{
Write-Host "Updating previous version of", $PackageName -foregroundcolor yellow
Update-SPSolution -Identity $PackageName -LiteralPath $SolutionPath
-GACDeployment -Force:$true -Confirm:$false
Write-Host "SOLUTION HAS BEEN UPDATED SUCCESSFULLY." -foregroundcolor yellow
}
else
{
Write-Host 'Adding solution:',$SolutionPath -foregroundcolor yellow
Add-SPSolution -LiteralPath $SolutionPath -Confirm:$false
if ($solution -eq $null){ $solution = Get-SPSolution |
where-object {$_.Name -eq $PackageName} }
Write-Host 'Installing solution:',$PackageName -foregroundcolor yellow
if ($solution.ContainsWebApplicationResource)
{
Install-SPSolution -Identity $PackageName -GACDeployment
-WebApplication $SiteUrl -Force:$true -Confirm:$false
}
else
{
Install-SPSolution -Identity $PackageName
-GACDeployment -Force:$true -Confirm:$false
}
Write-Host "SOLUTION HAS BEEN INSTALLED SUCCESSFULLY." -foregroundcolor yellow
}
}
function BeginProcessing
{
Start-Transcript $wspLogFile
$errorActionPreference = 'Inquire'
$wspFiles = Get-ChildItem $searchPath -Include *.wsp
if ($wspFiles -ne $null)
{
$filePathArray = @()
$fileNameArray = @()
WriteHost ""
WriteHost "Processing the following file(s) .."
WriteHost "-----------------------------------------------"
foreach ($wspFile in $wspFiles)
{
$fileNameArray = $fileNameArray + $wspFile.Name
$filePathArray = $filePathArray + $wspFile.FullName
WriteHost $wspFile.Name
}
WriteHost "-----------------------------------------------"
WriteHost ""
foreach ($fileName in $fileNameArray)
{
RetractRemoveAdd -PackageName $fileName
-OperationType $operationType
WriteHost ""
}
WriteHost ""
#WriteHost "Restarting IIS .."
#Restart-Service W3SVC
#iisreset
WriteHost "Operation completed."
}
else
{
WriteHost "Operation skipped. No WSP's found at",$currentDir
}
Stop-Transcript
}
if ($args[0] -ne $null -and $args[1] -ne $null)
{
BeginProcessing
}
else
{
WriteHost "Invalid arguments supplied"
WriteHost "Arg 1 = Action Directive: [update], [deploy], or [redeploy]"
}
Now we are going to create one more batch file (.cmd) to execute this import operation in sequence so that it will make the work easy for the installer(client). You can copy paste the following code into a Notepad, name it as InstallSite.cmd and save it.
@SET TARGETURL=http://80pd8devsp10:1122
@SET PACKAGE=Riskportal.cmp
powershell .\Import-Operation.ps1 %TARGETURL% %PACKAGE%
powershell .\Deploy-Solutions-InCurrentFolder.ps1 redeploy %TARGETURL%
Pause
Note: You have to set your target URL and package name according to your destination environment and save it. Now we are going to start our import operation.
Step 1: In the destination server (where you are going to import the site), create a new web application using Sharepoint central admin.
Step 2: Then create a site collection for the webapplication, while creating the site collection in the template selection option select Custom and select "Select a template later" as shown:
Step 3: Once the site is created, save the powershell files Import-Operation.ps1, Deploy-Solutions-InCurrentFolder.ps1 and InstallSite.cmd file in the same location of the destination server. Then put all the .wsp files of the site features plus the exported .cmp file "Riskportal.cmp" as well in the same folder.
Step 4: Once all the two .ps1 files, .cmd file, .wsp files and .cmp file are ready at the same location, run the InstallSite.cmd to start the import process.
Step 5: If you get any warning during installation, say yes for all of those.
Step 6: Once the installation is done, go to the new site to check your successful import process of site and its features.
Explanation
The command "powershell .\Import-Operation.ps1 %TARGETURL% %PACKAGE%
" will import the .cmp file to the new URL given.
The command "powershell .\Deploy-Solutions-InCurrentFolder.ps1 redeploy %TARGETURL%" will uninstall the features if already exists and will install the current versions of .wsp files available in the same folder.
Points of Interest
Sometimes some of the features of the site will fail during installation. You can reinstall them by executing the following command:
.'[path]/Deploy-Solutions-InCurrentFolder.ps1' redeploy [site url]
The advantage of this kind of deployment approach is that it will make the work easy for the Installer.