2

We have a context menu PowerShell script to move an item to a new location and perform some other actions on the item once it's moved to the new location. When the script has finished the item that was moved is still visually present in the old location. For that, we need to manually refresh the parent item.

We would like to reload the parent node of the current context node any idea on how to do this with SPE?

0
2

I did an investigation on the matter since you posted the question. Using OOTB Sitecore PowerShell, you will not be able to trigger the refresh of the Sitecore content tree. However, you may do so using the 2 possible solutions I've found.

1 - Use Sitecore Command on Context Menu

Instead of using the SPE Context Menu feature (where you create a script which is rendered under the Scripts menu item), create a menu item that will call your custom C# code.

From the back-end, you will still have the ability to call your powershell script using the below code

public void Invoke()
{
    using (ScriptSession scriptSession = ScriptSessionManager.NewSession("Default", true))
    {
        Item speScriptItem = Sitecore.Context.Database.GetItem("/path-or-id/to-spe-item");
        string script = speScriptItem["Script"];
        if (!string.IsNullOrEmpty(script))
            scriptSession.ExecuteScriptPart(script);
    }
}

More info on the above code snippet at Running a Sitecore Powershell script from code.

With this, you will have control on executing the refresh command using the following

Context.ClientPage.SendMessage((object)this, "item:refresh(id=" + itemId + ")");
Context.ClientPage.SendMessage((object)this, "item:refreshchildren(id=" + itemId + ")");

More info at Sitecore Dialogs - Content Editor.

2 - Customize the Sitecore PowerShell

The reason to customize the PowerShell is because when you are executing the Menu Item, in the code behind, it is already refreshing the item where the script has executed. So, for example, if you run your script on Item A, the refresh will occur on Item A. My workaround to override the item:executescript command. Below is the code I am using

[Serializable]
public class ExecuteScriptExtension : Command
{
    private string scriptId;
    private string scriptDb;
    private string itemId;
    private string itemDb;
    private string itemLang;
    private string itemVer;
    private bool isCustom;

    public override CommandState QueryState(CommandContext context)
    {
        return context.Parameters["ScriptRunning"] != "1" ? CommandState.Enabled : CommandState.Disabled;
    }

    public override void Execute(CommandContext context)
    {
        Assert.ArgumentNotNull((object)context, nameof(context));
        this.scriptId = context.Parameters["script"];
        this.scriptDb = context.Parameters["scriptDb"];
        if ((uint)context.Items.Length > 0U)
        {
            Item obj = context.Items[0];
            this.itemId = obj.ID.ToString();
            this.itemDb = obj.Database.Name;
            this.itemLang = obj.Language.Name;
            this.itemVer = obj.Version.Number.ToString((IFormatProvider)CultureInfo.InvariantCulture);
            if (scriptId.Equals("Your SPE Script Item Id"))
            {
                isCustom = true;
            }
        }
        SheerResponse.CheckModified(false);
        Context.ClientPage.Start((object)this, "Process");
    }

    protected void Process(ClientPipelineArgs args)
    {
        Assert.ArgumentNotNull((object)args, nameof(args));
        if (args.IsPostBack)
        {
            if (isCustom)
            {
                Context.ClientPage.SendMessage((object)this, "item:refresh(id={110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9})");
                Context.ClientPage.SendMessage((object)this, "item:refreshchildren(id={110D559F-DEA5-42EA-9C1C-8A5DF7E70EF9})");
            }
            else
            {
                Context.ClientPage.SendMessage((object)this, "item:refresh(id=" + this.itemId + ")");
                Context.ClientPage.SendMessage((object)this, "item:refreshchildren(id=" + this.itemId + ")");
            }
            if (!args.HasResult || args.Result.IsNullOrEmpty())
                return;
            string result = args.Result;
            char[] chArray = new char[1] { '\n' };
            foreach (string eventName in result.Split(chArray))
                Context.ClientPage.ClientResponse.Timer(eventName, 2);
        }
        else
        {
            UrlString urlString = new UrlString(UIUtil.GetUri("control:PowerShellRunner"));
            if (!string.IsNullOrWhiteSpace(this.itemId))
            {
                urlString.Append("id", this.itemId);
                urlString.Append("db", this.itemDb);
                urlString.Append("lang", this.itemLang);
                urlString.Append("ver", this.itemVer);
                if ((bool)(args.Properties["UsesBrowserWindows"] ?? (object)false))
                    urlString.Append("cfs", "1");
            }
            urlString.Append("scriptId", this.scriptId);
            urlString.Append("scriptDb", this.scriptDb);
            SheerResponse.ShowModalDialog(urlString.ToString(), "400", "260", "", true);
            args.WaitForPostBack();
        }
    }
}

Using the isCustom, it allows to not refresh the item being moved but another item. In this case, I am refreshing the default Home item. You may need to add a certain logic to know which parent item needs to be refresh.

I will deep dive more into it and share any additional info if found.

Once you have the above code, you need to patch the config file for the command item:executescript. The current path of the config file is at App_Config/Include/Spe/Spe.config.

UPDATE #1

I blog about the above at Sitecore Powershell – Reload Item

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.