Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

How to make JSEngineRef work properly?

New Here ,
Jul 07, 2015 Jul 07, 2015

Hi,

I'm currently writing an automation plugin which should execute some javascript. In general it works, but I get some weird behaviour when executing certain javascript functions:

If I try to execute:

app.open(File("C:/Path/To/File.bmp"));

It will return the following error:

Error 8000: Cannot open the file because the open options are incorrect\rLine: 1\r->  app.open(File("C:/temp/bla_2.1000.bmp"));'

If I execute the exact same command from inside AdobeExtendToolkit it works as it should and just opens the image.

My first guess was, that it doesn't work, because I create the JSEngine in a different thread, but even if I run my evaluation method in the main thread the result is the same.

Now I think, that it doesn't sources some dependencies by default and I have to source them manually, but maybe I'm totally off the topic with this assumption.

I would be really grateful for any hint on this. Thanks,

Martin

Here is an exerpt of my code (its mostly based from this threadRe: Call Script through plug-in.😞

std::string AutomationPlugin::evaluateCommand(std::string command)

{

    this->inProgress = true;

   

    std::string answer = "";

    const char * jscode = command.c_str();

    ASErr err = 0;

    JSScriptingSuite2 * sScriptingSuite = NULL;

   

    /* get a new javascript engine */

    err = this->basicSuite->AcquireSuite( kJSScriptingSuite, kJSScriptingSuiteVersion2, (const void**)&sScriptingSuite);

    if (sScriptingSuite == NULL)  //Also support Photoshop CS1-CS4 and Elements 6-10

    {

        err = this->basicSuite->AcquireSuite( kJSScriptingSuite, kJSScriptingSuiteVersion1, (const void**)&sScriptingSuite);

    }

    if  (sScriptingSuite == NULL)

    {

        this->inProgress = false;

        this->reply = "Error: ScriptEgine was not available!";

        return this->reply;

    }

   

    JSEngineRef engineRef = NULL;

    err = sScriptingSuite->CreateEngine( &engineRef );

   

    while (sScriptingSuite->ScriptIsRunning())

    {

        // .. wait until all other scripts are done ..

    }

   

    /* source some additional functions in external javascript files */

    std::string scopeCmd = this->getScopeCommand();

    std::wstring wideScopeCmd = this->strToWstr(scopeCmd);

    const ASUnicode * scopeResult = NULL;

    err = sScriptingSuite->ExecuteScript(engineRef, (ASUnicode *)wideScopeCmd.c_str(), kJSExecutionModeNoDebug, &scopeResult);

   

    /* if engine was found without an error.. */

    if ( err == kSPNoError )

    {

        //Convert ascii to unicode

        this->log(1, command);

        std::wstring wideCommand = this->strToWstr(command);

        std::wstring wideAnswer;

        const ASUnicode * result = NULL;

        /* THIS IS WHERE THE ERROR HAPPENS */

        err = sScriptingSuite->ExecuteScript(engineRef, (ASUnicode *)wideCommand.c_str(), kJSExecutionModeNoDebug, &result);

       

        wideAnswer = (wchar_t*)result;

        answer = this->wstrToStr(wideAnswer);

       

        if ( err != kSPNoError )

        {

            this->inProgress = false;

            this->reply = "ERROR: " + answer;

            return this->reply;

        }

    }

    else

    {

        this->inProgress = false;

        this->reply = "ERROR: " + answer;

        return this->reply;

    }

   

    if (engineRef)

    {

        sScriptingSuite->DeleteEngine( engineRef );

    }

    this->inProgress = false;

    this->reply = answer;

    return this->reply;

   

}

TOPICS
SDK
643
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
New Here ,
Jul 13, 2015 Jul 13, 2015

Hi again,

after some debugging I found out, that it is a threading issue. I found out, that if I trigger the kPSPhotoshopCaller/kPSDoIt caller-selector combination. The plugin gets loaded in the current thread instead of the main. But if trigger the same caller/selector combination from the javascript interface in the ExtendScript Toolkit it gets executed in the main thread and works.

That leads me to another question, how can I trigger the doIt function from another thread to be started in the main thread?

Any help would be appreciated!

Thanks.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Jul 24, 2015 Jul 24, 2015

How are you doing this " trigger the kPSPhotoshopCaller/kPSDoIt" you should be playing an action and letting Photoshop do the caller/selector workflow.

You need to be doing everything on the main thread. Photoshop is not thread save regarding plug-in execution.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Aug 10, 2015 Aug 10, 2015
LATEST

I use the following hack to make Photoshop react to the kPSDoIt. As you mentioned I can't play an action in the second thread, as this will fail, because Photoshop isn't thread safe with API-commands. What worked for me is making my plugin scriptable, then opening a jsScriptEngine in the second thread and trigger the action via the scriptingEngine. Using this workaround Photoshop will call the doIt callback of my plugin in main thread. Luckly that seems to works without a problem.. It's not nice, but it does the job.

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines