SolidPractices: Getting Started with the SOLIDWORKS API

Revision History
Rev #DateDescription
1.0March 2020Document created
1.1August 2023Added Considerations for SOLIDWORKS Connected.
Document validated for the current release.

Note

All SolidPractices are written as guidelines. You are recommended to use these documents only after properly evaluating your requirements. Distribution of this document is limited to Dassault Systèmes SolidWorks employees, VARs and customers that are on active subscription. This document may not be posted on blogs or any internal or external forums without prior written authorization from Dassault Systèmes SolidWorks Corporation.

This document was updated using SOLIDWORKS 2023 SP03. If you have questions or need assistance in understanding the content, please get in touch with your designated reseller.

Acknowledgments

This document was authored by CADSharp LLC and reviewed by Dassault Systèmes SolidWorks Corporation.

  1. Preface:

The SOLIDWORKS Application Programming Interface (API) is a powerful capability of the SOLIDWORKS software because it allows a user with knowledge of programming to automate almost any part of the software and thereby use SOLIDWORKS in ways that are not possible interactively.

This document provides you with the best practices of developers who have already invested tens of thousands of hours into developing the SOLIDWORKS API, and thereby help you avoiding many common mistakes.

Your Feedback Requested

We would like to hear your feedback and also suggestions for new topics. After reviewing this document, please take a few minutes to fill out a brief survey. Your feedback will help us create the content that directly addresses your challenges.

  1. Introduction

The SOLIDWORKS API is one of the most powerful “features” of the SOLIDWORKS software. This is because it allows a user with knowledge of programming to automate almost any part of the software and thereby use SOLIDWORKS in ways that are not possible under normal circumstances. Of course, the drawback to the SOLIDWORKS API is that it is also the most complex “feature” of the software. It is effectively the intersection of two distinct disciplines: computer-aided design (CAD) and programming. Each of these disciplines has multiple layers of complexity. This means that the depth to which a skilled engineer and programmer can take the SOLIDWORKS API are beyond what most users realize is possible. On one extreme, a user might use the macro recorder to create a macro that shaves off a few minutes of effort each day. On the other extreme, a company might use an add-in or stand-alone application to automate the entire design workflow of their company from front to back, thus saving the company a significant amount of money each year.

The intention of this document is to teach users how to develop with the SOLIDWORKS API, which is well beyond the scope. Instead, the purpose is to provide you with the best practices of developers who have already invested tens of thousands of hours into the SOLIDWORKS API development. These best practices can help you avoid mistakes that make your development experience slow and frustrating for you and your company.

  1. Programming Best Practices

SOLIDWORKS users often ask, “How much programming or software development experience do I need before I can use the SOLIDWORKS API?” The answer is simple, the more the better. Unfortunately, there are no shortcuts with using the SOLIDWORKS API. If you do not know the fundamentals of good software design, then your program, no matter how small, will reflect that. Because most SOLIDWORKS users are self-taught programmers s with less time to invest in software development than they would like, the resulting code is often of low quality even if it ultimately performs the desired task. Low quality code is hard to understand, hard to modify, hard to debug, and hard to reuse.

Over time, a SOLIDWORKS API developer should invest sufficient time into understanding best practices for programming in general. These practices apply to any object-oriented programming (OOP), whether the task is CAD API programming or writing the latest cutting-edge mobile app. The following six best practices are relevant for any SOLIDWORKS API programmer:

  1. Meaningful naming. Always take the time to give your classes, functions, and variables meaningful names. Otherwise, your code is hard to understand. When in doubt, be more descriptive. For example, compare the name “face1” to “largestPlanarFace”. While it may be obvious at the time of writing that this variable stores the pointer to the largest planar face in a body, will it be obvious six months from now?

  2. Good formatting. Failure to indent or nest statements properly makes code difficult to read. Modern integrated development environments (IDEs) like Visual Studio make this easier. However, flagrant violations of this practice still occur when writing Visual Basic for Applications (VBA) macros in the Visual Basic Editor.

  3. Good commenting. It is possible to have too many code comments. If your function names are clear and descriptive, then comments can become redundant. Use comments in situations when it is necessary to provide a detailed explanation of why write code in a particular way. For example, you might write several paragraphs of comments to explain your reasoning for using a particular algorithm and not another algorithm, which actually contains a subtle pitfall.

  4. Control constants from one location. If your code contains multiple instances of a constant value, that value should be stored in a single constant with scope over all classes and methods where it is used. That constant should be referenced every time the constant is needed. If the constant’s value needs to be modified, you then only need to change it in one location rather than finding and changing every instance in your code.

  5. Expose configurable constants. If the end user ever needs to modify a constant’s value, then you should not hard-code that constant. Otherwise, the user must contact the developer in order to do so. This creates a dangerous bottleneck if the developer is unavailable. Only hard-code constants that you are certain will never change (such as mathematical constants, physical constants, and industrial standards). Expose the remaining constants to the user (or at least the administrator) through settings forms or neutral (XML, JSON) data files.

  6. Separation of concerns. This principle contains numerous subprinciples that this document does not address. If you want to learn more, search the internet for information about the set of OOP design principles known as “SOLID”. The common theme in SOLID and many other OOP design principles is separation of concerns. The next section discusses this very important design principle.

  1. Separation of Concerns

Separation of concerns is the idea that every individual variable, function, class, and interface should (usually) have one single purpose. In other words, a function should be concerned with accomplishing one particular task. A class should represent one single object, and so on. The simplest way to understand separation of concerns is to begin by understanding what a violation of the principle looks like.

As an example, imagine that you are creating a program that simulates a basketball game. (Apologies to readers who are unfamiliar with basketball. Hopefully, this example will make sense anyway.) In such a program, you need classes such as Player, Referee, Crowd, Court, Ball, Hoop, ShotClock, and others. Each class has its own properties and methods, which correspond to information and actions that relate to the class. For example, the Player class might have the following properties and methods:

  1. Class: Player

