J.Link Task Library
If you have a need for a Pro/Web.Link application to reach out to other processes, a task library may be the answer. Basically have your Pro/Web.Link app start up another small J.Link app, do something and then send your app the results which presumably it will then know how to process. The J.Link application is not subject to the same sandboxing constraints of a web browser, it kind of sits both inside and outside Creo whereas Pro/Web.Link applications are best thought of as being internal to Creo.
The J.Link App
J.Link is another Creo Parametric API. It uses Java, is extremely similar to the Pro/Web.Link API but with it being a Java app can access system level areas. A full treatment of Java and this API is out of scope for this article but the following code is an example of a task library. I've added comments to try and explain it.
//Need these for java operations
import java.io.*;
import java.util.*;
//Need classes from PTC's J.Link API
import com.ptc.cipjava.*;
import com.ptc.pfc.pfcSession.*;
import com.ptc.pfc.pfcWindow.*;
import com.ptc.pfc.pfcGlobal.*;
import com.ptc.pfc.pfcCommand.*;
import com.ptc.pfc.pfcExceptions.*;
import com.ptc.pfc.pfcArgument.*;
import com.ptc.pfc.pfcUI.*;
import com.ptc.pfc.pfcJLink.*;
/**
* This class is used to start the jlink application in Creo.
* The name of the class has to appear in the protk.dat
* under the java_app_class option.
**/
public class Helper{
private static Session curSession;
public static void main (String [] args)
{}
/**=========================================================================
* This method is called by proe upon starting a jlink application
**/
public static void start ()
{
try
{
//1. Get Session
curSession = pfcGlobal.GetProESession();
//2. Report to user tool is started up
stringseq Messages = stringseq.create();
Messages.set (0, "Starting...");
curSession.UIDisplayMessage ("msg_helpertools.txt",
"Helper Tools Info: %0s.", Messages);
//3. Register with the session a function which can be used
curSession.RegisterTask ("ReadFile", new ReadFileHelper (curSession));
Messages.set (0, "...Read File Helper");
}
catch (jxthrowable x)
{
printMsg ("Stop");
}
}
/**=========================================================================
* This method is used for cleanup and etc...called when the jlink application exits
*/
public static void stop (){
printMsg ("Stop");
}
/**=========================================================================
* This method prints a string to the standard output.
*/
public static void printMsg (String msg){
System.out.println ("Helper: " + msg);
}
}
//This is the helper
class ReadFileHelper extends com.ptc.pfc.pfcJLink.DefaultJLinkTaskListener
{
Session session;
public ReadFileHelper(Session currentSession)
{
this.session = currentSession;
}
//OnExecute is the method that gets called to do something usefull
public Arguments OnExecute (Arguments InputArguments)
{
try
{
//We're expecting 1 input argument containing the name
//of a file in the working directory to read
Argument myArg = InputArguments.get(0);
String myArgLabel = myArg.GetLabel ();
ArgValue myArgVal = myArg.GetValue ();
String myArgValStr = myArgVal.GetStringValue ();
String FileToRead = session.GetCurrentDirectory() +myArgValStr;
stringseq Messages = stringseq.create();
Messages.set (0, myArgLabel+" read "+FileToRead);
session.UIDisplayMessage ("msg_helpertools.txt",
"Helper Tools Info: %0s.", Messages);
session.UIClearMessage ();
//Build return arguments as the file contents
Arguments outArgs = Arguments.create ();
String listString = "";
try
{
FileReader file = new FileReader(FileToRead);
BufferedReader buffer = new BufferedReader(file);
String line="";
//Works ok for smaller files
while((line=buffer.readLine())!=null)
{
listString+=line+"\n";
}
buffer.close();
}
catch(IOException e)
{
System.out.println ("problem");
Messages.set (0, myArgLabel+" read problem "+FileToRead);
session.UIDisplayMessage ("msg_helpertools.txt",
"Helper Tools Info: %0s.", Messages);
session.UIClearMessage ();
}
//Build arguments and append to the arguments collection
ArgValue ResponseValue = pfcArgument.CreateStringArgValue(listString);
Argument ResponseArg = pfcArgument.Argument_Create ("Response", ResponseValue);
outArgs.set (0, ResponseArg);
return outArgs;
}
catch (Exception x)
{
x.printStackTrace ();
System.out.println ("------------------------------------");
}
return null;
}
}
In order to compile something like this:
@echo off
del C:\Helper\*.class
del C:\Helper\src\*.class
C:\java\jdk1.4.2.19\bin\javac C:\Helper\src\Helper.java
copy C:\Helper\src\*.class C:\Helper\*.class
del C:\Helper\src\*.class
Assuming the J.Link app compiles, you'll get some class files created and are in a position now to use that. Before the application will properly run however, we need to additionally create a C:\Helper\text\msg_helpertools.txt file to hold pre-formatted messages which the application uses to report messages back to the user.
%CIHelper Tools Info: %0s.
Helper Tools Info: %0s.
#
#
The Pro/Web.Link App
So rather than go with all the theory, here's a bit of sample code that uses the J.Link app.
<HTML>
<HEAD><TITLE>Using J.Link Task Library</TITLE></HEAD>
<BODY>
<DIV id="UI"></DIV>
<SCRIPT>
if (!pfcIsIE())
{
netscape.security.PrivilegeManager.enablePrivilege("UniverasalXPConnect");
}
libCheckEnvironment();
//Start up Helper App
var helpertoollocn = "C:\\Helper";
var helperapp = oSession.StartJLinkApplication("Helper","Helper","start","stop",
helpertoollocn,helpertoollocn,false);
//Build up Input Arguments
var inputarg = pfcCreate("pfcArgument").Create("RequestDemo",
pfcCreate("MpfcArgument").CreateStringArgValue("trail.txt.1");
var inputargs = pfcCreate("pfcArguments");
inputargs.Append(inputarg);
//Request the task is executed using your provided arguments
var response = helperapp.ExecuteTask("ReadFile",inputargs);
//Process the arguments
var Out = "<H4>"+response.Item(0).Label+"</H4>";
Out+="<P>"+
response.Item(0).Value.StringValue.split("\n").join("<BR>")+
"</P>";
document.getElementById("UI").innerHTML = Out;
//ALWAYS stop the application
helperapp.Stop();
//===============
//Utility Functions
//===============
function libCheckEnvironment()
{
try
{
if (!pfcIsIE())
{
netscape.security.PrivilegeManager.enablePrivilege("UniverasalXPConnect");
}
window.oSession = pfcCreate("MpfcCOMGlobal").GetProESession();
oSession.CurrentWindow.SetBrowserSize(50);
}
catch(er)
{
alert ("Pro/Web.Link failed to initialise");
}
}
function pfcIsIE()
{
//IE8,9,10
if (navigator.appName.indexOf("Microsoft")!=-1)
{
return true;
}
else
{
//IE11
if (navigator.userAgent.indexOf("Trident")!=-1)
{
return true;
}
else
{
return false;
}
}
}
function pfcCreate(className)
{
if (!pfcIsIE())
{
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
return Components.classes["@ptc.com/pfc/"+className+";1"].createInstance();
}
else
{
return new ActiveXObject("pfc."+className);
}
}
</SCRIPT>
</BODY>
</HTML>
So the general procedure can be summarized as:
Conclusion
A Helper can be helpful to get you out of a restriction. Because Java has access to all kinds of libraries and isn't subject to the sandbox restrictions of the Creo Browser, the world *could* be yours to explore. Be aware of course that if your app is ending up feeling overly complex then perhaps you should consider stepping up to using a different API. Simple Automation should be simple remember!
<< Recoding Apps for Pro/Web.Link |