SharePoint 3.0 WSP Deployment Scripts

I have been working with a customer over the last few weeks to come up with a mechanism that their Configuration Management (CM) team can use to deploy custom WSS code.  Fortunately, WSS allows our developers to wrap up their code into a Solution (WSP files).  The solution can have things like templates that go on the file system, web.config changes and features.  Features are cool little things that can do things on WSS as well as have additional tasks on the server or file system, all defined by the developer through and XML file.  Not all solutions will have a feature.

The trick here was to make it very simple for the CM team to deploy different versions of code to different environments such as Dev, Test and Prod.  So, I looked at some of my old WSS 2.0 scripts that would deploy web parts out to EVERY INDIVIDUAL box in the farm by draining the application pools, deploying the DLL and GAC'ing them, restarting the web site (iisapp.vbs), and running a warm up script to fire up the ISAPI filters.  This was a pain for the CM teams, especially in Internet facing properties that you wish to have as little service interruption as possible.  You had to really watch the logs to ensure each box updated successfully, restart the site, etc.

WSS 3.0 makes this a lot easier by having a solution database that can store those solutions that you want to deploy, and then can either use a timer to deploy them across the farm or you can force them.  You deploy the solution to a single web server in the farm, it is stored in the solution database, and SharePoint takes care of installing them on all the web boxes.  In my scripts below, we decided that we would rather have the solutions deploy immediately so that we could troubleshoot any problems right away.

I further wanted to simplify the CM groups deployment by having all deployment scripts and logs on a central server.  They basically "push a button" for the particular solution package they want to deploy and it fires off a remote task to the web server.

The last BIG bonus about this is disaster recovery.  Since we do SQL backups regularly, we are able to bring up a new SharePoint farm, restore our DB's, run our WSP files, and we are back in business.  This is how MSIT does it, BTW.

Here is how it works, pay attention, it gets a little tricky as to what server is running what:

image

