Award Winning Plant Industry Community

SmartPLANT Review .NET API Usage Tutorial

SmartPlant Review
.NET API Usage Tutorial

By Parrish Husband


When I worked as a piping designer, the SmartPlant Review driving and reporting fell into my lap more times than I can remember. Eventually I got to a point where I spent more time setting up VUE sessions and making tag reports than I was designing; thus it became clear to me I would need to figure out a way to streamline my efforts.

I was introduced to the SmartPlant Review API module shortly thereafter by one of our PDS administrators, and immediately began testing it’s capabilities and limitations. One thing I struggled with initially was the steep learning curve to get started with the API in .NET. Luckily the Drapix_API.chm file had some VB6 implementation examples, however the documentation felt more cryptic at times than it was informative. I widened my search online and to my surprise came up with a series of empty Google results.

For the next several months I tested the classes and methods inside the VaxCtrl3.dll until eventually getting to a point where I felt comfortable using it. Having had my development progress slowed by the lack of information, I felt it was my responsibility to share what I had learned; so that hopefully others could benefit. The idea behind this tutorial series is to de-mystify SmartPlant Review programming, and kick off healthy discussions on implementing ideas and techniques. Therefore without further delay, welcome to part 1 of this development series.

Part 1: Setting up a new project in Visual Studio



1. Launch Visual Studio and start a new project


2a. Create a new form application in the desired language format. The image on the left is setting up a new form project in C#.


2b. For all the VB junkies out there, here is the VB.NET equivalent.


3a. Add a reference to VaxCtrl3.dll to your project (typically located in your SPR install folder) as outlined below.
3b. Right-Click on your project in the solution explorer, and select “Add Reference” from the context menu.

3c. A dialog box will appear for adding in a specific reference. Click on the “Browse” tab and navigate to the directory containing VaxCtrl3.dll

3d. Select the VaxCtrl reference from the solution explorer, and modify the “Copy Local” setting to TRUE from the properties view. (If desired, in .NET 4.0 and higher this property can be set to false using Embed Interop Types)


4. Open the application form code editing page by right-clicking on the form on the project explorer and selecting “View Code” from the context menu.


5. Add in the VaxCtrl3 reference namespace to the form code page. This strips away the requirement for needing to prefix objects inside the reference with the full reference name. In VB.NET the "Imports" keyword is used altenatively to "using".


6a. With the form designer active, add a button to the application form from the Visual Studio form toolbox.


6b. With the new button selected, rename the button and change the button display text as desired from the properties window. It's a good habit to get into managing control names yourselft, as it will make the project easier to read and edit.


7. Create a new button click event method by double-clicking the button from the form designer. In C#, this is what gets generated:


Alternately in VB.NET you get a subroutine in this format:

*Note*

Double clicking the button to create the event method allows Visual Studio to do some work in the background. In C#, the event is manually created in the button declaration of the Designer.cs page of the form. This can be done manually like this in C#:

btn_SprConnect.Click += btn_SprConnect_Click;

In VB.NET similar changes are made in the background, but rather than link an event (which the “Handles” declaration does by itself) it simply adds a “WithEvents” flag to the button declaration in the Designer.vb page:


Friend WithEvents btn_SprConnect As System.Windows.Forms.Button



8. Add in a method to send text to the SmartPlant Review text window. This is the C# code:


...and the VB.NET equivalent


The first line in the method simply creates a new instance of the DrApi class. This class represents the main SPR application when using the VaxCtrl3 API. Note that creating a DrApi object does not invoke a new instance of SmartPlant Review to be started. If an instance if SPR is running, the class constructor (new DrAPI() ) will latch onto the existing session, however it is otherwise separate from spr.exe. If you want to launch a new running instance of spr.exe, you can do so using Process.Start, or from the API itself with the “SessionAttach” method:
C#:

sprApp.SessionAttach("C:\\ProjectPath\\ProjectName.vue");

VB.NET:

sprApp.SessionAttach("C:\ProjectPath\ProjectName.vue")

