Skip to main content
johny roger
Inspiring
March 31, 2017
Question

Getting the path of linked (smart) object / PS Bug?

  • March 31, 2017
  • 1 reply
  • 7627 views

Hello All

i'm trying to read the path of the linked object/layer trough script. The path information seems to be available in the Layers properties panel (see screenshot 1).

When i try to use the command "reveal in finder" from within Photoshop, i do get an Error "Could not complete your request because of a program error."

So, i'm not able to use Scriptlistener to use the code for that.

Does anyone have a working AM code for this function available and knows why i do get this error on my side (on all psd documents i tried).

alert(app.activeDocument.activeLayer.filePath);

EDIT:

found this code that checks if there is a linked smart object and returns it's path.

Unfortunately i can't get it working like:

//Pseudocode:

If (activeLayer = linkedSmartobject)

{

var activeDesignPath = activeLayer.filePath;

} else {

// ignore ALL errors and continue (next layer will then be checked)

};

// Export/save as jpg to the root Folder of the linked smart object.

app.activeDocument.saveAs((new File(activeDesignPath + "/_Files Export/with GTO Background" +'/' + activeColor + ' ' + basename + ' ' + designDoc.activeLayer.name +'.jpg')),jpegOptions,true);

Original Script:

  1.   if (app.documents.length)   
  2.   {   
  3.     var doc = app.activeDocument;   
  4.     for (var ilayer = 0; ilayer < doc.artLayers.length; ilayer++)   
  5.     {   
  6.       var layer = doc.artLayers[ilayer];   
  7.       if (layer.kind == LayerKind.SMARTOBJECT)   
  8.       {   
  9.  
  10.         var ref = new ActionReference(); 
  11.         ref.putIdentifier(charIDToTypeID('Lyr '), layer.id ); 
  12.      
  13.         var desc = executeActionGet(ref); 
  14.         var smObj = desc.getObjectValue(stringIDToTypeID('smartObject')); 
  15.         var localFilePath = smObj.getPath(stringIDToTypeID('link'));   
  16.       }   
  17.     } 
  18.   }  
This topic has been closed for replies.

1 reply

JJMack
Community Expert
Community Expert
March 31, 2017

The code you found works for linked smart object layers it will through an error if the object is not a linked file. You can use a try catch to note the and ignore none linked smart object layers.

function processSmartObj(obj) {

  var localFilePath = "";

  var ref = new ActionReference();  

    ref.putIdentifier(charIDToTypeID('Lyr '), obj.id );  

    var desc = executeActionGet(ref);  

    var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));  

  try {

  var localFilePath = smObj.getPath(stringIDToTypeID('link')); 

  alert("Layer " + obj.name + ' linked file is"' +  localFilePath + '"');

  }

  catch(e) {}

  return localFilePath;

}

You could put some boilerplate around the process to structure the code an make it  more readable  for example process all layer in a document may look something like this.

/* ==========================================================

// 2017  John J. McAssey (JJMack)

// ======================================================= */

// This script is supplied as is. It is provided as freeware.

// The author accepts no liability for any problems arising from its use.

// enable double-clicking from Mac Finder or Windows Explorer

#target photoshop // this command only works in Photoshop CS2 and higher

// bring application forward for double-click events

app.bringToFront();

// ensure at least one document open

if (!documents.length) alert('There are no documents open.', 'No Document');

else {

  // declare Global variables

  //main(); // at least one document exists proceed

    app.activeDocument.suspendHistory('Some Process Name','main()');

}

///////////////////////////////////////////////////////////////////////////////

//                            main function                                  //

///////////////////////////////////////////////////////////////////////////////

function main() {

  // declare local variables

  var orig_ruler_units = app.preferences.rulerUnits;

  var orig_type_units = app.preferences.typeUnits;

  var orig_display_dialogs = app.displayDialogs;

  app.preferences.rulerUnits = Units.PIXELS;   // Set the ruler units to PIXELS

  app.preferences.typeUnits = TypeUnits.POINTS;   // Set Type units to POINTS

  app.displayDialogs = DialogModes.NO;     // Set Dialogs off

  try { code(); }

  // display error message if something goes wrong

  catch(e) { alert(e + ': on line ' + e.line, 'Script Error', true); }

  app.displayDialogs = orig_display_dialogs;   // Reset display dialogs

  app.preferences.typeUnits  = orig_type_units; // Reset ruler units to original settings

  app.preferences.rulerUnits = orig_ruler_units; // Reset units to original settings

}

///////////////////////////////////////////////////////////////////////////////

//                           main function end                               //

///////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////

// The real code is embedded into this function so that at any point it can return //

// to the main line function to let it restore users edit environment and end      //

/////////////////////////////////////////////////////////////////////////////////////

function code() {

  processArtLayers(activeDocument) 

}

function processArtLayers(obj) { 

    for( var i = obj.artLayers.length-1; 0 <= i; i--) {processLayers(obj.artLayers);} 

    for( var i = obj.layerSets.length-1; 0 <= i; i--) {processArtLayers(obj.layerSets); } // Process Layer Set Layers 

}

function processLayers(layer) {

  switch (layer.kind){

  case LayerKind.SMARTOBJECT : processSmartObj(layer); break;

  default : break; // none process layer types catch all

  }

}

//////////////////////////////////////////////////////////////////////////////////

// Layer Type Functions //

//////////////////////////////////////////////////////////////////////////////////

function processSmartObj(obj) {

  var localFilePath = "";

  var ref = new ActionReference();   

    ref.putIdentifier(charIDToTypeID('Lyr '), obj.id );   

    var desc = executeActionGet(ref);   

    var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));   

  try {

  var localFilePath = smObj.getPath(stringIDToTypeID('link'));  

  alert("Layer " + obj.name + ' linked file is"' +  localFilePath + '"');

  }

  catch(e) {}

  return localFilePath;

}

JJMack
hladdha123
Participating Frequently
March 20, 2018

Hi, I also tried getting the localfilepath with the snippet you shared, but do you know how can we replace this localFilepath with a new file or how do we relink it to other file stored on disk programmatically. If you can spare a couple of minutes, can you please have a look at - How to customize the linking file path in recorded photoshop actions. & try to help out .

hladdha123
Participating Frequently
March 20, 2018

Hi

Use this code:

(desc = new ActionDescriptor()).putPath( cTID( "null" ), new File( "C:\\Path\\to\\your\\file.psb" ) );

executeAction( sTID( "placedLayerRelinkToFile" ), desc, DialogModes.NO );

This will replace your selected linked file to another one.


One question though in this snippet I think we are grabbing the current selected layer & then replacing its contents.
Can we do a select layer by name first & then replace / relink the file in the same way as you are doing with executeAction()

or the alternate approach would be to

1) select a layer by name in photoshop programatically first,

2) then replace the selected files contents.


So, now (2) can be done with the snippet you shared, how can we get (1) done so that we can setup a batch process to replace & export relinked graphics.