Can I open a Photoshop file with UXP?

Yup!

The photoshop object supplies an open method that you can use to open a document. Since the document would be in your plugin’s folder, you can access it using getPluginFolder():


async function openTemplate() {
    const fs = require("uxp").storage.localFileSystem;
    const pluginFolder = await fs.getPluginFolder();
    const theTemplate = await pluginFolder.getEntry("yourFile.psd");
    
    const app = require("photoshop").app;
    await app.open(theTemplate);
}

3 Likes

OMG! It worked perfectly. :smiley:

Thank you. You’re always awesome… haha
I’ll improve my script and make it a Plugin. :heart_eyes:

1 Like

Hi @kerrishotts,
How would I go about getting a file from a subfolder of the pluginFolder?

I’ve created a subfolder to hold my photoshop template files and I’ve tried a few things to access that subfolder without any luck. Any clues?

I’ve tried await pluginFolder.getEntry('/subfolder/template.psd') but that crashes PS.
Do I have to use BatchPlay?

John

1 Like

Nevermind. I found another post with the answer. I just had to remove the first forward slash. :roll_eyes:

Thanks anyway.

2 Likes

Do you have the crash log(s)/error messages when using the leading slash?

I’ve tried recreating the crash but can’t replicate it now. I was a bit frustrated with my code at the time so it could have been something completely unrelated and I didn’t notice it.

John

Sorry is there anyway to change the props of the importing file? like changing sizes for a SVG file.

Heya!

Been busting trying to retrieve the nativePath for getPluginFolder().

All I want to do is get the users plugin path, so I can pass that path into a Displace effect such as:

async function init() {
    //other code
    async function action1() {
        const fs = require('uxp').storage.localFileSystem;
        const df = await fs.getPluginFolder();
        // const token = df.getEntry("Map1.psd");
        let result;
        let command = [
            // Displace
            {
                "_obj": "displace",
                "horizontalScale": 50,
                "verticalScale": 50,
                "displacementMap": {
                    "_enum": "displacementMap",
                    "_value": "stretchToFit"
                },
                "undefinedArea": {
                    "_enum": "undefinedArea",
                    "_value": "repeatEdgePixels"
                },
                "displaceFile": {
                    "_path": "token",
                    "_kind": "local"
                },
                "_isCommand": true,
                "_options": {
                    "dialogOptions": "dontDisplay"
                }
            }
        ]
        console.log(df.nativePath);
        result = await psAction.batchPlay(command, {});
        console.log(df.nativePath);
    }
    await require("photoshop").core.executeAsModal(action1, {"commandName": "Action Commands"});
}

Any ideas?
Back in CEP days I used to be able to do something like:
var extensionRoot = csInterface.getSystemPath(SystemPath.EXTENSION) to return the path, which I could send to that batchPlay script for the UXP version?

It’s a static displacement map PSD file so can live in the packaged plugin directory so I don’t have to ask for permissions of user to use/open. Read only.

Please Help! Still learning JS!
much love,

Hi Kerri,
I tried this snippet and I am unable to get it to run. I’ve have zero ideas of why considering there are no errors produced. It simply ignores the app.open() request.
Diving down the forum rabbit hole I see that v23.3 it probably now needs executeAsModal() ??
If I’m correct, can you give me an idea how I would accomplish this simple task in the api 2 language?
Thanks in advance.

Not quite following what you’re trying to do, but this gets the native path to the plugin folder.

const fslocal = require('uxp').storage.localFileSystem;
const pluginFolder = await fslocal.getPluginFolder();
const pluginFolderPath = pluginFolder.nativePath;

But it looks like you’re code already logs that out to the console, so this probably isn’t the answer you’re looking for.

Heya @AnthonyK, thanks for the response. I am trying to accomplish the simplest of tasks - Open a .psd file programmatically with a UXP plugin. Trying to find the exact code to do that now we need to use executeAsModal. @kerrishotts has the code up in this thread, but that doesn’t work now in API2 and we need to use executeAsModal. All my attempts to date do not work and the await function just seems to ‘wait’ indefinitely…

To use executeAsModal you need to first import it from photoshop and then you can pass it a function as its parameter to execute that code with Photoshop in a modal state.

// Imports
const { app, core } = require("photoshop");
const fs = require("uxp").storage.localFileSystem;

// Open document helper function
async function openDocument() {
  const pluginFolder = await fs.getPluginFolder();
  const theTemplate = await pluginFolder.getEntry("yourFile.psd");

  // The document is opened 
  await app.open(theTemplate);
}

// Main function - is async so that await can be used within
async function main() {
  // Passing openDocument function to executeAsModal to open file 
  await core.executeAsModal(openDocument);
}

// Run main function from inside try/catch for error handling
try {
  // Don't need to await because a) nothing to run after it and b) you can't anyway because top-level await is not allowed
  main();
} catch (error) {
  console.error(error);
  console.trace(error);
}

EDIT: Code edited to remove error inducing return statements and incorrect imports.

Heya @Timothy_Bennett,
Thanks for your response. I replied to a response in another thread and it the same. Not even the errors are being logged to the console. My environment must not be set up or something. Is it the manifest.json I am using?
Sorry for being a newbie.

That’s getting into guesswork territory - it would be better if you push your project to GitHub and share the repo or package it up as a .ccx in the Developer Console and send it to me via private message.
I’m happy to give it a look over and see it there’s anything in your code setup that’s arwy.

Thanks Tim,
Definitely able to do that, but my code is simply the uxp-template-ps-starter (package.json) and the same manifest you get with that option. I then paste in your code and change the “yourFile.psd” to the file that I wish to open.
I assumed that this would immediately open the file upon loading the plugin?

I can’t remember off the top of my head, but I think the starter project has an api1 manifest.
For api2 it should look like this:

{
  "id": <plugin id>,
  "name": <plugin name>,
  "version": "1.0.0",
  "main": "index.html",
  "host": [
    {
      "app": "PS",
      "minVersion": "22.0.0",
      "data": {
        "apiVersion": 2
      }
    }
  ],
  "manifestVersion": 4,

// Entrypoints etc...
}

It’s weird that you’re getting no errors though, IIRC you should get one saying that you’re using api1.

There’s also manifest 5 now. I haven’t had a chance to really explore it but I don’t think it’s that different from 4,.

Yup. Def no errors. The plugins seems to stop/pause/hang at every app.open call. Ive clearly got something strange going on.
When I return to the office, ill package my plugin and upload it and see if itll run on a system other than mine.

Feel free to send it to me if it’s still doesn’t work.

Hello! I’ve run into a similar problem that is described here, where I try to open an image inside executeModal, but nothing really happens.

My code is something like this:

const executeModal = async (targetFunction: (executionContext: ExecutionContext) => Promise<any>) => {
  try {
    await PSCore.executeAsModal(targetFunction, { commandName: 'User Cancel Test' });
  } catch (er) {
    console.log('error', er);
  }
};

const openFile = async (file: any) => {
  await executeModal(async executionContext => {
    const open = await PSApp.open(file);
  });
};

No error is caught, but the image is not opened inside photoshop. Is there a step that I’ve missed?

1 Like

I’m not too familiar with TS syntax but it looks to me like you’re not actually passing a function into your executeModal function.

I think you’re over complicating it by making an helper function for executeAsModal - as you don’t do any logic within that function it’s a bit redundant to make two function calls.

Personally, I’d make a helper function that encapsulates the whole file open process:

async function openFile(file) {
 await core.executeAsModal(async (file) => {
   await app.open(file)
 }
}
1 Like