Determine Smart Object Attributes - Linked - Embedded - Missing - Path
Copy link to clipboard
Copied
I've found a few older threads on Smart Objects, but none with a direct solution in this forum for getting smart object attributes.
Some of the older threads reference a try catch around placing a layer to determine if it's embedded:
executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO );
I did find this thread on Stack Overflow, and am wondering if there are any other direct methods of getting info from a smart object.
I've compiled a few separate scripts to determine the extension of the smart object, to evaluate if it's vector or raster.
Is there a more direct way to evaluate smart objects? I use script listener, but not well enough to understand how I can generate a true false value etc.
Explore related tutorials & articles
Copy link to clipboard
Copied
From the same link:
// Check Test Get Property for Linked Smart Object.jsx
/* Based on:
https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-jsx
*/
var ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
var so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));
if (so.getBoolean(stringIDToTypeID("linked"))) {
alert("Linked");
} else {
alert("Embedded");
}
Copy link to clipboard
Copied
Another one:
/*
https://stackoverflow.com/questions/63010107/get-a-smart-objects-layers-files-directory-source-in-jsx
*/
var mySO = getSmartObjectReference();
if (mySO.found) {
alert('Is linked: ' + mySO.linked + '\nFile Name: ' + mySO.fileRef + '\nFile Path: ' + mySO.filePath);
}
function getSmartObjectReference()
{
try
{
var smartObject = {
found: false,
fileRef: '',
filePath: '',
linked: false,
};
var ref, so;
ref = new ActionReference();
ref.putProperty(charIDToTypeID("Prpr"), stringIDToTypeID("smartObject"));
ref.putEnumerated(charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
so = executeActionGet(ref).getObjectValue(stringIDToTypeID("smartObject"));
smartObject.found = true;
smartObject.linked = so.getBoolean(stringIDToTypeID("linked"));
smartObject.fileRef = so.getString(stringIDToTypeID("fileReference"));
if (smartObject.linked) {
smartObject.filePath = so.getPath(stringIDToTypeID("link"));
} else {
smartObject.filePath = Folder.temp + '/' + smartObject.fileRef;
}
return smartObject;
}
catch (e)
{
alert(e);
return smartObject;
}
}
Copy link to clipboard
Copied
I've been using getSmartObjectReference(), wrapped in a loop that cycles through layers.
lyrSOInfo = getSmartObjectReference();
if(lyrSOInfo.filePath == '') alert("Linked File Is Missing")
if (lyrSOInfo.linked == true && lyrSOInfo.filePath != '') {
//Embed linked file
executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO );
}
By default it throws an error so I commented out alert(e), and I guess I could use found rather than testing the filePath directly.
Copy link to clipboard
Copied
What do you actually want to achieve?
Just a list of all linked SO, a list of the path’s of the linked files, …?
Copy link to clipboard
Copied
I'm evaluating each smart object in a file, and looking for something similar to InDesign's LinkStatus. When searching adobe forums, the tops hits that popped up were similar to the link/script below: https://community.adobe.com/t5/photoshop-ecosystem-discussions/file-information-for-smart-objects/m-...
Quoted from link:
var idplacedLayerConvertToEmbedded = stringIDToTypeID( "placedLayerConvertToEmbedded" );
executeAction( idplacedLayerConvertToEmbedded, undefined, DialogModes.NO );
theDoc.activeHistoryState = theDoc.historyStates[theDoc.historyStates.length-2];
alert ("linked")
getSmartObjectReference() works, but I wanted to ask on this forum as a recent answer also doesn't seem to be captured, at least the way I'm asking.
I'm using the link status/if statements to then trigger PS to embed linked Smart Objects.
Copy link to clipboard
Copied
Your refer to a thread from 2014; SO’s AM-accessibility has been improved over time, so that does not seem useful.
Have you seen this thread?
Copy link to clipboard
Copied
I'm evaluating each smart object in a file, and looking for something similar to InDesign's LinkStatus.
What do you actually mean? Please elaborate, post a meaningful screenshot/sketch …
Copy link to clipboard
Copied
Thanks for the link, I'll check it out.
Below is an excerpt of how I'm using the link status, since I've compiled from different scripts/functions it's not easy to show.
Please note, the below excerpts also utilize objectIsPsObject(SOlayer), in this script, but as it's lengthy I've omitted from this thread:
https://community.adobe.com/t5/photoshop-ecosystem-discussions/extendscript-photoshop-edit-contents-...
//Layer can be set with a loop for each active layer
layer = app.activeDocument.activeLayer;
/******
objectIsPsObject(layer) default determines as a raster smart object
*******/
if (layer.kind == LayerKind.SMARTOBJECT && objectIsPsObject(layer) == true) {
layer.rasterize(RasterizeType.ENTIRELAYER)
}
/******
objectIsPsObject(layer) anything remaining is assumed a vector smart object and will be embedded or rasterized if missing
******/
if (layer.kind == LayerKind.SMARTOBJECT && objectIsPsObject(layer) == false) {
lyrSOStat = psGetSmartObjectReference();
//Check if file is linked, and if it is embed it
//Must check that the file path is not empty or it will error out when trying to embed
if (lyrSOStat.linked == true && lyrSOStat.filePath != '') executeAction( stringIDToTypeID( "placedLayerConvertToEmbedded" ), undefined, DialogModes.NO);
//If FilePath is missing, rasterize the layer
if (lyrSOStat.filePath == '') layer.rasterize(RasterizeType.ENTIRELAYER);
}
Copy link to clipboard
Copied
Will you please tell me what you actually want to achieve?
A dialog with the information, text in the clipboard, a Panel, …?
Copy link to clipboard
Copied
Sorry for any confusion, I'm just asking if there is a more direct way to get link statuses for smart objects within a script and then run a function based on that.
In Indesign, there are 5 statuses LinkStatus.LINK_MISSING, LinkStatus.LINK_OUT_OF_DATE, LinkStatus.LINK_INACCESSIBLE, LinkStatus.LINK_EMBEDDED, and LinkStatus.NORMAL. I was asking to see if there is a photoshop equivalent.
I have yet to review the link you sent, though I did see the stack overflow link in there as well. Thanks again.
Copy link to clipboard
Copied
// 2024, use it at your own risk;
if (app.documents.length > 0) {
var theThings = collectSmartObjectsWithLayerComps();
var theString = "smart objects are";
for (var m = 0; m < theThings.length; m++) {
var thisOne = theThings[m];
theString = theString + "\n\n" + thisOne[0] + "\nis linked: " + thisOne[1];
if (thisOne[1] == true) {theString = theString + "\nlink missing: " + thisOne[2] + "\nlink changed; " + thisOne[3]}
};
alert (theString);
};
////////////////////////////////////
////// collect smart objects, probably based on code by paul, mike or x //////
function collectSmartObjectsWithLayerComps () {
// the file;
var myDocument = app.activeDocument;
// get number of layers;
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
var applicationDesc = executeActionGet(ref);
var theNumber = applicationDesc.getInteger(stringIDToTypeID("numberOfLayers"));
// process the layers;
var theLayers = new Array;
for (var m = 0; m <= theNumber; m++) {
try {
var ref = new ActionReference();
ref.putIndex( charIDToTypeID( "Lyr " ), m);
var layerDesc = executeActionGet(ref);
var layerSet = typeIDToStringID(layerDesc.getEnumerationValue(stringIDToTypeID("layerSection")));
var isBackground = layerDesc.getBoolean(stringIDToTypeID("background"));
// if not layer group collect values;
if (layerSet != "layerSectionEnd" && layerSet != "layerSectionStart" && isBackground != true) {
var theName = layerDesc.getString(stringIDToTypeID('name'));
var theID = layerDesc.getInteger(stringIDToTypeID('layerID'));
if(layerDesc.hasKey(stringIDToTypeID('smartObject'))) {
var soDesc = layerDesc.getObjectValue(stringIDToTypeID('smartObject'));
var theFileRef = soDesc.getString(stringIDToTypeID('fileReference'));
var theDocID = soDesc.getString(stringIDToTypeID('documentID'));
var isLinked = soDesc.getBoolean(stringIDToTypeID('linked'));
if (isLinked == true) {
var isMissing = soDesc.getBoolean(stringIDToTypeID('linkMissing'));
var isChanged = soDesc.getBoolean(stringIDToTypeID('linkChanged'));
} else {
var isMissing = undefined;
var isChanged = undefined;
};
/*var x = soDesc.getList(stringIDToTypeID("compsList"));
var theCompsList = soDesc.getObjectValue(stringIDToTypeID("compsList"));
if (theCompsList.count > 2) {
var theCompsList = theCompsList.getList(stringIDToTypeID("compList"));
var theSOComps = new Array;
for (var n = 0; n < theCompsList.count; n++) {
var thisOne = theCompsList.getObjectValue(n);
var compName = thisOne.getString(stringIDToTypeID("name"));
var compID = thisOne.getInteger(stringIDToTypeID("ID"));
var theComment = thisOne.getString(stringIDToTypeID("comment"));
theSOComps.push([compName, compID, theComment]);
};
theLayers.push([theName, theID, theFileRef, theDocID])
theLayers.push([theName, theID, theFileRef, theDocID, theSOComps])
};*/
theLayers.push([theName, isLinked, isMissing, isChanged, theID, theFileRef, theDocID])
}
}
}
catch (e) {};
};
return theLayers
};

