Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / productivity / SharePoint

Sharpoint 2010 deployment using Powershell

5.00/5 (2 votes)
24 Oct 2011CPOL3 min read 26K  
This article will assist you to deliver/deploy your Sharepoint site and its features using Powershell

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:

Image 1

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 

Image 2

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.

C#
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.

C#
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:

Image 3

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)