Properties

  • Name

  • Height

  • Weight

  • Speed

  • Methods

  • Run()

  • Dribble()

  • Shoot()

  • Pass()

  • Foul()

  • To demonstrate a simple violation of separation of concerns, imagine that instead of having a method for Dribble() and Shoot(), you have a method called DribbleAndShoot(). The advantage, it appears, is that you have fewer methods. Does this make your program simpler? Not at all, because now you have no way to cause a player to only dribble or only shoot without modifying the inner workings of the function to allow for such situations based on what arguments are passed into the function. The fault of this example might seem obvious. However, programmers of every skill level make this mistake. The solution to this problem is to “refactor” the code. This is also known as “modularizing” or “decoupling”.

When you refactor your code, you are taking the time to ask, “What is the purpose of this code?” It is easy to begin writing a piece of code thinking that it will be simple, only to watch it balloon over time into a monster that makes your program’s code difficult to extend, debug, and reuse. The obvious tie-in to this point is that you need to plan the architecture of your program before you begin writing it. As the tongue-in-cheek saying goes, “Three days of debugging can save you three hours of planning.”

  1. Program Type and Language Comparison

Options Available

Programs written using the SOLIDWORKS API include macros, add-ins, and stand-alone applications. Although you can use any language that supports COM to write these programs, SOLIDWORKS primarily supports VBA, VB.NET, C#, and C++. This document focuses on the VBA, VB.NET, and C# languages because they are by far the most common options. The following chart depicts which languages you can use with a particular program type.

  1. Choosing a Program Type and Language

What program type and language should you use? The program type you use affects the level of integration, ease of development, ease of administration, and performance. The language you use affects the ease of development, security, and performance. What the program type and language do not affect is how you use the SOLIDWORKS API calls themselves (with rare exceptions, which are beyond the scope of this document). The API functionality is available in all program types and languages.

Some SOLIDWORKS API developers rarely write macros except when testing a particular API call. This is because small VBA macros are much faster to write and debug than stand-alone applications or add-ins that accomplish the same thing. It is also faster and simpler to set up a .NET stand-alone application than it is to use a .NET macro. Moreover, the benefits of C++ are limited (usually as they relate to performance), so some developers never write C++ software using the SOLIDWORKS API.

Where does this leave us in terms of recommendations? Assuming that you know VBA and .NET, one recommendation is to always use a .NET add-in or stand-alone application unless you need a quick program for personal use. Of course, not everyone is a professional developer, which means that many people do not know or have time to learn the .NET language. In that case, you can accomplish quite a bit with a VBA macro. However, be aware that you are missing out on the tremendous power of the .NET language. Another disadvantage of VBA macros is that you cannot write them as stand-alone applications. This means that you will never have the flexibility that a stand-alone application offers.

When choosing between add-ins and stand-alone applications, here are some considerations:

  • Flexibility. A stand-alone application is best for flexibility, because you control SOLIDWORKS from a separate program that runs independently of the SOLIDWORKS software. Although this comes at the cost of performance (because API calls have to cross a process boundary), this allows you to run your software on a server or perform large processes overnight that do not require user interaction. Using a stand-alone application, you can also restart SOLIDWORKS if something fails and not lose progress.

  • Integration. Use of an add-in is best here, because the add-in can create a seamless user experience than a stand-alone application. Your user interface (UI) might tie into a task pane, drop-down menu, command tab, launch on a particular event, or hook into an existing command. Performance is best with an add-in because the add-in is running in the same process as SOLIDWORKS. On the other hand, if SOLIDWORKS crashes, your add-in crashes also.

  • Ease of development. Stand-alone applications are much easier to set up and develop. Because they do not interact with the registry, the boilerplate code necessary to create useful stand-alone application is a fraction of what is necessary to have a useful add-in. Stand-alone applications run independently of SOLIDWORKS. Therefore, it is not necessary to close SOLIDWORKS every time you want to modify the code, whereas it is often necessary to close SOLIDWORKS when modifying add-in code. For more information, see the section “Embed Interop Types”.

Add-ins and stand-alone applications each serve specific purposes in the SOLIDWORKS API developers toolbox. It is possible to use both programs in tandem to gain the best of both worlds. There is more discussion of this in the Architecting Add-ins section.

  1. The Macro Recorder

More people try using the macro recorder to avoid learning any programming. This is a mistake for those who try to use the SOLIDWORKS API because:

  • The macro recorder cannot know your intentions. The code that the macro recorder creates has not indentation and often contains unnecessary calls.

  • You cannot record many parts of SOLIDWORKS, such as using custom properties.

  • You cannot record a macro that obtains user input.

  • You cannot record a macro that handles conditional logic. What you record is literally all that happens when you run it.

With this in mind, the macro recorder still has value. For example, if you struggle to find an API in the Help, the macro recorder might be revelatory. Another example is in cases where you do not want to take the time to add in the arguments for an API call with a huge number of arguments manually, such as IFeatureManager.FeatureExtrusionX.

  1. The SOLIDWORKS API Help