Basically, a script is kicked off on the deployment server with parameters for the environment, it fires SchedTaskWebSolDeploy.cmd, which fires a WMIC command to the web server based on name in WMICSolMachines.txt.  This wakes up a scheduled task on the web server, which is set to only run once in 1978 (ensuring that it doesn't fire automatically), and runs the WebServerDeploySolutionwithFeature.cmd.  All of these output log files on the deployment server so that the status can easily be checked from a central place. 

Below are the scripts, I posted them as text to have the search engines crawl them for reference.  If you want to skip to the good stuff, it is in the WebServerDeploySolutionWithFeature.cmd section.  Please NOTE: Thes scripts are intended to overwrite the existing Solutions and Features, so be sure you know what they do before you get them up and running.  Also, the normal rules apply here around the fact that these are examples, please use at your risk and support them yourselves, the last thing I need is any midnight phone calls.

The names of the innocent servers have been changed to "deploymentserver" or "mossdev" to protect their identity:

DeployWebPartsFeature.cmd

://////////////////////////////////////////////////
:// Author: Marcus Hass (mhass@microsoft.com)
:// Version: 2.0
:// Date: 08.01.2007
://
:// Notes:
://
://   Runs a remote task via WMIC to deploy a SharePoint 2007 Solution
://   THIS SCRIPT MUST BE RUN FROM THE deployscripts DIRECTORY (assumes the \CORE is below current direcotry)
://   Assumes all necesary infrastructure exists for Sharepoint on all boxes
://   Assumes that the remote scheduled tasks exist
://
:// Inputs:
://
://   LogFile(%1) - Path to centralized log file (i.e \\endor\deployscripts$)
://   WebSiteName(%2) - The name of the web site that will be deployed to, also used on log file name (Tntranet, ProdMOSSWeb1)
://   PathtoScripts(%3) - UNC path to scripts (i.e. \\endor\deployscripts$)
://   SchedTaskName(%4) - Name of the scheduled task on the remote box
://
://////////////////////////////////////////////////
echo Starting DeployDeployIntranetSiteDefWSP.cmd

\\deploymentserver\deployscripts$\dev\core\SchedTaskWebSolDepoly.cmd \\deploymentserver\deployscripts$\dev\logs \\deploymentserver\deployscripts$\dev DeployWebPartsFeature

SchedTaskWebSolDepoly.cmd

@echo off
://////////////////////////////////////////////////
:// Author: Marcus Hass (mhass@microsoft.com)
:// Version: 2.0
:// Date: 08.01.2007
://
:// Script File:
://
://   SchedTaskWebSolDeply.cmd
://
:// Notes:
://
://   Runs the local sched task to deploy a MOSS solution
://   THIS SCRIPT MUST BE RUN FROM THE deployscripts DIRECTORY (assumes the \CORE is below current direcotry)
://   Assumes all necesary infrastructure exists for Sharepoint on all boxes
://   Assumes that the remote scheduled tasks exist
://
:// Inputs:
://
://   LogFile(%1) - Path to centralized log file (i.e \\endor\deployscripts$, etc)
://   PathtoScripts(%2) - UNC path to scripts (i.e. \\endor\deployscripts$, etc)
://   SchedTaskName(%3) - Name of the scheduled task on the remote box
://  
:// Outputs:
://
:// Environment variables referenced:
://
:// Runs in:
://
://   N32, N64
://
://////////////////////////////////////////////////

:Main

:// Validate the input parameters to make sure they exist.

  if NOT "%1"=="" goto :LogFileOK
    echo ERROR: Empty LogFile parameter. Aborting.
    set RETSTS=1
    goto :usage
  :LogFileOK

  set PathtoScripts=%2
  set SchedTaskName=%3
  set LogFile=%1\Status%computername%%WebSiteName%_DeployServer.txt

:// Sending script info to log file

  echo. >> %LogFile%
  echo Running script SchedTaskWebSolDeploy >> %LogFile%
  Date /T >> %LogFile%
  Time /T >> %LogFile%
  set username >> %LogFile%

:// Run script to envoke remote scheduled tasks

  set cmd1=WMIC /node:@"%PathtoScripts%\WMICSolMachines.txt" PROCESS CALL Create "schtasks /Run /TN %SchedTaskName%"

  echo.
  echo.
  echo Sending Deployment commands to remote computers.
  echo.
  echo Envoking remote scheduled tasks using the following command: >> %LogFile%
  echo Envoking remote scheduled tasks using the following command:
  echo %cmd1% >> %LogFile%
  echo %cmd1%

  %cmd1% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :Oktogotoend
    echo Error running the command: %cmd3%, please check log file located at %LogFile%. >> %LogFile%
    echo Error running the command: %cmd3%, please check log file located at %LogFile%
    goto :bigerror
  :Oktogotoend

  echo.
  echo.
  echo +-----------------------------------------------------+
  echo  Script is successful and did not return any errors
  echo  Log File located at: %LogFile%
  echo +-----------------------------------------------------+
  echo  Please check log files for remote computers as status
  echo  is not reported in this deployment script
  echo +----------------------------------------------------+
  echo.
  echo Script is successful and did not return any errors >> %LogFile%
  echo Please check log files for remote computers as status >> %LogFile%
  echo is not reported in this deployment script >> %LogFile%
  pause

  goto :end

:bigerror
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >> %LogFile%
  echo. >> %LogFile%
  echo A catastropic error has occured and the deployment can not continue, please check >> %LogFile%
  echo error logs located at %LogFile% >> %LogFile%
  echo The return status code was %RETSTS% %ERRORLEVEL% >> %LogFile%
  echo. >> %LogFile%
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >> %LogFile%
  echo.
  echo.
  echo.
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  echo.
  echo A catastropic error has occured and the deployment can not continue, please check
  echo error logs located at %LogFile%
  echo The return status code was %RETSTS% %ERRORLEVEL%
  echo.
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  echo.
  echo.
  pause
  goto :end
://////////////////////////////////////////////////
://
:// Script end.
://
://////////////////////////////////////////////////

:end

  set LogFile=
  set PathtoScripts=
  set cmd1=

WMICSolMachines.txt

webservername

Example of DeployWebPartsFeature Scheduled Task Command Line:

://////////////////////////////////////////////////
:// Author: Marcus Hass (mhass@microsoft.com)
:// Version: 2.0
:// Date: 08.01.2007
://
:// Notes:
://
://   Schedulede Task Name: DeploySolution
://   This is an example file that details what should be in the scheduled task on a remote box.
://
:// Inputs:
://
://   LogFile(%1) - Path to centralized log file (i.e \\endor\deployscripts$\logs)
://   PathtoCode(%2) - UNC Path to Code repository (i.e. \\endor\code$\prod)
://   AppVer(%3) - version of software to deploy (i.e., current, 1.0.0.0)
://   WebSiteName(%4) - The name of the web site that will be deployed to (i.e. Intranet, ProdMOSSWeb1)
://   SiteDefName(%5) - Name of the feature that will be activated/deactivated, Filename and solution names should match (i.e. IntranetSiteDef)
://   PathToScripts(%6) - Path to where the scripts are located (i.e \\endor\deployscripts$)
://
://////////////////////////////////////////////////

://Example of commandline:

\\deploymentserver\deployscripts$\dev\core\WebServerDeploySolutionWithFeature.cmd \\deploymentserver\deployscripts$\dev\logs \\deploymentserver\code$ dev\current mossdev WebPartsFeature \\deploymentserver\deployscripts$\dev

WebServerDeploySolutionWithFeature.cmd

@echo off
://////////////////////////////////////////////////
:// Author: Marcus Hass (mhass@microsoft.com)
:// Version: 2.0
:// Date: 08.01.2007
://
:// Script File:
://
://   WebServerDeploySolutionWithFeature.cmd
://
:// Notes:
://
://   This script is called by a scheduled task on a MOSS web front end server
://   THIS SCRIPT MUST BE RUN FROM THE deployscripts DIRECTORY (assumes the \CORE is below current direcotry)
://   Assumes all necesary infrastructure exists for Sharepoint on all boxes
://
:// Inputs:
://
://   LogFile(%1) - Path to centralized log file (i.e \\endor\deployscripts$\logs)
://   PathtoCode(%2) - UNC Path to Code repository (i.e. \\endor\code$\prod)
://   AppVer(%3) - version of software to deploy (i.e., current, 1.0.0.0)
://   WebSiteName(%4) - The name of the web site that will be deployed to (i.e. Intranet, ProdMOSSWeb1)
://   SiteDefName(%5) - Name of the feature that will be activated/deactivated, Filename and solution names should match (i.e. IntranetSiteDef)
://   PathToScripts(%6) - Path to where the scripts are located (i.e \\endor\deployscripts$)
://  
:// Outputs:
://
://   LogFile=%1\SolutionDeployFeature%computername%%WebSiteName%.txt
://
:// Environment variables referenced:
://
://   ComputerName
://
:// Runs in:
://
://   N32, N64
://
://////////////////////////////////////////////////

:Main

:// Validate the input parameters to make sure they exist.

  if NOT "%1"=="" goto :LogFileOK
    echo ERROR: Empty LogFile parameter. Aborting.
    echo ERROR: Empty LogFile parameter. Aborting. >> c:\DeploySolution.txt
    set RETSTS=1
    goto :end
  :LogFileOK

  if NOT "%6"=="" goto :BadParmsOK
    echo ERROR: Not All Paramters have been supplied. Aborting.
    echo ERROR: Not All Paramters have been supplied. Aborting. >> c:\DeploySolution.txt
    set RETSTS=1
    goto :end
  :BadParmsOK

  set PathtoCode=%2
  set AppVer=%3
  set WebSiteName=%4
  set SiteDefName=%5
  set PathToScripts=%6
  set DepFeatureName1=ITWebParts
  set LogFile=%1\SolutionDeployFeature%computername%%WebSiteName%.txt

  set stsadmpath="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN"

:// Sending script info to log file

  echo. >> %LogFile%
  echo Running script WebServerDeploySolutionWithFeature >> %LogFile%
  Date /T >> %LogFile%
  Time /T >> %LogFile%
  set username >> %LogFile%

:// need to retract the solution so it can be replaced

  set cmd2=%stsadmpath%\stsadm -o retractsolution -name %SiteDefName%.wsp -immediate

  echo Running the following command to retract the solution >> %LogFile%
  echo Running the following command to retract the solution:
  echo %cmd2%  >> %LogFile%
  echo %cmd2%

  call %cmd2% >> %LogFile%

:// If error with command tell user but DONT dump out of script

  if "%ERRORLEVEL%"=="0" goto :retractok
    echo Error running STSADM retract command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM retract command, please check log file located at %LogFile%.
    set ERRORLEVEL=0
  :retractok

:// Executing the commands across the farm, this done after most commands

  set cmd3=%stsadmpath%\stsadm -o execadmsvcjobs

  echo Executing the commands across the farm using the command: >> %LogFile%
  echo Executing the commands across the farm using the command
  echo %cmd3% >> %LogFile%
  echo %cmd3%

  call %cmd3% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :execute1ok
    echo Error executing execadmsvcjobs1, please check log file located at %LogFile%. >> %LogFile%
    echo Error executing execadmsvcjobs1, please check log file located at %LogFile%.
    goto :bigerror
  :execute1ok

:// need to delete the solution so it can be replaced

  set cmd4=%stsadmpath%\stsadm -o deletesolution -name %SiteDefName%.wsp -override

  echo Running the following command to delete the solution >> %LogFile%
  echo Running the following command to delete the solution:
  echo %cmd4%  >> %LogFile%
  echo %cmd4%

  call %cmd4% >> %LogFile%

:// If error with command tell user but DONT dump out of script

  if "%ERRORLEVEL%"=="0" goto :deleteok
    echo Error running STSADM deletesolution command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM deletesolution command, please check log file located at %LogFile%.
    set ERRORLEVEL=0
  :deleteok

:// Executing the commands across the farm, this done after most commands

  set cmd5=%stsadmpath%\stsadm -o execadmsvcjobs

  echo Executing the commands across the farm using the command: >> %LogFile%
  echo Executing the commands across the farm using the command
  echo %cmd5% >> %LogFile%
  echo %cmd5%

  call %cmd5% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :execute2ok
    echo Error executing execadmsvcjobs2, please check log file located at %LogFile%. >> %LogFile%
    echo Error executing execadmsvcjobs2, please check log file located at %LogFile%.
    goto :bigerror
  :execute2ok

:// need to add the solution to the repository

  set cmd6=%stsadmpath%\stsadm -o addsolution -filename %PathtoCode%\%AppVer%\%SiteDefName%.wsp

  echo Running the following command to add the solution >> %LogFile%
  echo Running the following command to add the solution:
  echo %cmd6%  >> %LogFile%
  echo %cmd6%

  call %cmd6% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :addsolutionok
    echo Error running STSADM addsolution command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM addsolution command, please check log file located at %LogFile%.
    goto :bigerror
  :addsolutionok

:// Executing the commands across the farm, this done after most commands

  set cmd7=%stsadmpath%\stsadm -o execadmsvcjobs

  echo Executing the commands across the farm using the command: >> %LogFile%
  echo Executing the commands across the farm using the command
  echo %cmd7% >> %LogFile%
  echo %cmd7%

  call %cmd7% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :execute3ok
    echo Error executing execadmsvcjobs3, please check log file located at %LogFile%. >> %LogFile%
    echo Error executing execadmsvcjobs3, please check log file located at %LogFile%.
    goto :bigerror
  :execute3ok

:// need to deploy the solution from the repository

  set cmd8=%stsadmpath%\stsadm -o deploysolution -name %SiteDefName%.wsp -immediate -allowGacDeployment -allowCasPolicies -allcontenturls -force

  echo Running the following command to add the solution >> %LogFile%
  echo Running the following command to add the solution:
  echo %cmd8%  >> %LogFile%
  echo %cmd8%

  call %cmd8% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :deploysolutionok
    echo Error running STSADM deploysolution command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM deploysolution command, please check log file located at %LogFile%.
    goto :bigerror
  :deploysolutionok

:// need to deactvate a feature before it can be updated

  set Depcmd1=%stsadmpath%\stsadm -o deactivatefeature -name %DepFeatureName1% -url https://%WebSiteName% -force

  echo Running the following command to unextend the https://%WebSiteName% Web Site: >> %LogFile%
  echo Running the following command to unextend the https://%WebSiteName% Web Site:
  echo %Depcmd1%  >> %LogFile%
  echo %Depcmd1%

  call %Depcmd1% >> %LogFile%

:// If error with command tell user but DONT dump out of script

  if "%ERRORLEVEL%"=="0" goto :deactivateok
    echo Error running STSADM deactivate command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM deactivate command, please check log file located at %LogFile%.
    set ERRORLEVEL=0
  :deactivateok

  set RETSTS=0

:// Activate the feature

  set Depcmd2=%stsadmpath%\stsadm -o activatefeature -name %DepFeatureName1% -url https://%WebSiteName%

  echo Running the following command to unextend the https://%WebSiteName% Web Site: >> %LogFile%
  echo Running the following command to unextend the https://%WebSiteName% Web Site:
  echo %Depcmd2%  >> %LogFile%
  echo %Depcmd2%

  call %Depcmd2% >> %LogFile%

:// If error with command tell user but DONT dump out of script

  if "%ERRORLEVEL%"=="0" goto :deactivateok
    echo Error running STSADM deactivate command, please check log file located at %LogFile%. >> %LogFile%
    echo Error running STSADM deactivate command, please check log file located at %LogFile%.
    set ERRORLEVEL=0
  :deactivateok

:// Executing the commands across the farm, this done after most commands

  set cmd10=%stsadmpath%\stsadm -o execadmsvcjobs

  echo Executing the commands across the farm using the command: >> %LogFile%
  echo Executing the commands across the farm using the command
  echo %cmd10% >> %LogFile%
  echo %cmd10%

  call %cmd10% >> %LogFile%

:// If error with command tell user and dump out of script

  if "%ERRORLEVEL%"=="0" goto :execute4ok
    echo Error executing execadmsvcjobs4, please check log file located at %LogFile%. >> %LogFile%
    echo Error executing execadmsvcjobs4, please check log file located at %LogFile%.
    goto :bigerror
  :execute4ok

://The finish line

  echo.
  echo.
  echo +----------------------------------------------------+
  echo  Script is successful and did not return any errors
  echo  Log File located at: %LogFile%
  echo +----------------------------------------------------+
  echo.
  echo Script is successful and did not return any errors >> %LogFile%
  echo SUCCESS SUCCESS SUCCESS SUCCESS >> %LogFile% 

  goto :end

:bigerror
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >> %LogFile%
  echo. >> %LogFile%
  echo ERROR ERROR ERROR ERROR >> %LogFile%
  echo A catastropic error has occured and the deployment can not continue, please check >> %LogFile%
  echo error logs located at %LogFile% >> %LogFile%
  echo The return status code was %RETSTS% %ERRORLEVEL% >> %LogFile%
  echo. >> %LogFile%
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! >> %LogFile%
  echo.
  echo.
  echo.
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  echo.
  echo A catastropic error has occured and the deployment can not continue, please check
  echo error logs located at %LogFile%
  echo The return status code was %RETSTS% %ERRORLEVEL%
  echo.
  echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  echo.
  echo.
  goto :end
://////////////////////////////////////////////////
://
:// Script end.
://
://////////////////////////////////////////////////

:end

  echo. >> %LogFile%
  Date /T >> %LogFile%
  Time /T >> %LogFile%
  echo COMPLETED COMPLETED COMPLETED COMPLETED >> %LogFile%
  echo. >> %LogFile%
  echo. >> %LogFile%

  set LogFile=
  set PathtoCode=
  set AppVer=
  set WebSiteName=
  set SiteDefName=
  set PathToScripts=
  set cmd1=
  set cmd2=
  set cmd3=
  set cmd4=
  set cmd5=
  set cmd6=
  set cmd7=
  set cmd8=
  set cmd9=
  set cmd10=
  set RETSTS=