The second portion of our new method simply checks to see if our DrApi object is set to something. If it’s not, this indicates the reference may not be resolving at runtime, or the VaxCtrl3.dll library is not properly registered.

Once we determine we indeed have a DrApi object, we send a message to the Text Window of the running SmartPlant Review application using the “TextWindow” method. As indicated in the Drapix_API.chm help file, the TextWindow method requires 4 parameters when invoking it:

1. Flags – Integer. A bit-mask controlling the display of the text window.
2. Title – String. The text to be displayed as the Text Window title.
3. Text – String. The text to be displayed in the Text Window.
4. CharacterPosition – Integer. Controls the cursor position in the text window.

For the flags parameter, we can use the built-in constants from inside the referenced library (DrConstants), or the actual values themselves. In our example, I’ve used the actual constants, as it makes the method call easily identifiable without requiring additional commenting to clarify. However for reference, DrConstants.DR_TEXT_WIN_CLR is a value of 1.

Now that our method is complete, we can run our test project. Make sure an instance of SPR is running, otherwise the application will have no effect. If we were testing the result of the TextWindow method (which returns an integer value on error, zero on success) we’d find that without having an SPR instance running, we’d get a result of 1 (DR_NO_DR_AVAIL).
This can be set up in the project as follows:

C#:

int sprResult;

// Clear the text window and add the new output message
sprResult = sprApp.TextWindow((int)DrConstants.DR_TEXT_WIN_CLR, "SPR Tutorial", "Hello World", 0);

// Show a connection error if applicable
if (sprResult == 1) MessageBox.Show("Not connected to SmartPlant Review");

//

VB.NET:


Dim sprResult As Integer

' Clear the text window and add the new output message
sprResult = sprApp.TextWindow(DrConstants.DR_TEXT_WIN_CLR, "SPR Tutorial", "Hello World!", 0)

' Show a connection error if applicable
 If sprResult = 1 Then MessageBox.Show("Not connected to SmartPlant Review")

'

Here is the result of our application’s TextWindow method invoke:


9. Output application information to the TextWindow using the concepts discussed above. Now that we have a way of communicating with SPR, we can send some useful information to the text window using a range of methods available to the DrApi class:

Version(reference string) – Passes a string of the current application version to a referenced string object.
GlobalOptionsSet(integer, double) – Passes a new value to an application constant. Used to control how the application and API methods behave globally.
FileNameFromNumber(integer, reference string) – Passes a string of the nth file number in the active session to a referenced string object.
FilePathFromNumber(integer , reference string) – Passes a string of the nth file number’s path in the active session to a referenced string object.
TagNextNumber(out integer, integer) – Returns an integer value of the next available tag number to a defined integer. This is the value contained in the MDB site_table “next_tag_id” column.

C#:

private void btn_SprConnect_Click(object sender, EventArgs e)
{
    // Create a new SPR Application object
    var sprApp = new DrApi();

    // Check if the application object is not null
    if (sprApp != null)
    {
        // Create output variables
        var sprVersion = string.Empty;
        var sprVueName = string.Empty;
        var sprMdbPath = string.Empty;
        var sprWorkDir = string.Empty;
        int sprNextTag;

        // Get the current SPR version
        sprApp.Version(ref sprVersion);

        // Turn the global file info variable on
        sprApp.GlobalOptionsSet((int)DrConstants.DR_G_API_FILE_INFO_MODE, 1);

        // Get the VUE session name
        sprApp.FileNameFromNumber(0, ref sprVueName);

        // Get the Mdb name
        sprApp.FileNameFromNumber(1, ref sprMdbPath);

        // Get the working directory
        sprApp.FilePathFromNumber(1, ref sprWorkDir);

        // Build the full mdb path
        sprMdbPath = Path.Combine(sprWorkDir, sprMdbPath);

        // Reset the global file info variable
        sprApp.GlobalOptionsSet((int)DrConstants.DR_G_API_FILE_INFO_MODE, 0);

        // Get the next tag number
        sprApp.TagNextNumber(out sprNextTag, 0);

        // Create the output message
        var sb = new System.Text.StringBuilder();
        sb.AppendFormat("Version: {0}\n", sprVersion);
        sb.AppendFormat("Vue Name: {0}\n", sprVueName);
        sb.AppendFormat("Mdb Path: {0}\n", sprMdbPath);
        sb.AppendFormat("Next Tag Number: {0}\n", sprNextTag);

        // Clear the text window and add the new output message
        sprApp.TextWindow((int)DrConstants.DR_TEXT_WIN_CLR, "SPR Tutorial", sb.ToString(), 0);
    }
}
//