Critical to your success as a SOLIDWORKS API programmer is a good understanding about how to use the API. Here are several tips with regard to using the API:

  1. The local API Help is arguably more useful than the online API Help because the local API Help provides an Index that you can use to search by topic. To access the local API help (assuming it is installed), first deactivate the Help > Use SOLIDWORKS Web Help option, and then go to Help > API Help. This opens the API Help compiled help (CHM) file.

  2. When researching API calls, know whether you are on a member page or an interface page. Interfaces, which you can think of as programmable objects, begin with the letter “I”. These interfaces always have the word “Interface” after their name. Members, on the other hand, always have the word “Method” or “Property” after their names, followed by the owner interface in parentheses.

  1. Occasionally, you will see methods and properties that have the letter “I” as a prefix. These methods are for use with unmanaged C++ code and you should ignore these methods in every other context.

  2. At the bottom of most member pages is a sentence that states when the member was added to the SOLIDWORKS API. If there is no availability section, then that means the member was added before the year 2000. The following example shows that the member was added in version 23.0, which corresponds to SOLIDWORKS 2015 SP0.

  1. When using VBA, be aware that the VBA syntax does not appear after the parameters, unlike the .NET syntax, which appears before the parameters. The topmost syntax is for VB.NET, not VBA. Because there are slight differences between the data types in VBA and VB.NET, using the incorrect guide can confuse novice programmers.

  1. Many parameters and arguments in the SOLIDWORKS API are useful to return data and not receive data. These are effectively additional return values in an API call. You can tell that a parameter returns values to you because the VB.NET and VBA syntax uses the “ByRef” keyword before the parameter. The C# and C++ languages use the “out” keyword before the parameter as shown in the following examples.

  1. It is not necessary to use the latest version of an API if one exists. Even though the SOLIDWORKS API might indicate that earlier versions are “obsolete”, this does not mean that they will not work. It is sometimes useful to use obsolete versions if the newer versions contain arguments that are irrelevant to your software’s needs. On rare occasion, a SOLIDWORKS API call or interface is actually deprecated, that is, it no longer works in newer versions of the SOLIDWORKS software. If this is the case, then the API Help makes it obvious. For example, see IBomTable.

  1. The SOLIDWORKS API Object Model

The API Object Model, also known as the SOLIDWORKS API Object Hierarchy, describes the relationship between interfaces in the SOLIDWORKS API. Without an understanding of the API Object Model, programming with the API is a mystery, and using the API to write many programs will generally be a slow and frustrating experience.

For example, imagine that you want to select the largest face in a part programmatically. How would you even begin writing a macro like this from scratch? One suggestion is as follows:

  1. In the API Help, find the API call that you are trying to reach. In this case, IFace2.GetArea.

  • The interface for this API call is IFace2.

  • The member name for this API call is GetArea.

  1. At the API Help entry for IFace2.GetArea, go to the interface page for IFace2 by clicking the IFace2 Interface link just below the title of the API call. This takes you to the IFace2 interface page in the API Help. On this page, locate the section toward the bottom called Accessors. This section contains a list of all API calls that return a pointer to this interface. In other words, an “accessor” is an API call that grants access to another interface in the SOLIDWORKS API.

  2. Your program needs to use the correct accessor to get to IFace2. The list of accessors for IFace2 is very large and the API calls appear in the format [interface]::[member name]. Based on how your program works, most of these accessors are not relevant. Because you want to get the largest face in a part, and because a part consists of bodies, it makes sense that IBody2.GetFaces is the accessor you need. Click into this API call.

  3. Now that you are in the API Help page for IBody2.GetFaces, you start the process over again of finding the appropriate accessor for IBody2, which is IPartDoc.GetBodies2. There is no accessor for IPartDoc. Instead, you cast the IModelDoc2 pointer to IPartDoc, which means that you need to find the correct accessor for IModelDoc2.

  1. General SOLIDWORKS API Usage Advice

  2. Version Interoperability

Unlike SOLIDWORKS models, SOLIDWORKS API calls are forward and backward compatible as long as they exist in the APIs of the target version. It is rare that a program will “break” for this reason, since most commonly used API calls have been available in the API for decades. If you do run into a situation where an API call is not available in your target version, there may be an obsolete version of the call available. If no obsolete version exists, then it is likely that another workaround is possible through a variety of other API calls.

  1. Considerations for SOLIDWORKS Connected

SOLIDWORKS Connected is the version of SOLIDWORKS that is available as part of several 3DExperience roles. It is still installed locally and operates similarly to the standard SOLIDWORKS Desktop offerings. Typical usage will primarily involve documents saved in the 3DExperience platform. While SOLIDWORKS Connected shares the same API as SOLIDWORKS Desktop and supports custom macros & add-ins, there are specific behavioral and conceptual differences that must be considered.

  1. Files can still be opened locally or from 3DExperience using OpenDoc7, but limitations apply. See the API documentation for OpenDoc7 and PLMObjectSpecification for details.

  2. Documents can be saved locally, but once a local document has been saved to 3DExperience, it should only be opened from that platform, using the method described above.

  3. Documents can be saved to 3DExperience using IModelDocExtension.SaveTo3DExperience.

  4. The PDM Professional API does not work with SOLIDWORKS Connected, as 3DExperience provides its own lifecycle management functionality. Other PDM/PLM integrations will also be incompatible for this reason.

Applications that use the SOLIDWORKS API can be written to support both SOLIDWORKS Desktop and SOLIDWORKS Connected. This can be accomplished by adding a switch in the code whenever a file is opened or saved, using ISldWorks.ApplicationType.

  1. Naming SOLIDWORKS Variables

When using VBA, it is standard to use the Hungarian notation naming convention, in which a prefix identifying the variable’s data type begins the variable name. For SOLIDWORKS variables, a recommendation is to use the “sw” prefix, which is standard across the SOLIDWORKS API Help. .NET does not use the Hungarian notation naming convention except in form control variables. Regardless of what notation you choose, what is most important is that you remain consistent throughout your project.

  1. Early Binding SOLIDWORKS API Object Variables

When you declare a SOLIDWORKS object variable, you should declare it using its specific interface and not simply as Object, which is the default declaration when you open a new macro or when you use the macro recorder. For example, a new macro uses the following:

Dim swApp As Object

Because this variable is actually a declaration for ISldWorks, the declaration should be:

Dim swApp as SldWorks.SldWorks

