SmarTeam Workflow’s API engine offers tremendous flexibility for manipulating processes on-the-fly.  The object model, and the combination of nodes, users, and events make it easy to perform fairly advanced operations with workflow.  As an example, let’s use the API to dynamically assign a user to a node based on their participation earlier in the workflow. We’ll use BasicScript and C#.NET to write the code (directions for getting the source code below), and cover some of the important details of how to apply the customization in ENOVIA SmarTeam.

One of the most common requirements when designing a workflow in SmarTeam is dynamic user assignments but what is that?  Imagine a workflow that is routed through an approval process that is initiated by an engineer.  The engineer initiates the workflow which is routed to a document control node for a primary approval step which, in turn, goes to the engineer again for an additional step.  Since the engineer is not known at design-time of the flowchart, the user must be dynamically assigned to the next node.  Dynamic assignments may be done manually by the user at the node, or can be done automatically via scripting.  Rather than rely on the document control user to manually assign the engineer for notification, it’s more efficient and reliable to automate the assignment of the user.  In this case, automation is the only way to ensure that the initiator (the engineer) is assigned to the node.

The good news is that SmarTeam exposes all the objects needed for this flexibility via scripting.  Before explaining the code, let’s review what we’re creating to support the automation:

  1. SmarTeam script (written in BasicScript) with a function that will be hooked to an event in Workflow
  2. Workflow flowchart that is configured to run the script function
  3. Compiled COM-visible DLL that will be called by the script to do the automation (in this case, we’re using C#.NET 2005)

1. SmarTeam Script Development

Create a function within a SmarTeam script file.  For this scenario, the function will be called AssignInitiatorToEngineering.  Note the parameters that are being passed.  The parameters are important, because at various event hooks, different parameters are required.  In this case, the function will be hooked to the “After Send Accept” event of the Start Node (described later).

Function AssignInitiatorToEngineering(smFlowSession As Object, smFlowProcess As Object, smNode As Object, smResponse As Object) As Integer
‘ hook to After Send Accept of start node
On Error GoTo Error_AssignInitiatorToEngineering
Dim RazorleafUtils As Object
Set RazorleafUtils = CreateObject(“Razorleaf.AcmeMfg.Workflow.MessageUtils”)
RazorleafUtils.AssignInitiatorToEngineering smFlowProcess
Exit Function
MsgBox “An error has occured on line ” & Erl & “. The error number is ” & Err.Number & “. The error description is ‘” & Err.Description & “‘.”, ebCritical, “Error AssignInitiatorToEngineering()”
End Function

2. SmarTeam Workflow Configuration

Once the BasicScript function is in place, it can be hooked to the After Send Accept event on the Start Node of the flowchart.  Note that we are not covering creation of the Workflow flowchart here, but you can do this with the Flowchart Designer.  While in the Flowchart Designer (via the SmarTeam Admin Console), click on the Start Node; press F4 to access the Properties dialog; click on the Events tab and click the ellipsis button next to After Send Accept:

Locate the BasicScript file, select the AssignInitiatorToEngineering function, and click OK.

The Properties dialog in the Flowchart Designer should then look like this:

3. Library Development

Now that the script has been created and hooked to the event, the code development can be started.  In the script above, note the two lines that call the library:

Set RazorleafUtils = CreateObject(“Razorleaf.AcmeMfg.Workflow.MessageUtils”)
RazorleafUtils.AssignInitiatorToEngineering smFlowProcess

Razorleaf.AcmeMfg.Workflow.MessageUtils is the name of the library being developed.  It can have almost any name, but good practice is to name it something relevant.  Note that the second line is where the script passes the parameter into the library.

Open Visual Studio and create a class library project.  To use the SmarTeam API, several references must be added.  For ease of supporting future versions of SmarTeam, reference the COM assemblies and not the SmarTeam .NET interops:

SmarTeam Library
SmartFlow Library

The project’s references should now look like this: As mentioned above, this library was named Razorleaf.AcmeMfg.Workflow.MessageUtils.  The method we’re creating is named AssignInitiatorToEngineering and it will be configured to accept the parameters noted above.  Note that the class and the method must be public and the class constructor cannot take any input parameters.

public System.Int16 AssignInitiatorToEngineering(SmartFlow.ISmFlowProcess smFlowProcess)

In this dynamic assignment scenario, we need to perform two actions:

  1. Get the user who initiated the workflow
  2. Assign the user to the node named “Engineering”

To do these steps, first get the initiator’s User Object ID and then retrieve the User object:

//Getting User Object ID
System.Int32 userObjectID = (System.Int32)smFlowProcess.SmObject.get_Value(“USER_OBJECT_ID”);
//Retrieving user object
SmApplic.ISmObject smUser = smFlowProcess.FlowStore.Session.ObjectStore.RetrieveObject(smFlowProcess.FlowStore.Session.MetaInfo.get_SmClassByName(“Users”).ClassId, userObjectID);

Once the user object is retrieved, then we need to also retrieve the Engineering Node:

//Getting engineering node
SmartFlow.ISmNode engineeringNode = GetNode(“ENGINEERING”, smFlowProcess);

Note that GetNode() is a custom method that was added to the class.  The method retrieves the node, given the flow process and the name of the node.  Here is the code for the GetNode internal method:

internal SmartFlow.ISmNode GetNode(System.String nodeName, SmartFlow.ISmFlowProcess flowProcess)
//Getting outgoing nodes…
SmartFlow.ISmNodes smNodes = flowProcess.Flowchart.Nodes;
for (int i = 0; i < smNodes.Count; i++)
if (smNodes[i].Name.ToUpper() == nodeName.ToUpper())
//Found node…returning node
return smNodes[i];
// no match found
//Node not found..returning null
return null;

Once the node is found by the GetNode method, the user can be added to the node.  Be sure to save the node after updating:

if (engineeringNode != null)
//Adding user to node
//Saving node
//Throwing exception
throw new System.InvalidOperationException(“ENGINEERING node name does not exist!”);

Making SmarTeam “See” the Code

In order for SmarTeam to “see” the .NET assembly, it must be made COM-visible and registered for COM interop.  This is done via the properties page of the class library in Visual Studio.  In the Properties window of the project, select the Build tab, and check the box Register for COM interop:

Then select the Application tab and check the box Make assembly COM-Visible:

Once compiled, the library can be registered either manually, or via an Installer Package.  The assembly must be copied and registered to all clients that will use it.


This example was detailed, but relatively simple.  The node name was known ahead of time and hard-coded it into the method.  The code could be modified to act as a generic method that could be re-used to accept the node name as an input from the script, or from a separate configuration file.  Also worth noting is that the code could have been written into the script itself using the same code (using BasicScript instead of C#.NET).  But if you like our example, please request a free copy of the source code.  This simple example should get you started if you’ve been thinking of getting into deeper SmarTeam Workflow scripting.  If you need additional help getting going, or if you’d just like some expert advice on your planned/existing customizations, please contact us.