A few days back a budy from our Sitecore team has alerted me to this interesting question on StackOverflow which asks for automation of content promotion from one Sitecore instance to another. He suggested – and rightly so – that the PowerShell Console could be used in that scenario. While this was always possible by simply writing it as a PowerShell code the latest version of the console added a few commandlets making building packages much easier.

The easiest approach is to build the package visually in the package designer, save it and then simply use the console to read it and generate the installation zip like:

get-package "powershell console.xml" `
  | Export-Package -FileName "PowerShell Console.zip" -Zip

That’s fine in most cases but if you have some more complex scenarios or want to generate some custom packages – you might want to generate packages directly in PowerShell.

To Create a Package you simply use:

$package = new-package "Test Package";

Now that you have that package you might want to add some files and items to it.

Let’s add for example our item templates by querying the master database and creating a dynamic item source:

$TemplatesSource = get-childitem "master:/templates/Cognifide" `
  | New-ItemSource "Cognifide Templates";

And subsequently add it to our new package:


While that by itself is fairly useful, the really cool part is that you have a full flexibility of PowerShell at your disposal when you create a source with static items. Let’s say you want to add all items of template “Article Template” that reside anywhere under your “home” node … now that would require quite a bit of clicking in the Package Designer, but is trivial with the PowerShell Console:

$ArticlesSource = get-childitem master:/content/home/about-us/* -recurse `
  | where-object { $_.TemplateName -match "ArticleTemplate" } `
  | New-ExplicitItemSource "Cognifide Articles";


You can specify any automation or filter you can think of to your Get-ChildItem, and you really don’t have to skimp on the number of data sources – after all you can re-generate your package at any time!

Similarly you can do this to the files on disk. Let’s say – you want to add all .aspx, .ascx and .ashx files, just to make sure your deployment features all the latest code and for the sake of this example let’s assume your UI elements are located in the Layouts folder under your web application:

$LayoutsPath = $AppPath+"layouts\*"
$Layouts = get-childitem $LayoutsPath -include "*.as?x" -recurse -force `
  | New-ExplicitFileSource "My Layouts";

Easy enough… now let’s add everything that is within the bin folder as a dynamic file source:

$BinFolder = New-FileSource "Bin Folder" -Root "/bin"

That is it really… you may want to specify your package metadata which you would do like:

$package.Metadata.Author = "Auto generated " + `
$package.Metadata.Comment = "Isn't it cool?!";
$package.Metadata.Publisher = "Cognifide";

and then save it for later opening in package designer:

$package | Export-Package -FileName "test package.xml"

alternatively you can open such package as specified earlier

get-package "test package.xml"

if you ever wanted to add more sources to it or export as a zip file to be imported with the assets in your target environment:

$package | Export-Package -FileName "test package.zip" -Zip

… now on your target machine you need to upload your package to the Data\Packages folder. But then to install it all it takes is:

Import-Package "test package.zip"

Obviously all of it can be hooked to ribbon, context items, or be scheduled… but I get ahead of myself…

So how does it all relate to continuous deployment?

All of this can be completely automated, all you need to do is create a Script item as described in one of my previous posts and call the PowerShell execution URL referencing your script from your CruiseControl server or whichever continuous integration product you use in a fashion similar to:


You need to deal with the fact that you are most probably not logged in with your continuous delivery environment – in this case probably best approach is to use the web database or the script item my turn out to be unavailable to you and the script will not execute.

Now in your source environment your script will create the package and upload it to an FTP server (there is plenty of ways to do this from PowerShell… you can find a couple of samples on Stack Overflow) and subsequently call a second part of the script on the target server.

On the Target server – a complementary script will be executed in the similar fashion – by the originating server and if you don’t have direct access to the file on the FTP server you’ve just uploaded – you can download it and import the package.

Now if you integrate the script with a ribbon in Content Editor on the source server (like described in the previous post) you can have a one-click-deployment solution on your dev machine, but then the REALLY cool part would be to integrate it with the context menu (as described in this post) and be able to push parts of the site to production with a single click! Not to mention your nightlies can really be nightlies if you do it using the scheduled tasks integration.

1 Star2 Stars3 Stars4 Stars5 Stars (2 votes, average: 4.50 out of 5)

This entry (Permalink) was posted on Monday, December 19th, 2011 at 12:28 pm and is filed under ASP.NET, Best Practices, C#, CMS UX, Code Samples, Continuous Deployment, PowerShell, Sitecore, Software Development, Web applications. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response , or trackback from your own site.

  • Great post!

    That would definitely allow us to build a deployment pipeline. Build a package once as a part of continuous integration and then push it thorught staging, tests etc to finally arrive at live environment.

  • Pingback: Your own PowerShell commandlets | Codality()

  • Benjamin Vg


    My problem with the current system is that I try to script the installation of sitecore including the package installation. The problem to do that with your powershell is that I need to install the powershell package manualy. Is it possible to bypass it?


  • Vinod Singh


    I have created the nuget package. It contains sitecore items and files. While installing the package it is showing under the package folder. That one I don’t want to show. I want to show in the root folder of the application. [When we install the sitecore package through sitecore, all the files and items comes in proper place] My requirement is while installing the nuget package, Is it possible to  update the sitecore database using powershell during installation of nuget package? If yes then How?  I spent so much time to find this solution. Please suggest me.

  • Pingback: Sitecore-Tasks automatisieren mit Sitecore PowerShell Console – Sitecore()

  • Pingback: Sitecore PowerShell Extensions in numbers | Codality()

  • vinod jaiswal

    Hi Adam,

    Is there a way to provide remote path as the parameter for Install-Package command??

    Install-Package -Path Data-1.zip -InstallMode Overwrite

    Install-Package -Path “\<>Data.zip” -InstallMode Overwrite


  • Sen Gupta

    Just for the people who would wish to do CI/CD of habitat and generate package from the environment:

    Here is what i ended up using the excellent PowerShell Extension.

    Install Powershell Extensions in Habitat.

    1) Run Gulpfile-CI.js from command prompt like this: gulp –gulpfile gulpfile-ci.js CI-Do-magic
    Note: You may have to provide permission on the folder so that temp folder required by CI-DO-magic task can be run. The Gulpfile-CI.js is located in root folder.
    2) Grab: the output of above step in form of package.xml (Again located in root folder of Habitat Solution) and drop it into packages folder of Sitecore instance. Of course you can automate this in your powershell script. For the sake of POC, i dropped manually. Once, in office, i will run this through team city.

    3) Run Powershell Extension and drop this command into shell: (of course, you can script name, version and more information as shown by Adam in the above examples)
    get-package “package.xml” | Export-Package -FileName “habitat.zip” -Zip

    That’s it, you have a package ready with files and folder.

    I would recommend to go through gulpfile-CI.js and skeleton package.xml provided by Habitat Team:

  • Pingback: New us online casinos()

  • Pingback: tips for writing a good essay introduction()

  • Pingback: Continuous deployment in Sitecore with PowerShell | Codality()