By declaring the variable as its specific object type, Visual Studio IntelliSense is available in the Integrated Development Environment (IDE). This can greatly increase your efficiency while developing.

  1. Optional Arguments

There are no optional arguments in the SOLIDWORKS API. However, you can effectively “ignore” an argument by simply passing in its default value.

  • VBA default values are Nothing for objects and Empty for non-objects.

  • VB.NET default value is Nothing.

  • C# default values are null.

  • C++ default values are null.

Although the default value for a data type might correspond to 0 (zero) or a zero-length string, consider using the actual words Empty, Nothing, or null to clarify that you intentionally “ignored” that argument.

  1. Common Pitfalls

  • Assuming feature and entity names. For example, assuming that the XZ plane has the name “Top" or contains the word "Top". If the plane was renamed, or if the localization is not set as English, the code fails because it cannot find the XZ plane.

  • Using IModelDoc2.GetTitle to get a model’s name. This API call only returns the file extension if the Show file extensions for known file types option is active in the Windows® folder settings. Parsing the file name from the string returned by IModelDoc2.GetPathName is much safer.

  • Traversing feature trees without considering order. Sometimes it is desirable to traverse a feature tree in the order of feature creation. In this case, you can use IModelDoc2.FirstFeature along with IFeature.GetNextFeature. If you need to return the feature tree in the exact order that it appears, you can use the ITreeControlItem interface.

  • Using IModelDocExtension.SelectByID2 to make selections in the display area. This API call is notoriously unreliable for selecting items in the display area, particularly entities such as faces. While the call does select items in the feature tree if the feature names are known, relying on the XYZ coordinates alone can result in wrong selections.

  • Adding sketch entities to a sketch without turning off snapping. Many parts of the API mimic manual usage of SOLIDWORKS. An example of this is adding sketch entities. When you create a point using the API, the point snaps to the nearest reference point. This can result in inaccurate results if the model is not zoomed in enough. The solution is to use ISketchManager.AddToDB to add sketch entities directly to the SOLIDWORKS sketch database.

  • Inserting components using IAssemblyDoc.AddComponent5. There are two important caveats to this method that you will miss without carefully reading the remarks. First, the component you are adding must already be open. Second, the XYZ location specified is where the component’s bounding box center is placed, not its origin.

  • Misunderstanding or neglecting transforms. Transforms are necessary when converting points and vectors from sketch space to part space, component space to assembly space, drawing view space to drawing space, or the opposite of any of these. This topic is complex and requires a solid understanding of vector algebra. Studying API Help examples is a good place to start, though online learning resources are available. In particular, know that IComponent2.Transform2 returns the transform of the component relative to the top-level assembly and not the component’s immediate parent.

  • Misunderstanding casting and interface inheritance. While the SOLIDWORKS API does not support object inheritance, it does support interface inheritance, which behaves in a similar way. Practically, this means that you can cast a higher-level interface variable to a lower-level interface variable, and vice versa. Here is the official list of all interface inheritance in the SOLIDWORKS API. Without using interface inheritance, you face many insurmountable obstacles. Therefore, it is crucial that you keep this list handy.

  1. Troubleshooting API Calls

If an API call does not behave the way you expect, several options are available to help you troubleshoot the problem:

  1. Know what the API call actually does. Sometimes the names of API calls are vague or do not reflect exactly what the API does, therefore it is essential to closely read the description to make sure that your expectation of the call’s behavior matches the actual behavior.

  2. Look at examples. Search the SOLIDWORKS API Help, Google, or websites that specialize in SOLIDWORKS API for examples of an API call in use in a working program.

  3. Try writing a simpler macro. Trying to understand why an API call does not work is much easier in the context of a simple macro that demonstrates only the usage of that API call and nothing more. This technique of isolating the problem at hand is common in all forms of debugging.

  4. Review the remarks in the SOLIDWORKS API Help. The remarks section contains many helpful bits of information, including exceptions to the normal behavior of the API call.

  5. Look in the SOLIDWORKS API forums. It is unlikely that you are experiencing a problem that no one has ever seen before. Quite often, there is already an answer to the question in the API section of the official SOLIDWORKS API forum.

  6. Search the Knowledge Base. The official SOLIDWORKS Knowledge Base, which you can access from the customer portal, includes bug reports (SPRs) for all parts of the SOLIDWORKS software, including the API. The API call that you are using might be misbehaving because of an actual bug. If SOLIDWORKS API Technical Support is already aware of the bug, then you can find information about the issue in the Knowledge Base.

  7. Email SOLIDWORKS API Technical Support. If you have exhausted all other options, you might be experiencing an unreported bug that you should report to API Technical Support. At the very least, they will try to solve your problem and update the documentation as necessary. You can send an email message to apisupport@solidworks.com.

  1. General Best Practices for .NET Development

  2. Installers

Although many installer options are available for the .NET software, a very useful utility is the Installer Projects extension that you can download as a free plugin for Visual Studio. Make sure that the version you download works with your version of Visual Studio. When you use this plugin to create a Microsoft Installation (MSI) package for an add-in:

  • In the add-in DLL properties, be sure to define the Register field as vsdraCOM. Otherwise, the add-in does not register with COM on the user’s machine.

  • The installer package does not use RegAsm.exe to register the DLL with COM. Therefore, it is necessary to use the Windows Registry Editor in the installer project to specify what keys you need to create in HKEY_LOCAL_MACHINE.

A downside of using this extension is that it is not possible to link the File Version field in the project’s Assembly Information to the Version field in the setup project’s properties. This means that you need to increment the version in both places and ensure that their versions match. Otherwise, the installation could fail. When you increment the installer project version, you receive a prompt to change the installer’s GUID, which you should accept.

