Access is denied writing to file from ExtendScript

35 Views Asked by At

I'm trying to write an ExtendScript script for Photoshop 2024. I am using app.system() to execute other programs. I can't figure out how to get a script like that to write a file. I can't get a > redirection to write a file nor can I get a Python script to write a file.

For example, app.system("echo hi > tests.txt; & pause") will produce the following output:

Access is denied.
Press any key to continue . . .

Whereas, app.system("echo hi; & pause") will produce this:

hi;
Press any key to continue . . .

I've tried all manner of paths including ones in Folder.temp and they all fail similarly.

I've even tried opening the file first in ExtendScript via f.open("w") before running my script, and that fails with The process cannot access the file because it is being used by another process.

This is preventing me from having external programs do work and save their results to a file for me to read in my ExtendScript. It is also preventing me from writing out batch or Python files to execute via app.system().

1

There are 1 best solutions below

0
cjbarth On

@Yuri Khristich gave me a huge hint to solving this. He said:

I just tried app.system("echo hi > tests.txt; & pause") and got the same error. Then I tried app.system("echo hi > d:\\tests.txt; & pause") and it works just fine. I believe the problem has to do with access to the root folder of the drive C.

Even if running my script as an administrator, I still can't write to the C: drive. Since that is where the files live, I had to get clever with drive letters to work around this. I ended up creating a function that will take any path and map it to an unused drive letter so that I can work around this strange limitation.

function mapNextAvailableDriveLetter(path) {
  var driveLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

  for (var i = 0; i < driveLetters.length; i++) {
    var result = app.system("subst " + driveLetters[i] + ': "' + path + '"');
    if (result === 0) {
      return driveLetters[i];
    }
  }

  alert("Unable to map a drive letter to " + path);
  exit();
}

I pair that function with a function to undo this when my script ends:

function removeSubstDriveLetters() {
  var driveLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  var cmd = "@echo off";

  for (var i = 0; i < driveLetters.length; i++) {
    cmd = cmd + " & subst " + driveLetters[i] + ": /D >nul 2>nul";
  }

  app.system(cmd);
}

I even use this to get access to a temp folder like so: mapNextAvailableDriveLetter(Folder.temp.fsName).

With these two functions I can call external utilities and have them write their output to a file that I can read with ExtendScript. I can also create scripts that I can run via a call to app.system(). This greatly extends the ability of my ExtendScript to do work beyond just working with Photoshop.