Skip to main content
Participant
December 23, 2009
Question

Placing a file in an Action, pathing issues

  • December 23, 2009
  • 1 reply
  • 2507 views

I have created an action that will Place several local files into a Photoshop Document. I have them stored in the Presets/Actions folder for Photoshop CS3.

Here is the example path: Macintosh HD:Applications:Adobe Photoshop CS3:Presets:Actions:BROWSERS:firefox:botBar.png

This works fine for me (of course), however I want others to be able to use the Action without relinking. Is it possible to edit the path to be relative to the .atn file (and does it even work like that?)

Theory:

So I have my browsers.atn file in the roof of Adobe Photoshop CS3/Presets/Actions and my graphics in Adobe Photoshop CS3/Presets/Actions/Browsers/firefox/file.png. Would I be able to link to it like: Browsers/firefox/file.png?

Sorry if this is confusing. If this won't work, do I have any other options?

This topic has been closed for replies.

1 reply

Inspiring
December 23, 2009

As I understand it paths in action can't be relative.

But Xbytor has code that can be used as in install script that will place the image files where you want them, edit the paths in the action to those new paths, then load the action. The code is part of xtools http://sourceforge.net/projects/ps-scripts/files/xtools/

Participant
December 23, 2009

This either won't work or is above my skill level. I thought I was close at several points but I couldn't get it to do what I wanted. I also tried converting it to XML and editing the path that way, that didn't work either. Thank you for your feedback and help.

Participant
December 28, 2009

Here is what works for me.

Create a folder for your installer.

Create a sub folder named 'files' and one named 'xtools'.

Put the script you want to install along with any image resources in the 'files' subfolder, you can also put atn files that don't need path correction in this folder.

Copy the ChangePaths-1_1.jsx to the 'xtools' folder.

Convert the atn files that do need path conversions to XML. Add the suffix '-in' to those xml files i.e. 'actionName-in.xml'. Once converted place in the 'files' folder with the others.

Copy the following script and name it 'Installer-1_2.jsx'. Put that file in the main folder.

// needs files to install placed in files sub folder
// ChangePaths-1_1.jsx in xtools sub folder, any actions that have
// paths recorded need to be convert to xml with '-in'
// added to the base name. Do not include those atn files
// Action sets that don't have paths can be placed in files
// as atn
//
//
#target photoshop
//
// Installer.jsx
//
// $Id: Installer.jsx,v 1.2 2009/02/02 19:48:34 anonymous Exp $
// Copyright: (c)2009, xbytor
// License: http://creativecommons.org/licenses/LGPL/2.1
// Contact: xbytor@gmail.com
//

RELEASE = "v1.2";
CHANGEPATHS_SCRIPT = "ChangePaths-1_1.jsx";

function throwFileError(f, msg) {
  if (msg == undefined) msg = '';
  Error.runtimeError(9002, msg + '\"' + f + "\": " + f.error + '.');
};

isCS5 = function()  { return !!app.version.match(/^12\./); };
isCS4 = function()  { return !!app.version.match(/^11\./); };
isCS3 = function()  { return !!app.version.match(/^10\./); };
isCS2 = function()  { return !!app.version.match(/^9\./); };

isCompatible = function() {
  return isCS2() || isCS3() || isCS4();
};

isWindows = function() {
  return $.os.match(/windows/i);
};
isMac = function() {
  return !isWindows();
};
isVista = function() {
  return $.os.match(/vista/i);
};
isVista64 = function() {
  return $.os.match(/vista\/64/i);
};
isPhotoshop = function() {
  return app.name.match(/photoshop/i);
};
listProps = function(obj) {
  var s = '';
  for (var x in obj) {
    s += x + ":\t";
    try {
      var o = obj;
      s += (typeof o == "function") ? "[function]" : o;
    } catch (e) {
    }
    s += "\r\n";
  }
  return s;
};
XStdlib = function() {};       // Let's borrow some stuff....
XStdlib.logStr = '';
XStdlib.log = function(msg) {
  var file;

  if (!XStdlib.log.enabled) {
    return;
  }

  if (!XStdlib.log.filename) {
    return;
  }

  if (!XStdlib.log.fptr) {
    file = new File(XStdlib.log.filename);
    //if (file.exists) file.remove();
    if (!file.open("w")) {
      Error.runtimeError(19, "Unable to open log file " + file + ": "
                          + file.error);
    }
    file.seek(0, 0); // jump to the end of the file
    if (isMac()) {
      file.lineFeed = "unix";
    }
    XStdlib.log.fptr = file;

  } else {
    file = XStdlib.log.fptr;
    if (!file.open("e"))  {
      Error.runtimeError(19, "Unable to open log file " + file + ": "
                          + file.error);
    }
    file.seek(0, 2); // jump to the end of the file
  }
 
  XStdlib.logStr += msg + '\r\n';
  if (!file.writeln(new Date() + " - " + msg)) {
    Error.runtimeError(19, "Unable to write to log file " + file + ": "
                       + file.error);
  }
 
   file.close();
};
XStdlib.log.filename = undefined; //"~/logfile.txt";
XStdlib.log.enabled = true;

