Wrench value from your Creo Investments Home Measure the benefits Simple Automation can bring Why
Automate?
A personal way to do PDM Peer to Peer
PDM
3D Drawings Model Based
Design
Smooth out unwanted sharp edges Other
Articles
www.proetoolbox.co.uk - Simple Automation made Simple

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:

  • Install the JDK to suit your install, Creo2 (JDK 1.4.2.19) Creo3 (JDK 1.7.0.55)
  • Setup the CLASSPATH environment variable to include C:\PTC\Creo2\Common Files\M120\text\java\pfc.jar
  • Create a make.bat file, store it in C:\Helper
  • @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
    
  • Run the make file
  • 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:

  • Start the J.Link task library.
  • Build input arguments.
  • Call a taskID function and pass some arguments to it.
  • Process the response.
  • *IMPORTANT*... shut down the task library.
  •  

    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