acroctl.py

Close, open, and restore PDF documents in Acrobat Exchange on Windows.

Problem statement

Many people use TeX. Many use Windows. Many use TeX on Windows. Many generate PDFs from TeX on Windows. Many view their PDFs with Acrobat on Windows.

Many are annoyed when TeX cannot regenerate their PDF because it is currently open in Acrobat.

Rightly so.

Why it happens

When Acrobat has a window displaying a PDF, it has the underlying PDF file open. When pdflatex regenerates a document, it tries to delete the PDF and then replace it. On Windows, it is not possible to delete an open file, so this process fails.

A solution

Acrobat Exchange can be commanded with OLE (Object Linking and Embedding.) We may thus write a script to close Acrobat before running pdflatex, and then restore it afterwards. acroctl.py is such a script.

acroctl.py can close Acrobat and then restore it to the same page after you run pdflatex.

Directions

Setup

Download and install Python for Windows. You probably want the Python Windows installer. You need "native" Python because the script uses the pywin32 package to use Windows APIs, which (as of this writing, as far as I can tell) does not work on cygwin Python. You can, however, install both Pythons, and call the native python from the cygwin python.

Download and install pywin32.

Save the python script somewhere on your system so that you can use it. There are two versions of the script: acroctl.py and acroreadctl.py.

The first version of the script, acroctl.py, works only with Acrobat Exchange. acroctl.py does not work with Adobe Reader. Adobe Reader is the free download that can view PDFs. This version of the script works with Exchange, which is the not free program that can create and edit PDFs. This is the full featured version of the script. If you have Acrobat Exchange, I suggest you use this version.

The second version, acroreadctl.py, works with both Reader and Acrobat Exchange. However, it has two limitations. First, it can't determine whether a document is open, or what page is being viewed, so it can't restore the page view. Second, acroreadctl.py will silently discard any changes to the PDF. Of course, Reader can't make changes, so that's not a problem, but if you are using full-featured Acrobat, it could be.

In short, use acroctl.py with Acrobat Exchange (or the updated version acrobatpdfcontrol.py from Matthias Stevens) and acroreadctl.py with Adobe Reader.

(Technical details: the first version of the script uses OLE Automation, which Reader does not support. The second verion uses DDE messages.)

Document generation

Before running pdflatex, invoke acroctl.py to close your PDF, e.g.:

c:\python25\python c:\spam\acroctl.py --close c:\eggs\document.pdf

All windows of the PDF document will close. If there were any open windows, the script will print out the page number (zero-indexed) being viewed in one of them.

Run pdflatex to regenerate your document. Then, open your document, e.g:

c:\python25\python c:\spam\acroctl.py --open c:\eggs\document.pdf

Acrobat should open with the first page of your document displayed.

Usage from cygwin

Many people use cygwin. The easiest way to use this script in combination with cygwin (and the Makefile you probably use to run TeX) is to create a script that runs both acroctl.py and pdflatex. Something like:

#!/bin/sh

TOPTEX="$1"
shift

NATIVEPYTHON="/cygdrive/c/Python25/python.exe"
ACROCTL=`cygpath -w -a acroctl.py`
NATIVEPDF=`cygpath -w -a ${TOPTEX}.pdf`

PAGE=`"$NATIVEPYTHON" "$ACROCTL" --close "$NATIVEPDF"`

pdflatex $TOPTEX < /dev/null
bibtex $TOPTEX < /dev/null
pdflatex $TOPTEX < /dev/null
pdflatex $TOPTEX < /dev/null

"$NATIVEPYTHON" "$ACROCTL" --restore --page=$PAGE "$NATIVEPDF"

The cygpath program translates between cygwin paths (/spam/eggs/ham) and Windows paths (c:\spam\eggs\ham).

This script opens Acrobat only if it was open when the script started. If you change --restore to --open, it will open the PDF unconditionally.

Related work

Tips and tricks for LaTeX

Matthias Stevens has produced an updated version acrobatpdfcontrol.py that can save and restore the complete view settings (page, zoom, etc.)

Future work

It ought to be possible to integrate directly into a makefile, without an accessory shell script.

A native compiled version of the program would eliminate the need to install Win32 Python.

acroctl.py

The script may behave oddly if the document is open in multiple views.

It's annoying that only the filename without a path is available to decide what documents to close. Perhaps the JavaScript interface, available through GetJSObject() on AcroExch.PDDoc, has better information?

If Acrobat isn't running, there is a delay while the script starts it so that it can query what document are open, and then do nothing because there aren't any.

acroreadctl.py

If Reader is running but the PDF isn't open, the script will open it and immediately close it. This is because the command that makes a file available for manipulation also causes it to be opened and displayed.

Conclusion

acroctl.py can close Acrobat and then restore it to the same page after you run pdflatex.

Better than nothing. Tell your friends.

Last modified 10 July 2016