VB.NET:

Private Sub btn_SprConnect_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_SprConnect.Click

    ' Create a new Spr application object
    Dim sprApp = New DrApi()

    ' Check if the application object is not null
    If sprApp IsNot Nothing Then

        ' Create output variables
        Dim sprVersion = String.Empty
        Dim sprVueName = String.Empty
        Dim sprMdbPath = String.Empty
        Dim sprWorkDir = String.Empty
        Dim sprNextTag As Integer

        ' Get the current SPR version
        sprApp.Version(sprVersion)

        ' Turn the global file info variable on
        sprApp.GlobalOptionsSet(DrConstants.DR_G_API_FILE_INFO_MODE, 1)

        ' Get the VUE session name
        sprApp.FileNameFromNumber(0, sprVueName)

        ' Get the MDB name
        sprApp.FileNameFromNumber(1, sprMdbPath)

        ' Get the working directory
        sprApp.FilePathFromNumber(1, sprWorkDir)

        ' Build the full mdb path
        sprMdbPath = Path.Combine(sprWorkDir, sprMdbPath)

        ' Reset the global file info variable
        sprApp.GlobalOptionsSet(DrConstants.DR_G_API_FILE_INFO_MODE, 0)

        ' Get the next tag number
        sprApp.TagNextNumber(sprNextTag, 0)

        ' Create the output message
        Dim sb = New StringBuilder()
        sb.AppendFormat("Version: {0}" & vbLf, sprVersion)
        sb.AppendFormat("Vue Name: {0}" & vbLf, sprVueName)
        sb.AppendFormat("Mdb Path: {0}" & vbLf, sprMdbPath)
        sb.AppendFormat("Next Tag Number: {0}" & vbLf, sprNextTag)

        ' Clear the text window and add the new output message
        sprApp.TextWindow(DrConstants.DR_TEXT_WIN_CLR, "SPR Tutorial", sb.ToString(), 0)

    End If
End Sub
'

*Note*

In the two examples above, we declare variables beforehand, and then run the different methods required to obtain the SPR information. The GlobalOptionsSet method is used to set the file info mode (47) to on, so that the session files (vue/dri/mdb) are returned for the FileNameFromNumber and FilePathFromNumber methods rather than the .dgn files used to create the vue or dri. The vue/dri file number is 0, and the mdb number is 1.

Also note that rather than use string + append methods to build the output, a stringbuilder was used. I did this primarily because it’s a class better-suited for concatenating strings, and it also has a built-in formatting option for passing variable values (denoted with curl brackets surrounding the parameter number). This is identical to the string.Format() method in implementation.



Here is the resulting output from the implemented methods above:


10. Using the SharpPlant API wrapper, the same results can be achieved using minimal code:

C#:

private void btn_SprConnect_Click(object sender, EventArgs e)
{
    // Create a new SprApplication object
    var sprApp = new SprApplication();

    // Check that the application is connected
    if (sprApp.IsConnected)
    {
        // Build the message string
        var sb = new StringBuilder();
        sb.AppendFormat("Version : {0}\n", sprApp.Version);
        sb.AppendFormat("Vue name: {0}\n", sprApp.SessionName);
        sb.AppendFormat("Mdb path: {0}\n", sprApp.MdbPath);
        sb.AppendFormat("Next Tag Number: {0}\n", sprApp.NextTag);

        // Send the message text to the SprApplication text window
        sprApp.TextWindow_Update(sb.ToString(), "Spr Tutorial");
    }
}

