[bug] Sometimes adding multiple descriptors to a batchPlay doesn't work correctly

I’ve had a few occurrences where using batch play with multiple descriptors in the same batch play doesn’t work as it should. Splitting it up into multiple batchPlay descriptors fixes the issue. One time, it worked correctly on my PC and not Mac but can’t remember which exact descriptor that was.

Here is one example that I just ran into. In this case, it is a pretty specific situation that doesn’t work correctly. I have a 1 layer file that is NOT a background layer. I’m adding a new layer and moving the layer to the bottom. When putting both descriptors into the same batchPlay, it will create the new layer but it won’t move it to the bottom. However, if I split it out into 2 batchPlay descriptors it works correctly.

I thought initially that maybe the descriptors within the batch play were running asynchronously with each other and the move was happening before the new layer could be created. To test this, I ran the same batch play with a document that had 2 layers to start with to see if the top layer moved to the bottom before the new layer was created. However, in that case, it runs correctly to create a new layer and move it to the bottom below the other 2 layers.

Here is the code that doesn’t work. Again, this doesn’t work ONLY if running on a single layer document. Of coarse, the single layer isn’t a background layer.

const batchPlay = require("photoshop").action.batchPlay;    
    
await batchPlay(
[
   {
      "_obj": "make",
      "_target": [
         {
            "_ref": "layer"
         }
      ],
      "using": {
         "_obj": "layer",
         "name": "Background Image"
      },
      "_isCommand": true,
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   },
   {
      "_obj": "move",
      "_target": [
         {
            "_ref": "layer",
            "_enum": "ordinal",
            "_value": "targetEnum"
         }
      ],
      "to": {
         "_ref": "layer",
         "_enum": "ordinal",
         "_value": "back"
      },
      "_isCommand": true,
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});    

Here is the modified version that works for a single layer document. The descriptors are identical, just in 2 batchPlay commands.

const batchPlay = require("photoshop").action.batchPlay;

await batchPlay(
[
   {
      "_obj": "make",
      "_target": [
         {
            "_ref": "layer"
         }
      ],
      "using": {
         "_obj": "layer",
         "name": "Background Image"
      },
      "_isCommand": true,
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});    
    
await batchPlay(
[
   {
      "_obj": "move",
      "_target": [
         {
            "_ref": "layer",
            "_enum": "ordinal",
            "_value": "targetEnum"
         }
      ],
      "to": {
         "_ref": "layer",
         "_enum": "ordinal",
         "_value": "back"
      },
      "_isCommand": true,
      "_options": {
         "dialogOptions": "dontDisplay"
      }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});    

I’ve had similar issues a couple of other times and if I can figure out which exact descriptors they were I will post an update. Right now, I am gun shy to use multiple descriptors in the same batchPlay because I’m afraid it may work OK on my computer but not on all of the users computers. Therefore, I have started to just use one descriptor per batchPlay command. Hope this info help for the developer team to troubleshoot.

To create a layer below active one, add "below": true to a descriptor

You can achieve this by clicking a new layer button in layers panel while holding down Ctrl

1 Like

Thanks for the tip. I was unaware of that and I will try it out for sure. I already have a work-around for it but the way you indicate would be less steps.

However, there is still a bug I think which is the reason I posted it hoping someone from the development team would see it. For the examples I posted, both should work the same. The fact that the one with 2 batchPlay commands works and the one with one batchPlay command doesn’t work (when applied to a single layer doc) means something is wrong, as far as I can tell anyway. I have seen other descriptors as well not work correctly when put together in batchPlay and then work correctly when separated.

Yes, that doesn’t fix a bug. I have similar issue with moving multiple layers (each descriptor to move different layer). I had to split them apart, because one batch just wouldn’t do the thing. I think there might be something wrong with layer as a target. It just won’t get the layer I need. It works correctly only if a layer is selected and only if it’s the only one descriptor in a batch. Same with setting layer color - you won’t be able to set different colors to different layers in one batch.

Have you seen where different computers act differently? I’ve been hesitant to release anything using multiple descriptors in a batchPlay at all, even if it seems to works. I’m pretty sure I saw one case where it worked OK on my PC but not on my Mac but I haven’t been able to repeat that and can’t remember which descriptor it was. For now, I’ve been building the plugins with only one descriptor per batch for all steps.

I’m into UXP (and Ps scripting overall) only for a couple of weeks and doing everything only on a single PC, so didn’t have opportunity to check on different machines, but I guess it’s not accidental that Adobe has this in their docs :slight_smile:

Sometimes you need to write different code depending upon whether your plugin is hosted on macOS or Windows

But anyway, so far I’ve encountered batchPlay issues only while working with layers. I have my simple layers plugin already done and will move to more complex one - will see what I find out then :smiley:

hi did you solve this issue ? I’m having the same problem - thanks

No, I just divided it out it into multiple descriptors when needed. I haven’t tested combining recently to see if it was fixed though. I just left it alone as it was working as is.

Just a couple of thoughts:

  1. Why
"modalBehavior": "fail"

instead of

"modalBehavior": "wait"

I can’t remember which is default, but I’ve been “wait”-ing for everything.

  1. I’ve also found instances where not only do I need to put batchPlay calls into multiple descriptors, but I also have to make Photoshop do some “get” batchPlay in between them to apparently give Ps enough time to catch up, or something. I’m not really sure why that happens, but doing a “get” seems to make it so the second batchPlay gets executed.

This post was originally made back in Dec, 2020. I have not really looked into this since then.

Fail is default for UXP version 1. But there were some bugs where Photoshop briefly goes into a modal state. So the work around was using wait. I converted everything to use wait quite a while ago. I had already broke out the batchPlay into multiple batchPlay commands before I figured out to convert everythign to wait. I didn’t test this again at that time and just left it with multiple batchplay commands. So I’m not sure if using wait would have produced a different result.

With UXP version 2, I believe that execute is default. With it set to wait, it will never run as it will be waiting forever since Photoshop is in a modal state when using executeAsModal for UXP API version 2.

I was planning to revisit this when I convert everything to version 2. For right now, since it is working with multiple batchPlay commands I wasn’t going to mess with it in version 1 since the plugins will be converting soon anyway…

With API 2 I’m setting “modalBehavior” and “synchronousExecution” and “historyStateInfo:” to “{ }” and letting Ps just use whatever is default and that seems to work. I’m not sure any of these items are even relevant anymore with API 2.

I am also using {} and letting it run as default.

I think the default is execute, but I’m not sure. It does use them because it will work using execute but won’t work with wait… at least when I tested a few months back. I can’t remember about fail (I think that didn’t work but can’t remember for sure).

In any case, using {} to set it to default seems best.