Executing Acrobat Menu Items from JavaScript

By June 30, 2008

 

Acrobat provides a huge range of functionality through its menu items. Unfortunately for the scripter, much of this functionality is not directly available through the JavaScript DOM. But there is one glimmer of hope: Acrobat JavaScript does have a function for executing the Acrobat menu items. While not perfect, this function allows the scripter to provide shortcuts to the user and automate some functionality not available in the JavaScript DOM.

How to execute a menu item from JavaScript

There are two parts to this process. First, the function that runs the menu item is app.execMenuItem(cMenuItem). Try it out. Open a PDF in Acrobat and run this code in the Console Window:

app.execMenuItem("SaveAs");

The example executes the “SaveAs” menu item. This seems pretty straightforward. In the above example, the input argument to app.execMenuItem() is the name of the menu item, “SaveAs.” This name is exactly what you’d expect it to be, but unfortunately, only a few of Acrobat’s menu items have obvious names. The vast majority are much less obvious. So, the second part of executing a menu item is knowing the menu item’s name, and this is the tricky part.

Finding menu-item names

The text displayed for the menu items on the regular Acrobat menus are captions, i.e., user-friendly names. These captions will be different in the different language versions of Acrobat (French, Chinese, etc.). Underlying every menu item is a language-independent name, and this is the name used to execute it. These language-independent names are found with the app.listMenuItems() function.

This function lists all current menu items on the main menu bar. This includes all of the standard menu items, plus dynamic menu items (like stamps) and custom menu items created with a script or a plug-in. It does not include items on the popup menus or the various navigation windows, which is unfortunate since many of these functions are very useful.

Try running this function from the console window:

app.listMenuItems();

It will display a mess of text that’s difficult to sort through. Since the menus are hierarchical, the output from app.listMenuItems() is also hierarchical. It’s an array of objects that contain other arrays of objects. Parsing this mess will not be covered here. To get an idea of how the items are organized, you can look up the app.listMenuItems() in the Acrobat JavaScript Reference. Here are a couple links to scripts that will parse and display the menu items in an easily readable format:

Menu Item Report Generator: This folder-level script adds a toolbar button to Acrobat that when clicked creates a PDF file containing an organized list of menu items (for Acrobat Pro and Standard only).

Menu Item Menu PDF: This PDF displays a single button that when clicked displays a menu of Acrobat’s menu items. When an item is selected, the item name is displayed in a text box, from where it can be copied onto the clipboard (works for Adobe Reader and Acrobat Pro and Standard).

Automation shortcut

One of the most useful applications for executing menu items is creating toolbar-button shortcuts. There are two reasons for doing this.

First, if the Acrobat user needs to constantly run the same menu item over and over, a one-click, toolbar-button shortcut can save a great deal of time, human error and general frustration. This is especially true for buried menu items like the stamps, although the stamps are somewhat difficult to deal with (see the section below on dynamic menu items).

Second, offices constantly bring in new and temporary workers. Building a set of custom&153; toolbar shortcuts presents users with exactly the functionality they need, reduces training time and eliminates the need to remember or even know where a particular menu item is located. Of course, many of the menu items are already on the Acrobat toolbar. But many are not, and even for the ones that are, the custom buttons are implemented with a folder-level script. Folder-level scripts are implemented with a JavaScript file that can be copied onto a user’s system, providing an easy and reliable way to customize several different workstations within a working environment.

Here is a simple folder-level script for adding a toolbar button to Acrobat that executes a menu item. This is for Acrobat 7 and later.

var DoMyMenuItem = trustedFunction(function(cItemName) app.beginPriv();
app.execMenuItem(cItemName); app.endPriv(); });
app.addToolButton({
	cName: "MyReplacePages",
	cLabel: "Replace Pages",
	cEnable: "event.rc = (app.doc != null);",
	cExec: "DoMyMenuItem('ReplacePages');"
});

For reasons explained in the next section, the actual menu-item execution is done in a trusted function. This is necessary for security changes made in Acrobat versions 7.0 and later.

The function adds a button with the label “Replace Pages” to Acrobat’s AddOns toolbar. The label option was used in this example as a convenience because it’s short and simple. Icons look much nicer on a toolbar and take up less space, but are a bit more difficult to program. You can find information on using button icons in the Acrobat JavaScript Reference.

Restrictions and issues

Once a menu-item name is known, the menu item can be executed by passing it into the app.execMenuItem() function. However, dealing with menu functionality is not always straightforward. The menu items cover a wide range of functionality, and not all of it is suitable for use in a script. There are several restrictions and awkward situations that keep the menu items from being as useful as they could be.

Dialog input
Many of the Acrobat menu items display a dialog that has to be filled in before the function proceeds. From a script, there is no way to fill in dialog entries or bypass the dialog. This is not a problem for automation shortcuts (as described above) since calling the menu item is the only thing the script does; but for other more complex scripts, the menu items that display a dialog are awkward or impossible to use.

Menu-execution feedback
The app.execMenuItem() function is non-blocking, which means code execution continues whether or not the functionality run by the menu item has completed. Acrobat runs the menu item and then immediately proceeds to the next line of code in the script. If the code needs the result of whatever it was that the menu did, then a scheme has to be devised to detect when the menu item’s functionality is complete. This is not easy, and usually involves setting up some kind of timeout function that waits a specified amount of time before testing for the result.