Lastly, a recommendation is that you install programs in C:\Program Files rather than in the user’s AppData folder. The former requires administrative rights because this is the intended Windows location for program installations. The AppData folder does not require such rights because this folder is the intended Windows location for files that programs create and modify. While Windows allows program installations in the AppData folder, this effectively circumvents the settings established by the systems administrator. Users may also have a hard time finding the installation folder for programs in the AppData folder because they expect to find the programs under Program Files.

  1. Versioning

Every change to the code produces a new binary or binaries, which should be assigned a new version. This way, every deliverable to your users will have its own version and there is no confusion on the part of the user or the developer regarding the installed version. This is particularly important because users may fail to update their software properly despite thinking that the update was successful. If this happens, users might report the same bug that you thought you had already fixed, and you will then put in extra effort investigating an issue that you actually already resolved.

You can change the file version for a .NET binary in Project > Properties > Assembly > Assembly Information. This dialog box provides four values that you can change. A best practice is to use the first three values with this scheme: Major.Minor.Patch. Some developers do not use the last value, which is the Build number. If you use the Build number, you can set it up to auto-increment with every new build. If you use the shorter versioning scheme, consider treating each number as follows:

  • Major: Increment this number when you add new features that break compatibility with previous versions. For example, configuration files that can load into earlier versions of the software that cannot load into the new version.

  • Minor: Increment this number when you add new features that do not break compatibility with previous versions.

  • Patch: Increment this number when you fix bugs or make insignificant improvements, such as changing text on a form or adding comments.

  1. Assembly Information

As mentioned in the Versioning section, you can use the Assembly Information dialog box in the project settings to specify the file version. Consider also using this dialog box to specify the program name, description, and developer (under Company). Any time you need to use these values in your program, you can access them using the .NET FileVersionInfo class. Examples of when you might need these values include:

  • Using the program title in message box titles.

  • Using the program title, version, and company in an About dialog box.

  • Using the program title and description in the Title and Description string values when registering an add-in with SOLIDWORKS.

  1. Primary Interoperability Assemblies

To use the SOLIDWORKS API, PropertyManager pages, ISwAddin, and other resources, a class library project requires references to the SOLIDWORKS Primary Interop Assemblies (PIAs).You can find these PIAs, which are simply DLLs, in the api\redist folder of the SOLIDWORKS installation folder. Instead of referencing the files from this location directly, you should copy them into a third-party folder that you create in your project, and reference the files from there. This way, if you create a ZIP archive of your project and send it to someone else, or if you reinstall SOLIDWORKS in a new directory, the references will not become broken.

  1. Source Control

Source control is a deep topic but worth discussing briefly in this document. In short: any serious .NET developer should use source control. The two most common source control systems, also known as version control systems, are Git and Mercurial. Source control systems provide developers with many of the same advantages that Product Data Management (PDM) provides for CAD users: better organization, collaboration, and security. In this context, “security” not only refers to the ability to assign repository permissions to users (much like the assignment of vault permissions in PDM), but also security from errors. If you make significant modifications to a program and then realize that you must scrap the modifications, you can easily revert to an earlier version of the software.

An example organization uses Git for the source control system, Sourcetree for the Git graphical user interface (GUI), and BitBucket for online repositories and collaboration. GitHub offers similar options that should work equally well for SOLIDWORKS API developers. If you are in an industry that requires certain security compliance, you might need to set up a remote server that hosts your organization’s repositories.

  1. Embed Interop Types

After referencing the SOLIDWORKS PIAs in your project, you can specify that Visual Studio embed the used portions of the PIAs into your binary by setting the Embed Interop Types property to True as shown in the following image. This has a number of benefits:

  • Reduces the number of dependent binaries in your deliverables.

  • Reduces the size of your deliverables.

  • Reduces the number of explicit casts that C# code requires.

On the other hand, this option can cause problems in certain situations:

  • It can cause cast exceptions involving API calls that pass an array of structures. This is true in the SOLIDWORKS PDM API. It might also apply to the SOLIDWORKS API.

  • It can cause other cast exceptions and prevent the building of certain libraries, although there are no known examples that are easy to reproduce.

  • You cannot edit add-ins while debugging them. Because there is a limited number of kinds of code that you can edit during debugging in the first place, this downside is negligible if you never edit add-ins during debug mode. For more information, see the Debugging Add-ins section.

The safest course of action is to define the Embed Interop Types option as False. However, if you are confident that you can identify when this property is causing problems and want to reap the benefits until then,, you can set the option to True. A strong recommendation is for novice SOLIDWORKS API developers to define the option as False.

Error Handling and Program Termination

While the phrase “error handling” typically refers only to unhandled exceptions, in three circumstances the program should present information to the user:

  • The program runs successfully. If it is not obvious to the user, then the user should receive notification that the program has finished running, without errors.

  • The program runs successfully, but with warnings. A warning occurs when processing is successful but the output might not be desirable. As a simple example, a custom property used in processing might be missing from a model. This property is not critical to the completion of the processing, but the user should be aware that it was missing.

  • The program fails to run. This can occur for at least two reasons.

    • A bug in the program produces an unhandled exception. In this case, the user should receive notification of the failure and advised to provide the log file and any associated files that the developer might need for debugging.

    • The user-provided input is not sufficient for allowing the program to run. With reference to the previous example, perhaps the user wants processing to stop immediately if the program finds a model without custom properties.

  1. Logging

