WSP-Deployer.ps1


<#PSScriptInfo
 
.VERSION 1.1
 
.GUID 7be1d062-2b59-4390-a985-580ae1e6085a
 
.AUTHOR Mohamed El-Qassas
 
.COMPANYNAME deBUG.to
 
.COPYRIGHT This project is licensed under the terms of the MIT license.
 
.TAGS SharePoint,WSP,Bulk,Install,Rollback,Backup,Log,Version
 
.LICENSEURI https://debug.to
 
.PROJECTURI https://spgeeks.devoworx.com/install-deploy-wsp-sharepoint-2019-powershell
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 WSP Deployer is a PowerShell script that would help you to deploy WSP SharePoint Solutions with backup, rollback,logging, and versioning features in a safe and simple way.
 For more details about "WSP Deployer" features and how it works, Please check https://spgeeks.devoworx.com/install-deploy-wsp-sharepoint-2019-powershell
 
#>
 
Param()

#######################################################
#Author: Mohamed El-Qassas
#About Author: https://devoworx.com
#Script Name: Backup,Rollback, and install all WSP Solutions on your SharePoint Farm
#Check the details at: https://spgeeks.devoworx.com/install-deploy-wsp-sharepoint-2019-powershell
#Have a Question: Ask it at https://debug.to
#######################################################
#Add Add-PSSnapin Microsoft.SharePoint.PowerShell
Set-ExecutionPolicy "Unrestricted"
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue #Stop
#######################################################
function WSP-Deployer()
  { 
    param([Parameter(Mandatory=$true)][string]$WSPPath,
         [Parameter(Mandatory=$true)][String]$webApplication,
         [Parameter(Mandatory=$true)][bool]$Overwrite,
         [bool]$rollback)
   
 try{
    
    Write-Host "#####################################`n WSP SharePoint Deployer`n#####################################" -ForegroundColor Green
    Write-Host "Start deployment process................................." -ForegroundColor Cyan
    Write-Host "1) Checking the prerequiests" -ForegroundColor yellow
    #check the TimerService status
    $TimerService = Get-Service -Name "SPTimerV4"
    if($TimerService.Status -eq 'Running')
     {
       Write-Host ">> The SPTimerV4 is Running!" -ForegroundColor Green
         
      #Validate and verify
      if(!(Test-path $WSPPath))
      {
        Write-Host "The provided path $WSPPath is not found!`n Please provide a valid path Ex: C:\WSP" -ForegroundColor Red
        WSP-Deployer
      }
      else
      {
           Write-Host ">> The provided path $WSPPath is found!" -ForegroundColor Green
      }
      
      if($webApplication -ne "All")
      {
        if((Get-SPWeb $webApplication -ErrorAction SilentlyContinue) -eq $null)
          {
              Write-Host "The provided web application $webApplication is not found!`n Please, provide a valid SharePoint URL!" -ForegroundColor Red
              WSP-Deployer
          }
      
        else
         {
           Write-Host ">> The provided SharePoint Wep application URL $webApplication is valid!" -ForegroundColor Green
         }
      }
      else
         {
           Write-Host ">> The deployment will be done on ALL web apllications" -ForegroundColor Green
         }

    
     $WSPs = Get-ChildItem -Path $WSPPath  -Filter *.wsp
     if($WSPs.count -eq 0)
      {
        Write-Host "There are no SharePoint WSP solutions in this folder: $WSPPath.`n Please, make sure that the WSP' files are stored in the provided path" -ForegroundColor Red
        WSP-Deployer
      }
     else
      { 
        # List the WSP solution in the folder
        $WSPCount = $WSPs.count
        Write-Host "The specified folder $WSPPath has WSP solutions files!" -ForegroundColor Green
        Write-Host "Total number of WSP solutions at $WSPPath is $WSPCount" -ForegroundColor cyan
        $WSPs.Name
        Write-Host "--------------------------------------------------"  -ForegroundColor Cyan
        if($rollback -eq $False)
        {
        $reply = $(write-host "Are you sure you need to install all wsp solutions at $WSPPath ?[y/n]" -ForegroundColor yellow -NoNewline; Read-Host)
        }
        else {$reply = "Y"}

        if ( $reply -match "[yY]" ) { 
                       
            #perform a backup before deploying new release
            if($rollback -eq $False)
            {
              Write-Host "Installing the backup script .........!" -ForegroundColor Green
              Install-Script -Name Backup-WSPSharePoint -force
              Backup-WSPSharePoint
            }
 
            #Create a new Log folder with the current date and time
            $LogFolderPath = "c:\WSPInstall-Log"
              if(-not(Test-path $LogFolderPath))
                 {
                    New-Item -ItemType Directory -Path $LogFolderPath
                 }
            # create log file
            $LogFilePath = "$LogFolderPath\Log-$((Get-Date).ToString('yyyy-MM-dd-hh-mm-ss-tt')).txt"
              if(-not(Test-path $LogFilePath -PathType Leaf))
                 {
                   New-Item -ItemType File -Path $LogFilePath
                 }
            # curren user name who run the script
            $userName = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name

            Write-Host "Install and deploy WSP solutions................................." -ForegroundColor Cyan
            $WSPs | Select-Object Name

            foreach ($WSP in $WSPs)
            {
                $WPSName = $WSP.Name
                $WPSPath= $WSPPath + $WPSName
                $found = $False
                Write-Host " >> Deploy $WPSName" -ForegroundColor Yellow
                    foreach ($solution in Get-SPSolution)
                    {
                        if($WPSName -eq $Solution.SolutionFile.Name)
                        {
                            $found = $True
                            if ($Solution.Deployed -eq $False)
                            {
                                if($webApplication -eq "All")
                                {
                                    Install-SPSolution �Identity $WPSName -AllWebApplications -GACDeployment -force
                                }
                                else
                                {
                                    Install-SPSolution �Identity $WPSName -WebApplication $webApplication -GACDeployment -force
                                }
                                $deployed = $False
                                while ($deployed -eq $False) {
                                    Start-Sleep -s 20
                                    $s = Get-SPSolution -Identity $WPSName
                                    if ($s.Deployed -eq $True -And $s.JobExists -eq $False) {
                                        $deployed = $True
                                        Write-Host $WPSName "is deployed successfully" -ForegroundColor Cyan
                                    }    
                                }
      
                            }
                            else
                            {
                                if($Overwrite -eq $False)
                                {
                                Write-Host "$WPSName is already deployed, no action needed!" -ForegroundColor Red
                                break
                                }
                                else
                                {
                                   $deployed = $False
                                    while ($deployed -eq $False) {
                                        Start-Sleep -s 10
                                        $s = Get-SPSolution -Identity $WPSName
                                        if ($s.Deployed -eq $True -And $s.JobExists -eq $False) {
                                            $deployed = $True
                                        }    
                                    }

                                   if($webApplication -eq "All")
                                    {
                                        Install-SPSolution �Identity $WPSName -AllWebApplications -GACDeployment -force
                                    }
                                    else
                                    {
                                        Install-SPSolution �Identity $WPSName -WebApplication $webApplication -GACDeployment -force
                                    }
                                    $deployed = $False
                                    while ($deployed -eq $False) {
                                        Start-Sleep -s 20
                                        $s = Get-SPSolution -Identity $WPSName
                                        if ($s.Deployed -eq $True -And $s.JobExists -eq $False) {
                                            $deployed = $True
                                            Write-Host "$WPSName is deployed successfully" -ForegroundColor Cyan
                                        }    
                                    }
                                    
                                }
                            }
                    }
                }

                if($found -eq $False)
                {
                    Add-SPSolution -LiteralPath $WPSPath
                    if($webApplication -eq "All")
                    {
                        Install-SPSolution �Identity $WPSName -AllWebApplications -GACDeployment -force
                    }
                    else
                    {
                        Install-SPSolution �Identity $WPSName -WebApplication $webApplication -GACDeployment -force
                    }
                $deployed = $False
                while ($deployed -eq $False) {
                    Start-Sleep -s 20
                    $s = Get-SPSolution -Identity $WPSName
                    if ($s.Deployed -eq $True -And $s.JobExists -eq $False) {
                        $deployed = $True
                        Write-Host "$WPSName is deployed successfully" -ForegroundColor Cyan
                        }    
                    }

                }

                #Add to log
                Add-Content $LogFilePath "`n$WPSName`t | Deployed: $deployed`t | Deployed To: $webApplication`t | Done by: $userName`t | Deployment Time: $((Get-Date))"
        }

         #Add to log
        Add-Content $LogFilePath "`n---------------------------------------------------------------------------------------------"
        Add-Content $LogFilePath "`nAll wsp solutions ($WSPCount) at $WSPPath have been deployed`t"
        
        #Open log
        Invoke-Item -Path $LogFilePath
        if($rollback -eq $true)
        {
             Write-Host "The rollback operation is done successfuly, and all wsp solution at $WSPPath have been redeployed"  -ForegroundColor Green
        }
        else { Write-Host "All wsp solution at $WSPPath have been deployed"  -ForegroundColor Green}
        
        
        

        #Open Solution Management in Centeral Administration
        Start-Sleep -s 5
        Write-Host "--------------------------------------------------" 
        Write-Host "Current Deployed Solutions List on your farm:"  -ForegroundColor Cyan
        Get-SPSolution | Format-Table
        $CenteralAdministrationURL= [Microsoft.SharePoint.Administration.SPAdministrationWebApplication]::Local.Url
        [system.Diagnostics.Process]::Start("iexplore",$CenteralAdministrationURL+"_admin/Solutions.aspx")

        # Check rollback
        $LastBackupPath = "C:\WSPSolutions-Backup\01-Latest-WSPBackup"
        if ($rollback -eq $false)
        {
           $reply = $(write-host "Do you encounter any issues in the new release, `n Would like to roll back to the latest backup located at LastBackupPath? [y/n]" -ForegroundColor cyan -NoNewline; Read-Host)
           if ( $reply -match "[yY]" ) { 
             
             # Open the beackup folder
             Invoke-Item -Path $LastBackupPath
             
             $reply = $(write-host "Are you sure you need to rollback to the latest backup located at $LastBackupPath ? [y/n]" -ForegroundColor yellow -NoNewline; Read-Host)
             if ( $reply -match "[yY]" ) { 
                 $rollback = $true
                 Write-Host "Start rollback process from the last backup folder $LastBackupPath............"  -ForegroundColor Green
                 WSP-Deployer -WSPPath $LastBackupPath -webApplication $webApplication -Overwrite $True -rollback $true
             }
           }
        }
     }
    }
  }
  else
    {
      Write-Host "Opps, the SharePoint Timer Service is not Running,`nPlease start it first, then run the script again" -ForegroundColor Red
      Write-Host "Openeing the Services to start SPTimerV4........" -ForegroundColor cyan
      Start-Sleep -s 7
      Start-Process services.msc
    }
}
Catch
    {
        Write-Host $_.Exception.Message -ForegroundColor Red
        break
    }
}

WSP-Deployer
#EX: Install-AllSPwps -Path "C:\Backup-WSPSolutions\" -webApplication "http://epm" -Overwrite $True
#set webApplication to "All" to deploy the solution for all content web applications
#-Overwrite will redeploy the existing solutions