Context PowerShell Scripts in EPiServer

04 May 2011
Adam Najmanowicz
Frink_Cognifide_2016_HeaderImages_0117

Ok, so I’ve got my shot of endorphins writing about PowerShell last week (damn, it’s nice to be able to code again!), and I got pretty determined on making it usable and achieving all the goals I’ve initially envisioned. and in the process build a usable tool and a library of scripts that people can use either directly or to modify to meet their needs.

The goal for this week: Context Scripts

Context scripts are the first step to break the scripting out of the admin realm and into the editor’s space. Those scripts will still be written by admins and developers but the goal is for them to be usable by the authors. The goal for those scripts can be as trivial as e.g. syndicating all the great functionality little plugins like this Unpublish button by Ted in one place and then mix and match them to your liking.

Some of the important bits:

  • Context scripts are something that is visible to users on “Scripts” page.
  • Scripts can be exposed to everyone or just the groups of your liking… you define it in the script.
  • Scripts are grouped in collections that are defined in *.psepi files that you drop into your application folder

How do I define a script collection?

Each script collection is defined within a single .psepi file. A sample script can look as follows:

<?xml version="1.0"?>
<ContextScriptCollection>
  <Title>Statistics Scripts</Title>

  <Description>This is a sample script collection allows for calculating some interesting stats for the branch you're in.</Description>
  <Scripts>
    <ContextScript>
      <Title>Author Statistics</Title>
      <Description>Click to Learn more about how many pages under this one were created by which authors.</Description>

      <Script>get-childitem -recurse | Group-Object  ChangedBy | Sort count -descending | format-table -property count, name</Script>
        <Icon>/App_Themes/Default/Images/Tools/AddUser.gif</Icon>
        <Warning>This script only calculates statistics so it does not really need a warning but let’s show it anyway. Do you want to calculate them?</Warning>
      <Groups>

        <string>WebAdmins</string>
        <string>Administrators</string>
      </Groups>
    </ContextScript>
  </Scripts>

</ContextScriptCollection>

What does each of the tags mean?

  • Title & Description on ContextScriptCollection are going to appear at the top of the list for the collection – pretty self explanatory.
  • Scripts is a container for ContentScript tags, it can contain any number of them.
  • Each ContentScript tag represent a single script, where Title is what will appear on the button that the user will click to execute the script.
  • Script tag contains the script body – this is where you put the code that will get executed
  • Icon is a URL to an image that will appear on the button left of the button title.
  • Warning tag contains a question that will get presented to the user before the script will be executed. This tag can be omitted in which case no warning will be shown. A rule of thumb would be that you should show a warning before a long running scripts and scripts that modify content so a user can back away from a mistakenly pressed button.
  • Groups tag contains the list of groups that will have the right to see the script. if that tag is empty, all users will see the script. If you define at least one group, you need to define all groups that you want to see the button.

What does “Context” in Context scripts mean?

Basically since we cannot show the editor a console and let them navigate to the page (for various reasons, like complexity and potential destructive powers Smile) The scripting environment will put your script “in the current page” before releasing control to your script, which in essence is equivalent to typing before your script.

cd MyCMSDrive:
cd /path/to/my/page/

That means that your script can get access to the page the user is currently on simply by using the “get-item .” command or enumerate its children by use of “get-childitem” etc. in the case of the script above it calculates author statistics for the branch it is executed in. Pretty cool, huh? ;)

Additionally I’ve realized in the process of duplicating/extending the functionality of Ted’s plugin that modifying standard EPiServer properties is not necessarily very intuitive, hence I’ve created a few macros to help me with the scripting exercises. While I still need to call “CreateWritableClone” I’ve simplified the saving of a page by defining the “Save-Page” function and created a Get-CurrentPage as an alias to “get-item .”. So a following script unpublishes the current page:

Get-CurrentPage | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}

While this one unpublishes all of its children

get-childitem -recurse | foreach-object {
$writable = $_.CreateWritableClone();
$writable.StopPublish = [DateTime]::Now;
Save-Page($writable);
}

Notice the subtle difference in the script and the major difference in the effect? Pure PowerShell magic!

To be honest I was amused to find out that during the whole process I’ve still not broken the CMS 5 compatibility, but I don’t expect it to stay this way in the future.

EPiServer5ContextScript    EPiServer6ContextScript

Also at this moment you can add and remove the *.psepi files at any moment as the files are parsed on every request, if that proves to be a problem in the future, caching will get introduced. At this moment I don’t find it a problem as it only happens in edit mode.

[Download & Enjoy]

Includes 2 bonus script collections!

How to install?

Extract the DLL form the ZIP file into the BIN folder of your web application to install the plugin. Remove the DLL to uninstall it.

All constructive feedback appreciated!

Disclaimer – Responsibility: With great powers comes great responsibility – this tool can do a lot of harm to a lot of content in a very short time – backup your system before using the plugin! I will not be held responsible for any use of it. Test your scripts on your development server first! Test on an exact copy of production before running scripts on production content.

Disclaimer – Security: While the tool requires a membership in either the “WebAdmin” or “Administrators” group, to execute, protect it with a <location> entry in web.config, to add another layer of security especially if your administration UI is exposed to the public. Manage your group memberships & rights responsibly!

pre.ps1 { padding: 4px; margin: 4px 0 4px 0; overflow: auto; background-color: #012456; border: thin solid #aaa; color:#fff; font-weight:900; width: 95%; border: solid #000 1px; }