Tuesday, April 15, 2008

Intralink Scripting: Creating Pro/ENGINEER Trail Files in Java

If you're trying to automate some Pro/ENGINEER activity, the use of trail files is a solid and reliable method. Whether you are trying to automate interference checks, convert files to ProductView or PDF, or just verify a large number of family tables, trail files work great. This is assuming that you don't need any interaction between Intralink and Pro/ENGINEER, during the trail file execution.

The first thing you need is a trail file template. This is simply a trail file that you have recorded. The content will be changed slightly to include variable names where real values will be substituted at runtime.

For example, this:
~ Activate `main_dlg_cur` `ProCmdModelOpen.file`
~ Select `file_open` `Ph_list.Filelist` \
1 `abc.prt`

Becomes this:
~ Activate `main_dlg_cur` `ProCmdModelOpen.file`
~ Select `file_open` `Ph_list.Filelist` \
1 `@NAME@`


One thing to note about trail files, they contain a lot of "fluff", which are lines that you don't need, but got recorded. You won't know what you need and don't need until you try to remove it. My advice is to comment lines you think you don't need, by placing an exclamation point as the first character of the line. Pro/ENGINEER will ignore these lines. If the trail file plays as expected, the line is probably not needed.

This means that any line starting with an exclamation point can be eliminated. The one exception is the first line of the file. You need this, don't remove it. Generally, I leave some of the commented lines that were originally recorded in order to remind myself when an action has started or finished.

There is a config.pro option that will help prevent trail file fluff. Set CMDMGR_TRAIL_OUTPUT to YES and Pro/ENGINEER will reduce the number of lines and increase readability substantially.

Here is an example of a trail file template that records a timestamp, opens a file, records another timestamp, and then exits. You'll notice the comments indicating "blocks" of actions.


!trail file version No. 1301
!!!
!!! Timestamp
!!!
~ Select `main_dlg_cur` `MenuBar1` \
1 `Info`
~ Select `main_dlg_cur` `Info.cb_info_session`
~ Close `main_dlg_cur` `MenuBar1`
~ Close `main_dlg_cur` `Info.cb_info_session`
~ Activate `main_dlg_cur` `psh_util_time`
!!!
!!! Open model
!!!
~ Activate `main_dlg_cur` `ProCmdModelOpen.file`
~ Select `file_open` `Ph_list.Filelist` \
1 `@NAME@`
~ Activate `file_open` `Open`
!Command ProCmdModelOpenExe was pushed from the software.
!!!
!!! Timestamp
!!!
~ Select `main_dlg_cur` `MenuBar1` \
1 `Info`
~ Select `main_dlg_cur` `Info.cb_info_session`
~ Close `main_dlg_cur` `MenuBar1`
~ Close `main_dlg_cur` `Info.cb_info_session`
~ Activate `main_dlg_cur` `psh_util_time`
!!!
!!! Exit
!!!
~ Select `main_dlg_cur` `MenuBar1` \
1 `File`
~ Close `main_dlg_cur` `MenuBar1`
~ Activate `main_dlg_cur` `File.psh_exit`
! Message Dialog: Warning
! : Do you really want to exit?
~ FocusIn `UI Message Dialog` `no`
~ FocusIn `UI Message Dialog` `yes`
~ Activate `UI Message Dialog` `yes`
!End of Trail File

Now that we have a template, we need some java code to create the trail file that Pro/ENGINEER will run. There are many Java templating libraries that do some very complex manipulations, but for this simple example, we need very simple substitutions. The code listed below is quite simple, but works great for basic trail file creation.

Once variables have been established, the first task is to generate file handle objects for reading (using the BufferedReader/FileReader classes) and for writing (using the FileWriter class). Each line of the template file is read from using readLine() in the while loop. Then the value of the objName variable is substituted where @NAME@ is found in the template. The resulting line is written to the output file. Closing both the input and output file is very important, especially on Windows, to make them fully accessible.

String text;
String inputFile = "trl-template.txt";
String outputFile = "trl-output.txt";
String newline = System.getProperty("line.separator");

// Set up input and output files
BufferedReader templateInput = new BufferedReader(new FileReader(inputFile));
FileWriter trailOutput = new FileWriter(outputFile);

// Read through all lines in file
while ((text = templateInput.readLine()) != null) {

// Replace @NAME@ with objName String
text = text.replaceAll( "@NAME@", objName );

// Output modified template line to given output file stream
trailOutput.write(text + newline);

}

trailOutput.close();
templateInput.close();

Following best practices, the code should be placed in its own function, or, even better, its own class. Also, using an array or HashMap, instead of a simple String object for input, would allow for more extensive substitutions to occur during trail file generation, but the above is the core of a simple approach that works very well.

No comments: