Copy link to clipboard
Copied
Some days ago I needed to change my automation tool written in C# as Windows application. The reason was that we use Dropbox now and all pages opened on another computer have a whole bunch of missing links due to different Dropbox folder locations.
Updating links in Javascript is easy and if I do it from Indesign I use following script:
var alllinks = app.activeDocument.links;
for (var i = 0; i < alllinks.length; i++)
{
var cur_link = alllinks[i];
{
var m = cur_link.filePath.match(/.+Dropbox\\(.+)/);
if (m)
{
try
{
cur_link.relink(File('W:\\' + m[1]));
}
catch (e)
{ }
}
}
}
where W: is my Dropbox folder mapped as drive letter.
But as I tried to implement the same logic in my application using COM access
var allLinks = Doc.Links;
for (int i = 1; i <= allLinks.Count; i++)
{
Link l = allLinks[i];
if (l.Status == idLinkStatus.idLinkMissing)
{
string lp = (string) l.FilePath;
if (lp.IndexOf("Dropbox", StringComparison.Ordinal) > -1)
try
{
l.Relink(Regex.Replace(lp, ".+Dropbox", "W:"));
}
catch (COMException)
{
// ignored
}
}
}
I found that it doesn't work - relink function doesn't accept the new filename as string.
So I decided to look a little closer at the Javascript relink() function.
DOM defines it as following:
Link.relink (to:varies)
Adobe InDesign 2020 (15.0) Object Model
Points the link to a new source file.
to: Data Type: varies
The full path name of the new source file. Can accept: File or String.
In case of File it works perfectly and I am sure all of you use it in your scripts:
relink(File(newfilename));
But what about String?
I made a test page with missing image (d:\test\missing.jpg) and a test script:
var alllinks = app.activeDocument.links;
var newlink = "d:\\test\\test.jpg";
for (var i = 0; i < alllinks.length; i++)
{
var cur_link = alllinks[i];
$.writeln(cur_link.filePath + ' - ' + cur_link.status.toString());
if (cur_link.status == LinkStatus.LINK_MISSING)
{
try
{
cur_link.relink(newlink);
$.writeln(cur_link.filePath + ' - ' + cur_link.status.toString());
}
catch (e)
{ }
}
}
where I used a filename string as argument for relink().
Result:
d:\test\missing.jpg - LINK_MISSING
The function shows no error but does nothing and just goes to next loop iteration.
Changing the line
cur_link.relink(newlink);
to
cur_link.relink(File(newlink));
I got a working function:
d:\test\missing.jpg - LINK_MISSING
D:\test\test.jpg - NORMAL
So what does Adobe mean with the String and how could I get the right string in C#?
After some tests I have found the answer!
DOM should define the function argument as following:
The full path name of the new source file. Can accept: File or Uri String.
Indeed, if I change the filename string to Uri
cur_link.relink('file:' + newlink);
the script is working again:
d:\test\missing.jpg - LINK_MISSING
d:\test\test.jpg - NORMAL
Now I can use it in my C# code:
l.Relink($"file:{Regex.Replace(lp, ".+Dropbox", "W:")}");
Is the problem solved now? No.
The above solution works only if the new filename/path has no spaces.
As I deal with German filenames, it means
The above solution works only if the new filename/path has no umlauts.
So it wasn't a solution at all.
I needed to convert the new path to a valid Uri string.
That wasn't too complicate. In Javascript:
cur_link.relink('file:' + encodeURI(newlink));
In C#:
l.Relink($"file:{Uri.EscapeUriString(Regex.Replace(lp, ".+Dropbox", "W:"))}");
Result:
d:\test\missing.jpg - LINK_MISSING
d:\test\test.jpg - NORMAL
I added another missing image to my test page to test the solution in a loop.
Result:
d:\test\missing.jpg - LINK_MISSING
d:\test\test.jpg - NORMAL
d:\test\missing.jpg - LINK_MISSING
d:\test\test.jpg - NORMAL
Victory! 🙂
To make my research complete, I tested the new reinitLink() function, which is stated as experimental.
cur_link.reinitLink('file:' + encodeURI(newlink));
Result:
d:\test\missing.jpg - LINK_MISSING
d:\test\test.jpg - LINK_OUT_OF_DATE
d:\test\test.jpg - LINK_OUT_OF_DATE
So, this function replaces link paths but doesn't update links.
I hope, this information might be useful. 🙂
Copy link to clipboard
Copied
Hi @Michael_Rosenstein ,
I'm also testing the then ( InDesign 2018 ) new experimental method itemLink.reinitLink( linkResourceURI ) .
With InDesign 2025 in DOM documentation it's still mentioned as "experimental":
https://www.indesignjs.de/extendscriptAPI/indesign-latest/#Link.html#d1e301019__d1e301757
To my surprise there is a perhaps not documented feature ( or bug ) with reinitLink() .
If one graphic is placed more than one time, my tests are showing that if I use reinitLink() on one single instance of the graphic's itemLink the itemLink.linkResourceURI value for ALL OTHER INSTANCES in the document will change as well.
In my test case I had 2 pairs of images placed.
One pair of images share images with the same name but with different contents.
In one of the two pairs I wanted to "assign" a new linkResourceURI with reinitLink(), the one of the other image's linkResourceURI. To test if the image will change status. So it did. From NORMAL to OUT_OF_DATE as expected.
What was not expected by me was that the corresponding image in the other pair of images changed as well to OUT_OF_DATE with a new linkResourceURI. That behavor bears some dangers when using reinitLink() to graphics and images that are placed more than one time in a document.
Details from my German InDesign 2025:
Running this code on my selection of images:
var linkResourceURI1 = app.selection[0].allGraphics[0].itemLink.linkResourceURI;
var linkResourceURI2 = app.selection[1].allGraphics[0].itemLink.linkResourceURI;
app.selection[0].allGraphics[0].itemLink.reinitLink( linkResourceURI2 );
Result where also the other instance of the image has changed, not only the selected one:
Regards,
Uwe Laubender
( Adobe Community Expert )
Copy link to clipboard
Copied
On with my tests:
If there is yet a different image is placed with the same name, this one will not change with my script snippet.
Just the other instance of the same placed file.
Before script run:
After the script run:
Regards,
Uwe Laubender
( Adobe Community Expert )
Find more inspiration, events, and resources on the new Adobe Community
Explore Now