Add-ins and stand-alone applications that contain lengthy processing operations should contain logging capabilities. This helps the developer quickly reproduce and fix bugs. Best practices include:

  • The log file is primarily for the developer, not for the end user. For example, when a program throws and exception in a program you write, the user receives a message (usually as a message box) that says, “Unhandled exception occurred. Please send the log file and models to technical support.

  • Your log file should contain the three types of information discussed in the last section: information, warnings, and errors. It should be obvious in the log file which line corresponds to which type of information.

    • Information: A general term for any information that is not a warning or error.

    • Warning: Something is amiss, but the program continues to run.

    • Error: The program cannot continue for this reason.

  • To avoid permissions issues, tour program should place the log files in the user’s AppData folder, not in the installation folder. Likewise, the program should be installed in the Program Files folder, not in AppData.

  • Your program should allow users to access the log file folder easily, or at least an easy way to package the log files to send to the developer. It is helpful to include a function somewhere in the main form or in a settings form that says Open Log Folder.

  • Use a professionally written logging class. Use this class to create and then close a new text stream every time there is a modification to the log file. Otherwise, if your program crashes, the text stream never closes properly, which can result in write errors. Many excellent loggers such as NLog, log4net, and Serilog are available free from the NuGet Gallery website.

  • Name each log file after the date and time. That way, the file name is always unique and you never inadvertently rewrite to an existing log file on the next processing attempt. For example: “log 08-15-19 18_48_46.txt

  • Regardless of what logger you use, your log files should contain the following information:

    • The time the program runs and, optionally, the time of every single log entry.

    • The program name and version. Use this information to determine if the user is running the correct version of your software.

    • User inputs. This includes the fields of every single user control and the values of any configuration value in use.

    • Optionally, the SOLIDWORKS version. Sometimes it is not feasible to obtain this value using ISldWorks.RevisionNumber. However, this is a recommendation if you have access to the ISldWorks pointer when logging begins.

    • The sequence of every notable operation that occurs during processing. For example, if your program batch processes all drawings in a folder by changing outdated title block information, your log file should make it clear what file is processing at any given point and what the last major operation occurred before the failure. Use indentation and extra lines to make text readable.

Here is an example log file from an add-in called Acme Tools:

Remembering User Inputs

If user inputs must persist in the UI, it is a best practice to use the Windows Application Settings feature, which allows users to input specifications in the project settings for an add-in or stand-alone application. When using the Application Settings feature, Windows stores the user settings in the user’s AppData folder. Otherwise, it is necessary to create a custom settings storage and retrieval class to handle the same tasks effectively. If for some reason you do create your own custom class, then you should store the settings in the user’s AppData folder and not in the registry or the Program Files folder, because the latter locations might require administrative rights that could prevent your class from functioning properly.

  1. Message and Dialog Boxes

As a best practice, when creating message and dialog boxes over ISldWorks.SendMsgToUser2, use the .NET System.Windows.Forms.MessageBox class. There are two reasons for this. First, you cannot control the message box title using ISldWorks.SendMsgToUser2. This can make it unclear to the user whether it is your program or the SOLIDWORKS application that is sending the message. Second, the .NET MessageBox class gives you far more control over the look and function of the message.

  1. About Boxes and Help Pages

Have every program provide the end user with the following information, typically in the form of an About box:

  • The name of the program

  • The version of the program

  • The name of the developer (the end customer might prohibit this)

  • How to contact support

  • Preconditions and expected outcome when running the program. Otherwise, link to a help page with this information

  1. XML Comments

XML comments allow the developer to create custom IntelliSense text that appears in Visual Studio. This document does not cover how to use the comments, however there is no reason not to use them if you are developing a framework or library for frequent reuse in other programs. Furthermore, use of third-party tools like Sandcastle make it possible to create a Help file from the XML comments in a project.

  1. Add-in Development Best Practices

Using the SOLIDWORKS API SDK versus writing an add-in from scratch

The SOLIDWORKS API SDK is a sample add-in in the form of a template that demonstrates registration, event handling, and user interfaces. Typically when using the SDK as the basis of an add-in, the developer first pares down the SDK code to use only the code that is necessary for the add-in. While this is a satisfactory place to start for someone with little add-in development experience, more experienced developers can create their add-in from scratch or start with a template that contains the minimum of what they need. This results in cleaner code, and promotes a deeper understanding of the inner workings of add-ins. Instead of using the SDK as a starting point for your add-in, consider using the SDK only for reference and learning purposes.

  1. Exposing the ISldWorks Pointer

The ISwAdd-in interface provides a method called ConnectToSW that passes the pointer to ISldWorks into the add-in so that you can use the SOLIDWORKS API. The recommendation is that you assign this reference to a variable with public or internal / friend access so that the entire project can use it. Because the pointer value never changes as long as the add-in is running, this type of “global” access is perfectly safe and removes the need for the developer to pass the pointer around the add-in via arguments.

  1. COM Visibility

Only make a class COM-visible if it actually needs to be COM visible. You can do this by adding the tag to the class name. Do not activate the Make assembly COM-visible option in Project > Properties > Application > Assembly Information. This makes all classes in your add-in COM-visible, which is unnecessary. In a typical add-in, the only classes that need to be COM-visible are those that implement ISwAddin and IPropertyManagerPage2Handler8 (when using a PropertyManager page). The following image shows an example of this tag, used in the entry class of an add-in.

Add-in Registration

SOLIDWORKS add-ins require registering the DLL in two places in the registry:

  • HKEY_CLASSES_ROOT\CLSID – This is where the DLL registers with COM. One of the fields here states the path to your DLL on the local machine.

  • HKEY_LOCAL_MACHINE\Software\SolidWorks\AddIns – This is where the add-in registers with SOLIDWORKS. When SOLIDWORKS runs, it correlates the GUID found here with the GUID found in the COM-registration location. That way, SOLIDWORKS knows the location of your DLL.

Typically, a developer registers an add-in during development using the RegAsm.exe tool that comes with the .NET framework. The purpose of this tool is to register DLLs written in .NET with COM. Although RegAsm.exe only registers the DLL with COM, it can also initiate the registration and unregistration of the DLL with SOLIDWORKS. This is true as long as you use the and tags with functions that programmatically create and remove the registry gets in HKEY_LOCAL_MACHINE. Because there is no downside to using this approach, the recommendation is that every developer include such functions in their add-in because it greatly speeds up development. For examples, see the SOLIDWORKS SDK.