VB.NET:

Private Sub btn_SprConnect_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btn_SprConnect.Click

    ' Create a new SprApplication object
    Dim sprApp = New SprApplication()

    ' Check that the application is connected
    If sprApp.IsConnected Then

        ' Build the message string
        Dim sb = New StringBuilder()
        sb.AppendFormat("Version : {0}" & vbLf, sprApp.Version)
        sb.AppendFormat("Vue name: {0}" & vbLf, sprApp.SessionName)
        sb.AppendFormat("Mdb path: {0}" & vbLf, sprApp.MdbPath)
        sb.AppendFormat("Next Tag Number: {0}" & vbLf, sprApp.NextTag)

        ' Send the message text to the SprApplication text window
        sprApp.TextWindow_Update(sb.ToString(), "Spr Tutorial")
    End If
End Sub
'

Download the source!

In closing I’d like to personally thank Dave Tyner for having the infrastructure in place for hosting this information, as well as personally inviting me to share this knowledge. I am confident that through our collaborative efforts the entire community stands to benefit. I welcome any questions and feedback, as well as what you’d like to see in the next tutorial. Also if you see something in my code that can be improved on, never hesitate to point it out; I will be most appreciative. Until next time, happy coding.

Tags: , , , , , , , , , , , ,

About the Author

About the Author: .NET developer at Jacobs Engineering in Houston, Texas. .

Subscribe

If you enjoyed this article, subscribe now to receive more just like it.

There Are 4 Brilliant Comments

Trackback URL | Comments RSS Feed

  1. Dhaval Somaiya says:

    Hi Parrish,

    Can you help in demonstrating how can be change the label values through C# of any pipe component. I tried with the following code but not sure how to go about it as it isnt giving the expected result.

    ***********START***********************
    int sprResult = 0;
    int itmcnt = 0;
    int objid=0;
    int DR_OBJ_LBL_DATA=3;
    int spr_elementdata = 0;
    string sName = “”;
    string sValue = “”;
    string sSearchCriteria = “FIND Data Line no = “;

    sprResult = spr.ObjectDataSearch(sSearchCriteria, 0, out itmcnt);
    sprResult = spr.ObjectDataSearchIdGet(out objid, itmcnt-1);

    var objData = new DrObjectData();
    spr_elementdata = spr.ObjectDataGet(objid, DR_OBJ_LBL_DATA, objData);

    for (int i = 0; i < objData.LabelDataCount; i++)
    {
    // Get each label
    sprResult = spr.ObjectDataLabelGet(ref sName, ref sValue, i);
    if (sprResult == 0)
    {
    sb.AppendFormat("{0}: {1}", sName, sValue);
    }
    }
    int viewmask = 0;
    sprResult = spr.LabelValueSet(objid, "Insulation", "100 MM", 1, out viewmask);

    ***************END****************

    My emphasis on the following; once I've the label values how do i modify it through C# and get it reflected in SPR. Not sure on how to use spr.LabelValueSet().

    Any help/guidance is greatly appreciated.

    • Allockse says:

      Dhaval,

      From the Drapix_API.chm file that ships with SmartPlant Review I see that the LabelValueSet method is obsolete since version 4.2.

      Since you’ve got a DrObjectDataDbl, you have the label file name and the label key available to you. If Intergraph has removed the ability to modify these values through the API, you could certainly use these two objects to modify the mdb2 file directly if you wanted to. I’ll be getting into reading/writing the MDB in future tutorials, so this may be something I address.

      Since changing these values in the mdb2 will have no effect on the actual models themselves, and will be overwritten the next time a dri or vue is created, this is probably why Intergraph chose to remove it in the first place.

      I’ll bookmark this as something to test the next time I have some time, and will update my findings here.

      Thanks for the inquiry.

  2. tikekaramit says:

    how much of c#.net is useful for SP3D .
    also how about WPF & WCF from .net can be useful in SP3D.

    I will be very thankful to know about this……

Post a Comment

Your email address will not be published. Required fields are marked *

Top