Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
3

Exploring Link.relink() function in Javascript and COM

Explorer ,
Dec 13, 2019 Dec 13, 2019

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&colon;

 

 

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. 🙂

TOPICS
Scripting
1.5K
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 27, 2025 May 27, 2025

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:

reinitLink(linkResourceURI)_TEST-1_BEFORE-SCRIPT-RUN-3.png

 

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:

 

reinitLink(linkResourceURI)_TEST-1_AFTER_SCRIPT-RUN-3.png

 

Regards,
Uwe Laubender
( Adobe Community Expert )

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 27, 2025 May 27, 2025
LATEST

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:

 

reinitLink(linkResourceURI)_TEST-2_BEFORE-SCRIPT-RUN-3.png

 

After the script run:

reinitLink(linkResourceURI)_TEST-2_AFTER_SCRIPT-RUN-3.png

 

Regards,
Uwe Laubender
( Adobe Community Expert )

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