Because it is tedious to run RegAsm.exe from a command prompt, developers typically run the tool it one of two ways:

  • Using the “Register for COM interop” option. Taking after the SOLIDWORKS API SDK, the Register for COM interop option is activated in Project > Properties > Build > Output. Registration occurs when the project builds. Unregistration occurs when the project is cleaned. If Target CPU = AnyCPU then additional post-build event code is required to ensure use of the 64-bit version of RegAsm.exe.

  • Using batch (BAT) files. In this approach, the developer creates two BAT files, one for registration and the other for unregistration. These BAT files run RegAsm.exe directly with the appropriate flags. For example, if the DLL has the name MyFirstAddin.dll, then you can place the aforementioned BAT files in the add-in’s project folder with this code:

The superiority of one method over the other is debatable. This author favors the second approach. The main reason is that using BAT files permits registration and unregistration of an add-in without opening Visual Studio. This allows consideration of separation of concerns with respect to registration. That is, using Visual Studio to work with code, and using the BAT files to handle registration. Moreover, there are at least two downsides to the first approach. First, use of the Register for Com interop option requires that you create a post-build event in every project to ensure proper registration. This is rather tedious. Second, that option requires building or cleaning the code to register or unregister the DLL respectively. This might not be desirable.

  1. Tools Suite Add-ins

If you have numerous programs that the users at your company need to access, the recommendation is to create a single “tools suite” add-in that contains all of these programs. This allows for a single installation and easier administration, rather than numerous add-ins. This is especially useful for companies that use numerous macros use and wish to bundle them into a single package. Users typically access these programs from a drop-down list or via command button. The drop-down list of four tools created for a company called “Acme” might look like this:

  • Tools

    • Acme Tools

      • Assembly Creator

      • Assembly Analyzer

      • Drawing Creator

      • BOM Exporter

A recommendation is that you create each of these programs as its own project inside the solution, with one of the projects being the actual add-in that references the other projects. That solution structure looks like this:

  • Solution: Acme Tools

    • Project: Acme Tools

    • Project: Assembly Creator

    • Project: Assembly Analyzer

    • Project: Drawing Creator

    • Project: BOM Exporter

The point of entry from the main add-in DLL into the other DLLs is through the UI. For example, when a user clicks the Assembly Creator function, a call is made into that DLL.

  1. Debugging Add-ins

It is not as easy to debug running add-ins as it is to debug VBA macros. If the Embed Interop Types property is set as False, it is possible to make some changes unrelated to declarations, which can then run without restarting the add-in. For more complex code adjustments, it is necessary to stop debugging SOLIDWORKS, modify the code, and then restart SOLIDWORKS. For certain test procedures, this is a very time-consuming process. To speed up testing, one option is to create a stand-alone application that allows the developer to test the add-in code without actually loading the add-in into SOLIDWORKS. This “tester” stand-alone application has the following requirements:

  1. The tester needs to receive the correct inputs because the add-in UI is not available for use. You can often handle this by creating a simple Windows user form that mimics the core functionality of the add-in UI.

  2. The tester must connect to the active SOLIDWORKS session, in which the add-in is not loaded.

  3. The tester must reference the add-in project or DLL, which has the appropriate classes and methods exposed as public.

  4. The tester should use ISldWorks.CommandInProgress to reduce performance issues caused by API calls made across the process boundary.

After setting up this, you should be able to keep SOLIDWORKS and any associated models for testing open while you debug the add-in code.

  1. Updating Add-ins

For any organization that relies heavily on a custom add-in, it is important to know how to update add-ins with minimal administrative effort. Remember that an add-in should be installed locally because local registration is always required. It might be possible to store the add-in binaries on a network drive (as can be done with a VBA macro), which are replaceable as necessary. However, this is fruitless if it is not possible to register the DLL in that location. Therefore, assuming a local installation with the master version of the binaries stores on the server, here is a simple recommended workflow:

  1. Have users start SOLIDWORKS from a custom launcher that always copies the binaries stored on the server over to the local machine (if the versions are different) before running the SOLIDWORKS executable file. This is a simple solution but fails entirely if the user does not use the aforementioned custom launcher.

  2. To mitigate the problem of a user forgetting to use the launcher, the add-in can still run a version when loads. This means that it checks the current version against the server version. If the versions differ, the user receives notification that they should close SOLIDWORKS and then restart the application by using the custom SOLIDWORKS launcher. If you include this step, the developer can allow the user to store the server path to the binaries in an external settings file rather than by hard coding the path in the program.

  1. Architecting Add-ins

While add-ins come in many shapes and sizes, a generic and common form of add-in follows this workflow:

  1. The user opens the add-in UI. Usually this occurs from a drop-down list, command button, task pane, or by hooking into an existing SOLIDWORKS command.

  2. The user enters information and clicks a “Process” button (or something similar).

  3. During the processing, the add-in logs progress.

  4. Processing completes or fails. Either way, the user receives notification.

For an add-in such as this, a recommendation is to have the following classes, although the exact number and names are not critical. For example, it is possible that the UI and processor will have several classes each.

  • Main – This is the COM-visible class that should implement ISwAddin, expose a pointer to ISldWorks to the rest of the project, handle registration, and contain the UI callbacks.

  • UserInterface – This class builds the UI and contains code that relates to handling the UI.

  • Inputs – This class contains the user inputs and passes from the UserInterface into the Processor so that processing occurs according to the user’s specifications.

  • Processor – The class that contains or initiates the code that executes the main tasks of the add-in. This is where most SOLIDWORKS API calls are made.

  • Logger – The class that handles logging.