XStdlib.exceptionMessage = function(e) {
  var str = '';
  var fname = (!e.fileName ? '???' : decodeURI(e.fileName));
  str += "   Message: " + e.message + '\n';
  str += "   File: " + fname + '\n';
  str += "   Line: " + (e.line || '???') + '\n';
  str += "   Error Name: " + e.name + '\n';
  str += "   Error Number: " + e.number + '\n';

  if (e.source) {
    var srcArray = e.source.split("\n");
    var a = e.line - 10;
    var b = e.line + 10;
    var c = e.line - 1;
    if (a < 0) {
      a = 0;
    }
    if (b > srcArray.length) {
      b = srcArray.length;
    }
    for ( var i = a; i < b; i++ ) {
      if ( i == c ) {
        str += "   Line: (" + (i + 1) + ") >> " + srcArray + '\n';
      } else {
        str += "   Line: (" + (i + 1) + ")    " + srcArray + '\n';
      }
    }
  }

  if ($.stack) {
    str += '\n' + $.stack + '\n';
  }

  return str;
};
XStdlib.btExec = function(code, btapp) {
  if (!btapp) { btapp = BridgeTalk.appSpecifier; }

  BridgeTalk.bringToFront(btapp);

  var bt = new BridgeTalk();
  bt.target = btapp;
  bt.body = code;
  bt.send();
};


XStdlib.PRESETS_FOLDER =
  new Folder(app.path + '/' +
             localize("$$$/ApplicationPresetsFolder/Presets=Presets"));
