• Global community
• Language:
• Deutsch
• English
• Español
• Français
• Português
• 日本語コミュニティ
Dedicated community for Japanese speakers
• 한국 커뮤니티
Dedicated community for Korean speakers
• Getting the path of linked (smart) object / PS Bug...

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

Explorer ,
Mar 31, 2017 Mar 31, 2017

Copied

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:

  if (app.documents.length)      {        var doc = app.activeDocument;        for (var ilayer = 0; ilayer < doc.artLayers.length; ilayer++)        {          var layer = doc.artLayers[ilayer];          if (layer.kind == LayerKind.SMARTOBJECT)          {              var ref = new ActionReference();          ref.putIdentifier(charIDToTypeID('Lyr '), layer.id );                var desc = executeActionGet(ref);          var smObj = desc.getObjectValue(stringIDToTypeID('smartObject'));          var localFilePath = smObj.getPath(stringIDToTypeID('link'));          }        }    }
TOPICS
Actions and scripting

Views

5.0K

Likes

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
18 Replies 18
LEGEND ,
Mar 31, 2017 Mar 31, 2017

Copied

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 {

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 eventsapp.bringToFront();// ensure at least one document openif (!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

Likes

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
New Here ,
Mar 20, 2018 Mar 20, 2018

Copied

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 .

Likes

Report

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

Copied

Hi

Use this code:

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

Likes

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
New Here ,
Mar 20, 2018 Mar 20, 2018

Copied

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.

Likes

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
New Here ,
Mar 20, 2018 Mar 20, 2018

Copied

Nevermind, I got the selected layer with this -

app.activeDocument.activeLayer=app.activeDocument.artLayers.getByName("bluesock");

Thanks for the time & help though.

Likes

Report

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

Copied

To select a layer by name use this function:

function makeLayerActiveByName(name) {    (ref = new ActionReference()).putName( sTID('layer'), name);    (desc = new ActionDescriptor()).putReference( cTID('null'), ref ), desc.putBoolean( cTID('MkVs'), false );    executeAction( sTID('select'), desc, DialogModes.NO );}

Likes

Report

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

Copied

Hey - nice to see you here again. I just had to link a topic where you marked my answer as correct, as I if I am right r-bin​ showed you there how to check path of Linked Placed Layer. You simply came up now in good time btw I just noticed I have edited last post of final sentence in that topic you did not see yet. Could you please finally answer to my question?

Re: Updating SmartObject Layer Comps according to their names

Likes

Report

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

Copied

Actions can not use logic without using a script or using interactive steps so you can add the logic to choose the replacement etc.  If you want to completely automate your process you would need to script it.

I think if you look at Photoshop's menu Layer>Smart Objects>option  you will see what your options are for what you want to do.  Keep in mind though all Smart Object layers have an associated transform for the layers content that is not replaced or change if you update the layers object or replace it.  The Size and resolution of the object must not be changed for the associated transform to work correctly. The object need to be the correct size.

As far as I know you would either replace the smart object layers Object or Edit the Linked Files and change its content.  Relink to may also be an option I have never seen it scripted and I have never used placed linked files.

In a recent thread c.pfaffenbichler posted some code to open and edit a smart Object layer.  Re: Batch replace smart objects in mockup file

If you find the  object is a local linked image file you may be able to just open the file in  Photoshop and change the documents content and then save the linked file over itself.  When your script ends. I would expect Photoshop would Updated the Smart Object layers content for the linked file has changed.   That may be just like c.pfaffenbichler would do opening the smart object and editing it.  If the liked image file however, was a .svg or .ai file Illustrator may open if you open the linked file in either case and your script could not do the AI processing. If it was a Camera RAW file object ACR may open and you will not be able to change the image.  The may be pit falls one could fall into trying to edit the smart object IMO.  All Smart Object are not the same.  They are your Assets you should know what the objects are thate you are working with.]

JJMack

Likes

Report

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

Copied

John,

The original processSmartObj function used to work but no longer does, could this bve due to an update in Photoshop? If so I don't suppose you or someone else could probvided a function that does the same thing?

Thanks
Anthony

Likes

Report

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

Copied

Everything works.

Are you sure you are using it correctly? Does the function take as an argument a layer that is a linked smart object? Does the layer refer to a file on disk or from a library in the cloud? Are you getting some kind of error or is the function returning an empty value?

Likes

Report

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

Copied

Calling the function as a one liner via Visual Studio with the active document and active layer a linked smart object as I have always done in the past.

I have take the two lines out of the try/catch stament in order to force the error as shown at the bottom. otherwise it returns "" as the variable is defined in the fist part of the function.

The smart linked object is on a local network using an drive letter not UNC.

Likes

Report

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

Copied

Are you using macOS? The fact is that when opening a file, the paths of lost smart objects in Windows and macOSare interpreted differently (Photoshop in windows saves the path to the file, Photoshop for macOSloses the path to the file, but leaves its name)

Try this:

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.getString(stringIDToTypeID('fileReference'));
alert("Layer " + obj.name + ' linked file is"' + localFilePath + '"');
}
catch (e) { }
return localFilePath;
}

You can also look at the topic in which I suggested a script to update the lost paths of linked smart objects:  Is there an option that shows me a list with all smart objects paths?  (I don’t remember how up-to-date the code is, the latest version is available in my github repository Layers -> Layers - relink layers 2.jsx)

Likes

Report

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

Copied

Thanks, using windows.

That function now returns the file name which is what I'm looking for. - thank-you.

Inceidently I found you Linked_Files Script this morning, looks great, unfortunatly I couldn't us it for my sceneario as the the file name actually changes eg.  3912_04_D25066.Alpha.0000.png would change to  4930_04_D25066.Alpha.0000.png

Likes

Report

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

Copied

Run the code and look in the debug window for the structure of the descriptor (is there a path to the file at all, if so, in which variable it is written):

#target photoshop
s2t = stringIDToTypeID;

(r = new ActionReference()).putProperty(s2t('property'), p = s2t('smartObject'));
r.putEnumerated(s2t('layer'), s2t('ordinal'), s2t('targetEnum'));
(d = new ActionDescriptor()).putObject(s2t('object'), s2t('object'), executeActionGet(r));
\$.writeln(executeAction(s2t('convertJSONdescriptor'), d).getString(s2t('json')));

Likes

Report

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

Copied

Looks like it is returned on the 'link' variable:

Likes

Report

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

Copied

@Anthony L. Cityscape, try this:

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.getType(stringIDToTypeID('link')) == DescValueType.ALIASTYPE ?
alert("Layer " + obj.name + ' linked file is"' + localFilePath + '"');
}
catch (e) { }
return localFilePath;
}

to @r-bin , тебе встречались ситуации, когда путь к смарт-объекту был в виде string, а не в виде пути? Это можно как-то вопроизвести?

Likes

Report

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

Copied

Yes that worked with full path.

Thank-you.

Likes

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Valorous Hero ,
Jan 20, 2023 Jan 20, 2023

Copied

LATEST

to @r-bin , тебе встречались ситуации, когда путь к смарт-объекту был в виде string, а не в виде пути? Это можно как-то вопроизвести?

By @jazz-y

Типа переименовываешь папку с файлом. И в таком броукен объекте путь становится строкой.

Likes

Report

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