DriveWorks is great at generating SOLIDWORKS models and drawings from a specification. When those files land in SOLIDWORKS PDM Professional, though, they usually sit in the first state of the workflow until someone moves them by hand. In this tutorial we build a small Specification Flow task that moves each file to the right workflow state as soon as DriveWorks has added it to the vault.
What you need
- DriveWorks Pro with Specification Flow, on the machine that processes your specifications (Administrator for testing, Autopilot in production)
- The SOLIDWORKS PDM Professional client on the same machine, with a local view of the vault
- Visual Studio and the .NET Framework version your DriveWorks release targets
- A Windows account that can log in to the vault and run the transition you want
Step 1: Find the DLLs
A Specification Flow task is a .NET class library that references DriveWorks and the SOLIDWORKS PDM API. These are the assemblies to add:
- DriveWorks.Engine.dll, DriveWorks.Applications.dll and Titan.Rules.dll. They ship with the DriveWorks SDK as NuGet packages, and the same files are in the DriveWorks installation folder under
C:\Program Files\DriveWorks\. The SDK is free for customers with a valid subscription: request it from apisupport@driveworks.co.uk. - EPDM.Interop.epdm.dll, the SOLIDWORKS PDM API. You find it in the PDM client installation folder, by default
C:\Program Files\SOLIDWORKS PDM\.
Set Copy Local to False on the DriveWorks references, so your plugin always uses the copies DriveWorks has already loaded. The DriveWorks SDK Starter Examples on GitHub show the same references in a working project.
Step 2: Write the task
Create a new Class Library (.NET Framework) project and add the class below. It registers four properties that you will fill with DriveWorks rules: the vault name, the file path, the target state and an optional comment.
using System;
using System.IO;
using DriveWorks.EventFlow;
using DriveWorks.Specification;
using EPDM.Interop.epdm;
namespace BlueByte.DriveWorks.PdmTasks
{
/// <summary>
/// Specification Flow task that moves a file through a SOLIDWORKS PDM workflow transition
/// on a file that DriveWorks has added to the vault.
/// </summary>
[Task("PDM Workflow Transition", "", "SOLIDWORKS PDM", true)]
public class PdmWorkflowTransitionTask : Task
{
private const string DefaultComment = "Transitioned by DriveWorks";
private FlowProperty<string> VaultNameProperty { get; }
private FlowProperty<string> TargetFileProperty { get; }
private FlowProperty<string> TargetStateProperty { get; }
private FlowProperty<string> CommentProperty { get; }
public PdmWorkflowTransitionTask()
{
// Each registered property shows up in the task, so you can build a DriveWorks rule for it.
VaultNameProperty = this.Properties.RegisterStringProperty("Vault Name", "Name of the local SOLIDWORKS PDM vault view.");
TargetFileProperty = this.Properties.RegisterStringProperty("File Path", "Full path of the file inside the vault view.");
TargetStateProperty = this.Properties.RegisterStringProperty("Target State", "Name of the workflow state to move the file to.");
CommentProperty = this.Properties.RegisterStringProperty("Comment", "Optional comment stored with the transition.");
}
protected override void Execute(SpecificationContext ctx)
{
string vaultName = VaultNameProperty.Value;
string targetFile = TargetFileProperty.Value;
string targetState = TargetStateProperty.Value;
string comment = string.IsNullOrWhiteSpace(CommentProperty.Value) ? DefaultComment : CommentProperty.Value;
// Validate the rule results before touching the vault.
if (string.IsNullOrWhiteSpace(vaultName))
{
this.SetState(NodeExecutionState.Failed, "The Vault Name rule is empty.");
return;
}
if (string.IsNullOrWhiteSpace(targetFile))
{
this.SetState(NodeExecutionState.Failed, "The File Path rule is empty.");
return;
}
if (string.IsNullOrWhiteSpace(targetState))
{
this.SetState(NodeExecutionState.Failed, "The Target State rule is empty.");
return;
}
try
{
int windowHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle.ToInt32();
IEdmVault5 vault = new EdmVault5();
// LoginAuto uses the Windows account that runs DriveWorks.
// No user name or password is stored in the task.
if (!vault.IsLoggedIn)
{
vault.LoginAuto(vaultName, windowHandle);
}
IEdmFolder5 parentFolder;
IEdmFile5 file = vault.GetFileFromPath(targetFile, out parentFolder);
if (file == null || parentFolder == null)
{
this.SetState(NodeExecutionState.Failed, $"{Path.GetFileName(targetFile)} was not found in the vault. Check that it has been added before this task runs.");
return;
}
// Move the file to the target state. PDM runs the transition that leads
// from the current state to this state, with its actions and notifications.
file.ChangeState(targetState, parentFolder.ID, comment, windowHandle, (int)EdmStateFlags.EdmState_Simple);
this.SetState(NodeExecutionState.Successful, $"{Path.GetFileName(targetFile)} moved to {targetState}.");
}
catch (System.Runtime.InteropServices.COMException ex)
{
// PDM reports errors as HRESULTs, for example a missing transition or permission.
this.SetState(NodeExecutionState.Failed, $"PDM error 0x{ex.ErrorCode:X8}: {ex.Message}");
}
catch (Exception ex)
{
this.SetState(NodeExecutionState.Failed, $"Error: {ex.Message}");
}
}
}
}
How it works
- The Task attribute gives the task its name and its category in the Specification Flow toolbox.
- RegisterStringProperty exposes each input to DriveWorks, so you can build a rule for it like any other property.
- LoginAuto logs in with the Windows account that runs DriveWorks. No user name or password is stored in the task or the project.
- GetFileFromPath finds the file in the local vault view, and ChangeState moves it to the target state. PDM runs the transition that leads there, including its actions and notifications.
- SetState reports success or failure back to the Specification Flow, so you see the result in the specification report.
Step 3: Install the plugin
- Build the project in Release mode.
- In DriveWorks, click the Settings icon in the title bar and open Plugin Settings.
- Click Install…, browse to your DLL and choose Install For All Users.
- Restart DriveWorks. Repeat on every DriveWorks module that processes specifications, including Autopilot.
Step 4: Add the task to your Specification Flow
- Open your project in DriveWorks Administrator and go to Specification Flow.
- Pick the state or operation that runs after DriveWorks has generated the files and added them to the vault.
- Drag PDM Workflow Transition from the SOLIDWORKS PDM category of the toolbox onto the flow.
- Build a rule for each property: the vault view name, the full path of the generated file in the vault view, and the target state, for example Approved.
- Run a test specification and check the specification report for the task result.
Generating an assembly, its parts and a drawing? Add one task per file, or extend the class to take a list of paths and loop over them.
Tips before you go live
- The account that runs Autopilot must be able to log in to the vault and must have permission for the transition.
- The task has to run after the file is in the vault. If it runs too early, it reports that the file was not found.
- ChangeState takes the destination state. If two transitions from the current state lead to states with the same name, give them unique names so PDM picks the right one.
- Try it on a test vault first. A transition can trigger notifications, revisions and other workflow actions.
Need a hand with DriveWorks?
Blue Byte Systems builds custom DriveWorks plugins, Specification Flow tasks and SOLIDWORKS PDM integrations. See our DriveWorks development services or book a short call and tell us what you want to automate.