If you are not sure if the final form of your program should be a stand-alone application or an add-in, consider creating an add-in with public access given to the methods that receive inputs and begin program execution. This creates a public API that you can use from a stand-alone application. This does not require the add-in to be running, and you should use ISldWorks.CommandInProgress to increase performance. If you want a stand-alone application to control a running add-in, then you need to use ISldWorks.GetAddinObject. In testing, controlling the add-in directly does not improve performance; therefore, the author does not recommend this approach over a public API.

  1. Stand-Alone Development Best Practices

  2. Getting the ISldWorks Pointer

In an add-in, there is only one-way to get access to ISldWorks, and that is through the ThisApp parameter passed by ConnectToSolidWorks(). However, in stand-alone applications, the developer has several options, two of which include:

  • System.Activator.CreateInstance() – This is the simplest and most common means of getting ISldWorks. In its parameters, you can specify a major version, and this method gets an instance of this version if it is already open or creates a new instance. However, there are a few downsides to this method. First, you cannot use this method to get pointers to multiple instances of SOLIDWORKS that are running simultaneously on a computer. Second, the method opens SOLIDWORKS without loading certain add-ins loaded.

  • System.Diagnostics.Process.Start() – This method by itself only opens SOLIDWORKS; it does not return a pointer. To get the pointer, you need to access the Running Object Table and use the process ID to locate the correct COM object. How this occurs is beyond the scope of this document and is quite complicated. Suffice to say that this method is still worth mentioning because, unlike Activator.CreateInstance, you can get separate pointers to each instance of SOLIDWORKS running. This is significant when you need the performance gains of running multiple SOLIDWORKS automation processes simultaneously.

  1. Testing If SOLIDWORKS Crashed

In professional experience, SOLIDWORKS crashes during the running of an add-in not due to instability in SOLIDWORKS itself, but because you can push the limits of software after the creation of hundreds of thousands of COM objects (Runtime Callable Wrappers). While COM objects can be released after their use of Marshal.ReleaseComObject, sometimes this is not a good option for architectural reasons. Regardless of why SOLIDWORKS might crash, you can determine if a crash occurred by looking at the exception message when an exception occurs. If the COM server (SOLIDWORKS) is no longer available, then you can get exceptions that contain the following strings:

  • "RPC server is unavailable"

  • "remote procedure call failed"

  • "COM object that has been separated from its underlying RCW cannot be used"

  • "The server threw an exception"

  1. Calling An Add-in From a Stand-Alone Application

As mentioned in Architecting Add-ins, you can call a running add-in from a stand-alone application by using ISldWorks.GetAddinObject. However, there may be no performance benefit over creating the add-in DLL with a public API and using ISldWorks.CommandInProgress. Therefore, it is not a recommendation to use ISldWorks.GetAddinObject unless the add-in DLL does not grant the public access you need.

  1. Add-in User Interfaces

This section distinguishes between the types of GUI that are available to the SOLIDWORKS developer, and the different means by which these you can launch these interfaces.

  1. User Interfaces

  • Windows Forms. This is the simplest option, but it has the least integrated look.

  • PropertyManager pages. Also known as “PMPs”, this is a classic option when you want the user to experience a native SOLIDWORKS look and feel while using your add-in. For more information, see “IPropertyManagerPage2”.

  • FeatureManager page. This creates a custom FeatureManager tab by using IModelViewManager.CreateFeatureMgrWindowFromHandlex64. The main advantage of this approach over IPropertyManagerPageWindowFromHandle (which is a type of PMP control) is that you can create multiple tabs simultaneously, whereas you cannot create multiple PMPs simultaneously.

  • Task Panes. Another common option that is useful when you want to integrate with a system or server outside of SOLIDWORKS.

  • None. An add-in does not require a GUI. Consider creating a GUI only if the add-in requires user input or user verification of certain parameters before running.

  1. Launching User Interfaces

  • Event notifications. This option is necessary not only when you want to extend the functionality of SOLIDWORKS (such as reminding a user to deactivate a license before closing SOLIDWORKS) but also to override existing functionality. An example of the latter is overriding the normal Edit Materials dialog box with a custom material picker.

  • Drop-down lists.

    • Use ISldWorks.AddMenu and ISldWorks.AddMenuItemX.

    • This list the add-in under the Tools menu.

    • Developers can specify in which document types the list appears.

    • Developers can specify an icon for each command.

    • End users can create keyboard shortcuts for each command.

    • It is much easier to code than CommandManager tabs. The recommendation is to use drop-down lists instead of CommandManager tabs if the end user has no preference.

  • Toolbars.

    • This lists the add-in under the Tools menu by using ISldWorks.AddToolbarX and ISldWorks.AddToolbarCommandX. Because CommandManager tabs have largely superseded toolbars, this rarely used. For more information, see the API Help.

  • Context menu items.

    • You can add menu and sub-menu items to specific context and shortcut menus by using ISldWorks.AddMenuPopupItem4. For more information, see the API Help.

  • CommandManager tabs.

    • You can use ICommandManager to create drop-down lists, toolbars, and CommandManager tabs. Because this interface can be tedious to use, consider using ISldWorks.AddMenu or AddMenuItemX if you only need to create a drop-down list.

  • Task Pane button.

    • Used to launch a task pane UI.

  1. Stand-Alone User Interfaces

Because the entire purpose of a stand-alone application is to avoid integrating with SOLIDWORKS, it is a recommendation that developers only use Windows Forms, Windows Presentation Foundation (WPF) controls, or a console as the interface. As a best practice, use a console application when there is no requirement for a graphical interface. With console applications, the entry function can receive parameters sent through from a command prompt, thereby allowing other programs or CAD admins to hook it up with their existing workflow.

We hope that you find this document informational and useful and request that you leave a brief feedback about the topics that you want us to cover in the next revision of this document. Click here for a complete list of SolidPractices documents available from DS SOLIDWORKS Corp.