XStdlib.SCRIPTS_FOLDER =
  new Folder(app.path + '/' +
             localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts"));

//
// Options
//
Options = new Object();
Options.testMode = false;

Options.psScriptsFolder = XStdlib.SCRIPTS_FOLDER;
Options.myPicturesFolder = undefined; // created in checkConfig
Options.filesFolder = undefined;      // created in checkConfig
Options.xtoolsFolder = undefined;     // created in checkConfig
Options.atnScript = undefined;        // created in checkConfig
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// need to set Options.name before using installer
Options.name = '';
Options.LOG_FILE = "~/" + Options.name + "-installer.log";
Options.LOG_ENABLED = true;

//
// Installer
//
Installer = function() {
};
Installer.logstr = '';
Installer.log = function(str) {
  Installer.logstr += str;
};
Installer.getScriptFolder = function() {
  return Installer.getScriptFile().parent;
};
Installer.getScriptFileName = function() {
  var f = Installer.getScriptFile();
  return (f ? f.absoluteURI : '');
};
Installer.getScriptFile = function() {
  if (!isCompatible()) {
    return undefined;
  }

  var path = '';

  if (isCS2()) {
    var dbLevel = $.level;
    $.level = 0;
   
    try {
      some_undefined_variable;
    } catch (e) {
      path = e.fileName;
    }
   
    $.level = dbLevel;

  } else {
    path = $.fileName;
  }

  return new File(path);
};
Installer.loadActionFile = function(file) {
  XStdlib.log("Loading action file: " + decodeURI(file.fsName));
  Installer.loadActionFiles([file]);
  XStdlib.log("Loading action file completed.");
  return true;
};
Installer.loadActionFiles = function(files) {
  XStdlib.log("Loading action file: " + decodeURI(files));
  for (var i = 0; i < files.length; i++) {
    var file = files;
    XStdlib.log("Action files: " + decodeURI(file));
    XStdlib.btExec('app.load(new File("' + file.absoluteURI + '"));');
  }
  XStdlib.log("Loading action files completed.");
  return true;
};
Installer.createActionFiles = function(script, xmlFiles, newPath) {
  for (var i = 0; i < xmlFiles.length; i++) {
    var infile = xmlFiles;
    var outfile = new File(infile.parent + '/' +
                           infile.name.replace(/\-in.xml$/i, ".atn"));

    XStdlib.log("Converting action file: " + decodeURI(infile.fsName));

    var estr = "//@show include\r\n";

    estr += '//@include "' + script + '";\r\n';
    estr += "function main() {\r\n";
    estr += "  changePaths(\"" + infile + "\", \"";
    estr += outfile + "\", \"" + newPath + "\");\r\n";
    estr += "};\r\n";
    estr += 'main()';

    eval(estr);
  }
  return true;
};

Installer.run = function() {
  var inst = new Installer();
  var opts = Options;

  return inst.install(opts);
};
Installer.prototype.install = function(opts) {
  var self = this;

  // Check the package folder and the Photoshop and Bridge folders for sanity
  if (!self.checkConfig(opts)) {
    return false;
  }

  var cstr = (opts.name + " " + RELEASE + " will be installed at:\r\n\t" +
              decodeURI(opts.psScriptsFolder.fsName) +
              "\r\n\r\nand images at:\r\n\t" +
              decodeURI(opts.myPicturesFolder.fsName) + "\r\n\r\n" +
              "Do you wish to continue?");

  if (!confirm(cstr)) {
    return false;
  }

  var folder = opts.filesFolder;
  var imageFiles = folder.getFiles("*.psd");
  if (!self.copyFiles(imageFiles, opts.myPicturesFolder)) {
    return false;
  }

  var scripts = folder.getFiles("*.jsx");
  if (!self.copyFiles(scripts, opts.psScriptsFolder)) {
    return false;
  }

  var atnXmlFiles = folder.getFiles("*.xml");
  if (!Installer.createActionFiles(opts.atnScript, atnXmlFiles,
                                   opts.myPicturesFolder)) {
    return false;
  }

  var atnFiles = folder.getFiles("*.atn");
  if (!Installer.loadActionFiles(atnFiles)) {
    return false;
  }
 
  return true;
};

Installer.prototype.checkConfig = function(opts) {
  var self = this;

  XStdlib.log("Checking configuration...");
  XStdlib.log("Checking for Photoshop");
  if (!isPhotoshop()) {
    return self.error("Please run this script from Photoshop.");
  }
  XStdlib.log("Photoshop good!\r\n");

  XStdlib.log("Checking for CS2/CS3/CS4");
  if (!isCompatible()) {
    return self.error(opts.name + " is compatible with only " +
                      "Photoshop CS2/CS3/CS4.");
  }
  XStdlib.log("CS2/CS3/CS4 good!\r\n");

  XStdlib.log("Checking for Photoshop Scripts folder: " +
             decodeURI(opts.psScriptsFolder));
  if (!opts.psScriptsFolder.exists) {
    return self.error("Photoshop Scripts folder not found.\r\nExpected: " +
                      opts.psScriptsFolder);
  }
  XStdlib.log("Photoshop Scripts folder good!\r\n");

  XStdlib.log("Checking for 'My Pictures' folder...");

  var docFolder = Folder.myDocuments;
  if (!docFolder) {
    if (isMac()) {
      docFolder = new Folder("~/Documents");
    } else {
      docFolder = new Folder("~/My Documents");
    }
  }

  var picFolder = new Folder(docFolder + "/My Pictures");
  if (!picFolder.exists) {
    return self.error("\"My Pictures\" folder not found.\r\nExpected: " +
                      opts.myPicturesFolder);
  }
  opts.myPicturesFolder = picFolder;

  XStdlib.log("'My Pictures' folder good!");

  XStdlib.log("Checking installation package");

  opts.sourceFolder = Installer.getScriptFolder();

  opts.filesFolder = new Folder(opts.sourceFolder + "/files");

  if (!opts.filesFolder.exists) {
    return self.error("Bad installation package, folder not found:\r\n" +
                      decodeURI(opts.filesFolder));
  }
  opts.xtoolsFolder = new Folder(opts.sourceFolder + "/xtools");
  if (!opts.xtoolsFolder.exists) {
    return self.error("Bad installation package, folder not found:\r\n" +
                      decodeURI(opts.xtoolsFolder));
  }

  var script = new File(opts.xtoolsFolder + '/' + CHANGEPATHS_SCRIPT);
  if (!script.exists) {
    return self.error("Bad installation package, file not found:\r\n" +
                      decodeURI(script));
  }
  opts.atnScript = script.absoluteURI;

  return true;
};

Installer.prototype.error = function(msg) {
  var emsg = "Error: " + msg;

  XStdlib.log(emsg);
  alert(emsg);
  return false;
};

Installer.prototype.copyFile = function(srcFile, target) {
  var self = this;

  if (!(target instanceof Folder)) {
    Error.runtimeError(9002, "Internal Error: copyFile(" +
                        srcFile + ", " + target + ")");
  }

  if (!target.exists) {
    Error.runtimeError(9002, "The folder " + decodeURI(target.fsName) +
                        " does not exist.");
  }

  var testRO = new File(target + '/test.tmp');
  if (!testRO.open("w")) {
    var msg = ("The folder " + decodeURI(target.fsName) +
              " is 'readonly'. Please either invoke Photoshop " +
              "with Administrator permissions for installation " +
              "(use 'Run as adminstrator' on XP/Vista) or change the " +
              "permissions on the folder to allow the installer to " +
               "write files to that folder.\r\n\r\n");
    var emsg = XStdlib.exceptionMessage(new IOError()) + "\r\n\r\n" + msg;
       XStdlib.log(emsg);
       alert(msg);
       return false;
      
  } else {
    testRO.close();
       testRO.remove();
  }

  XStdlib.log("Copy file from " + decodeURI(srcFile) + " to " +
             decodeURI(target));
  var file = new File(target + "/" + srcFile.name);
  if (!srcFile.copy(file)) {
    var msg = "Copy failed: " + srcFile.error + "\r\n" + decodeURI(srcFile);
    if (file.exists) {
      msg += ("\r\n\r\nAn existing copy of this file exists and must be " +
              "removed manually before attempting installation.");
    }
    return self.error(msg);
  }
  return true;
};

Installer.prototype.copyFiles = function(src, target) {
  var self = this;

  XStdlib.log("\r\nCopying files from " + decodeURI(src) + " to " +
             decodeURI(target));

  var files;
  if (src instanceof Folder) {
    files = src.getFiles();
  } else if (src instanceof Array) {
    files = src;
  } else {
    Error.runtimeError(19, "src");
  }

  for (var i = 0; i < files.length; i++) {
    var file = files;
    if (file instanceof Folder) {
      continue;
    }
    if (!self.copyFile(file, target)) {
      return false;
    }
  }
  return true;
};

Installer.popup = function(title, str) {
  var w = new Window('dialog', title, [200,200,1000,750]);
  var t = w.add('edittext', [10,10,790,490], '',
                {multiline:true, readonly:true});
  t.text = str;
  w.add('button', [300,500,350,520], 'OK');
  w.show();
};

Installer.main = function() {
  XStdlib.log.filename = Options.LOG_FILE;
  XStdlib.log.enabled = Options.LOG_ENABLED;

  var rc = false;
  XStdlib.log("Start");
  XStdlib.log("Version: " + RELEASE);
  XStdlib.log("App: " + app.name);
  XStdlib.log("App Version: " + app.version);
  XStdlib.log("OS: " + $.os);

  try {
    rc = Installer.run();

  } catch (e) {
    var msg = (XStdlib.exceptionMessage(e) + "\"\r\n" +
               "Installation terminated.");
    XStdlib.log(msg);
    alert(msg);
  }

  XStdlib.log("\r\n" + Options.name + " Installation completed status: " +
             (rc ? "good." : "*** failed ***"));
  XStdlib.log("Stop");

  if (confirm("Installation " + (rc ? "succeeded!" : "failed!") +
              "\r\n\r\nView log?")) {

    Installer.popup(Options.name + " Installation: " + XStdlib.log.filename,
                     XStdlib.logStr);
  }

  if (rc) {
    alert("You will need to restart Photoshop to enable " + Options.name + ".");
  }
};
Installer.main();

"Installer.jsx";
// EOF

Note it expects any image files to be psd files. You can change the mask in the line var imageFiles = folder.getFiles("*.psd"); to use other formats.

The install needs to be run from Photoshop and you might need to be logged is a administrator with some OSs.

The install script and concept is from Xbytor.


Thanks for the help. I have set the above install script up, set the Options.name but it is hanging up on the "My Pictures" aspect.

Error: "My Pictures" folder not found...

I assume that the script looks for the "My Pictures" folder and if the computer dosen't have one, it creates it.

Is there any additional customizing I need to do to the file? I looked and fooled around with it but to be honest I don't have a lot of scripting experience.

I would love for the img files to be stored in the Actions folder in the Photoshop folder for the sake of keeping everything nice and tidy, but I won't have a problem with the "My Pictures" folder (if I can get the darn thing to work).

Sorry for being a pest.

edit: Looking at the log files, it says they are undefined. Then I see this, how would I define them in a way that would be platform independent?

Options.myPicturesFolder = undefined;      // created in checkConfig

Options.filesFolder = undefined;                // created in checkConfig

Options.xtoolsFolder = undefined;             // created in checkConfig

Options.atnScript = undefined;                 // created in checkConfig