PsRocket Kieranties must be the biggest PowerShell nerd (together with yours truly) I?ve had a privilege to chat with (I guess this implies I talk to myself?). So it shouldn?t be a surprise when the two started talking PowerShell/Sitecore pixie dust started sparkling.

This time ? events integration.

What does it take to integrate PowerShell with Sitecore events?

This is a fairly easy task that Sitecore pretty thoroughly describes in the ?Using Events? SDN article. So there is little point for me to reiterate it here.

The integration requires to add some entries to the include files. I?ve added definitions for most of the item related events to the Cognifide.PowerShell.config file, but commented them out, because I don?t want you to have any performance penalty associated with the PowerShell Console installation and by default it has some scripts defined for you to try out.. All you need to do to enable it is to uncomment the <events> section of the config file and scripts will start firing up.

Implementation is pretty straightforward – the console has well defined place within its script libraries where your scripts should be placed:

private const string EventHandlerLibraryPath =
    "/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/";

Which you can access from the PowerShell ISE:

image

Now if you follow the code you can see that the handler upon receiving an event will trigger all scripts located in the appropriate folder in that library:

public void OnEvent(object sender, EventArgs args)
{
    var eventArgs = args as SitecoreEventArgs;
    if (eventArgs == null)
    {
        return;
    }
    Item item = eventArgs.Parameters[0] as Item;
    string eventName = eventArgs.EventName.Replace(':', '/');

    Database database = item != null ? 
                            item.Database ??
                            Context.ContentDatabase : 
                            Context.ContentDatabase;
    Item libraryItem = 
             database.GetItem(EventHandlerLibraryPath + eventName);

    if (libraryItem == null)
    {
        return;
    }
    var session = new ScriptSession(ApplicationNames.Default);

    foreach (Item scriptItem in libraryItem.Children)
    {
        if (item != null)
        {
            session.SetItemLocationContext(item);
        }

        session.SetVariable("eventArgs", eventArgs);
        string script = scriptItem["Script"];
        if (!String.IsNullOrEmpty(script))
        {
            session.ExecuteScriptPart(script);
        }
    }
}

So e.g. ?item:added? event will trigger all scripts located under ?/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Added? this has been done by convention as there is no way I know of to define which script item to associate with a particular event. But then again ? you want that information in the CMS anyway!

Naturally you need the matching event added or uncommented in either Cognifide.PowerShell.config, or another config you should choose? which for the mentioned ?item:added? would look like:


  <sitecore>
    <events>
      <event name="item:added">
        <handler method="OnEvent" 
            type="Cognifide.PowerShell.SitecoreIntegrations.Tasks.ScriptedItemEventHandler, Cognifide.PowerShell" />      
    </events>
  </sitecore>
</configuration>

Now we can start scripting!

As you can see in the code above the code passes the event arguments to the script as eventArgs variable so you can act upon the value you got from the event. It will also attempt to change the context (location) the script starts at to the item it got from the triggering code (if event supports and uses items). So a sample script that accepts item related events and logs them into a item-event-log.txt file in the Sitecore logs folder could look like this:

$logFile = "$([Sitecore.Configuration.Settings]::LogFolder)\item-event-log.txt";
$item = $eventArgs.Parameters[0];
"$($eventArgs.EventName) : $($item.Database.Name):$($item.Paths.Path)" >> "$($logFile)"

and after attaching this to a couple more events my log looks as follows:

item:saved : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Added/Save to log
item:saved : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/Save to log
item:saved : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/Save to Log
item:renamed : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/Save to Log
item:saved : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/PowerShell Script
item:added : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/PowerShell Script
item:deleted : master:/sitecore/system/Modules/PowerShell/Script Library/Event Handlers/Item/Renamed/PowerShell Script

Now that opens plenty of possibilities:

  • Why not watch an item and get yourself notified every time someone messes with your article or configuration?
  • get notified when someone publishes something?
  • Email yourself or a person when their user is added or gets a role assigned?
  • Write a distinct log of publishing, user related or item related changes?
  • Move item to a proper place on save (like News Mover that Alistair describes in his article ? but in PowerShell)
  • Update your index real-time.
  • Make a build with a Psake when an item meets a condition? It?s PowerShell after all!
  • Send all those notifications to your Pebble watch via Kieranties? Pushover Scripts ? Sure!

One thing to remember is that $eventArgs parameters composition will vary from one event type to another. But you can always consult the nice table on SDN to determine those.

You will find the integration in the PowerShell Console starting from Version 2.0 (RC7) already available on the Sitecore Marketplace.

Thanks for the great idea Kieran! (You should really watch his blog for some serious PowerShell magic!)

Disclaimer: With great powers comes great responsibility ? this tool can do a lot of good but also bring harm to a lot of content in a very short time ? backup your system before running a script that modifies your content and never run any untested scripts in a production environment! 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.

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5.00 out of 5)
Loading...



This entry (Permalink) was posted on Monday, May 27th, 2013 at 8:50 am and is filed under .Net Framework, C#, Code Samples, PowerShell, Sitecore, Software, Software Development, Solution, 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.