The app.execMenuItem() function does not return a value. So there is no general purpose way to know whether or not the menu item actually did anything. The user may have canceled the operation or Acrobat, for security reasons, may have simply refused to run the menu item’s functionality. There is no way for the script to know what happened.

One example of where these issues are important is an automation script that applies a markup annotation to a PDF. Let’s say the script needs to let the user draw a square on the PDF that will then be used for some further action, like placing a field. The first thing the script does is execute the menu item for the “Square” annotation. This action displays the annotation-drawing cursor. The user is then supposed to draw a square on the PDF page.

The code needs to detect when the square is drawn so it can proceed with creating a field. How does it know when, or even if, the square is drawn? The only way is to wait for a specified amount of time to determine if there is a new square annotation on the page.

The app.setInterval() function creates a timer that repeatedly calls a custom function after a set interval in milliseconds. This timer can be used to continuously check for the existence of the square annotation at short intervals. After a specified number of intervals, if no new annotation is detected, the function times out.

This seems like an awkward methodology (and it is), but when the timing of a return value is unknown, there aren’t too many options. Be careful whenever the result of a menu item is required.

Non-existent items
The app.execMenuItem() function does return a value in one sense. If a menu item does not exist or it has security restrictions, Acrobat will throw an exception when a script attempts to execute it. This is important for a script that uses a menu item created from a custom script or plug-in, and for using dynamic menu items (which are discussed below). To handle all of these cases, the app.execMenuItem() function should be enclosed in a try/catch block as shown below:

try{app.execMenuItem("MyCustomItem");}catch(e){
	app.alert("Invalid Menu Item\nPlease Contact the SysAdmin");
}

Version changes
Adobe has a habit of changing the menu items around in different versions of Acrobat. This is one cause of non-existent menu items. A script might work fine in Acrobat 7, but fail in Acrobat 8 because the menu item name changed. For example, Acrobat 5 had a menu item named “CatalogPlugin” for creating index files. In later versions, the search functionality changed and this menu item was removed.

As another example, the “ZoomIn” menu item in Acrobat 7 was changed to “ZoomInMenuItem” in Acrobat 8. The functionality is exactly the same. Adobe just changed the name of the menu item.

Another thing that happens from version to version is security concerns change. In versions earlier than Acrobat 7, the “SaveAs” menu item was restricted to privileged contexts. But in Acrobat 7, Adobe loosened up on security and let it be run from any context.

This, however, is the exception to the trend, i.e., to restrict previously open menu items. In Acrobat 8, Adobe introduced the White List (discussed below). It enumerates which of the main menu items can be run from non-privileged contexts. This list severely locked down many menu items that had previously been available and broke many existing document scripts. Needless to say, there were a lot of unhappy people.

How menu item names change from version to version can seem rather arbitrary. I am sure there are good reasons for these changes, but they are unpredictable. So don’t assume that what works today will work tomorrow.

Dynamic menu items
There are some menu items that Acrobat generates on the fly as they are needed. The most notable of these are the stamp annotations. The stamp menu items, even for the standard stamps, do not exist until the user activates the stamps menu. A particular stamp doesn’t have to be selected in order for the menu item to pop into existence; it just has to be exposed on the menu.

If one of the stamp menu items is called by JavaScript before it has been exposed, the app.execMenuItem()function will throw an exception, as explained above.

White list
As already stated, in Acrobat 8 Adobe introduced the concept of a White List. This is, quite literally, a list of menu-item names. If a menu-item name appears on the list, then it can be executed from a non-privileged context, like a document script. If a menu-item name does not appear on the list, then that menu item can only be executed from a privileged context. Privileged contexts include the console window, a batch sequence and a trusted function.

This list is part of the Acrobat installation. On a Mac, it’s stored in one of the configuration files inside the Acrobat Application Package. On Windows, it’s in the Registry at this location:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\ Adobe\Adobe Acrobat\8.0\FeatureLockDown\cDefaultExecMenuItems

Adobe Reader has a similar Registry location:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\ Adobe\Adobe Reader\8.0\FeatureLockDown\cDefaultExecMenuItems

Menu items can be added and removed from this list for individual Acrobat installations. Changing the White List works very well for closed environments, a single office for example. It’s not practical to change the list for more distributed groups of users. The items not on this list by default are typically suitable only for use in an automation script. They should only be considered for document scripting under special circumstances.

Forbidden items
There are a few menu items that cannot be executed, period. The “Quit” menu item falls into this category. Exiting Acrobat is something Adobe feels should not be done from a script. There are others, but they are not documented. Just be aware there are some menu items that will not execute under any circumstances.

For more information on functions used in this article, see the Acrobat JavaScript Reference and the Acrobat JavaScript Guide.
http://www.adobe.com/devnet/acrobat/

Click on the Documentation tab and scroll down to the JavaScript section.


Was this tutorial helpful?

Please Log in to provide feedback on this tutorial.

Rate this tutorial

Please Log in to rate this tutorial.

Rating:

Did you know?

  • You can ask a question and get an answer from one of our experts.
  • You can search our database of over 800 tutorials by product and/or topic.
  • You can leave a comment below for the author of this tutorial.

Products covered:

Related topics:

JavaScript

Top Searches:

Edit PDF, Create PDF, Interactive PDF, Action Wizard


0 comments

Leave a reply:

Commenting is not available in this channel entry.

Download
Acrobat XI trial

Get the trial now

Learn how to
edit PDF.

Get started