Create VB.NET Stand-Alone (exe) application for SOLIDWORKS
In this tutorial I will demonstrate how to connect to SOLIDWORKS application from out-of-process (a.k.a Stand-Alone) application (e.g. Windows Forms, Windows Console) using VB.NET and Microsoft Visual Studio.
For more detailed explanation of the approaches discussed in this article please read the Connect To SOLIDWORKS From Stand-Alone Application article.
Creating new project
I will be using Microsoft Visual Studio development environment. You can use any edition of Visual Studio. The same code will work in Professional, Express or Community editions. Follow this link to download Visual Studio
- Open Visual Studio
- Start new project:
- Select the project template. I would recommend to start with Console Application project template as it contains the minimum pregenerated code:
- Add reference to SolidWorks Interop library. Interop libraries are located at SOLIDWORKS Installation Folder\api\redist\SolidWorks.Interop.sldworks.dll* for projects targeting Framework 4.0 onwards and SOLIDWORKS Installation Folder\api\redist*CLR2**SolidWorks.Interop.sldworks.dll for projects targeting Framework 2.0 and 3.5.
For projects targeting Framework 4.0 I recommend to set the Embed Interop Types option to false. Otherwise it is possible to have unpredictable behavior of the application when calling the SOLIDWORKS API due to a type cast issue.
Now we can add the code to connect to SOLIDWORKS instance.
Creating or connecting to instance
Probably the most common and quick way to connect to COM server is using the CreateObject method. Alternative methods are: Activator::CreateInstance and GetObject. Note, that GetObject will create new instance if it cannot connect to the active session.
Const PROG_ID As String = "SldWorks.Application" 'Using Interaction.CreateObject function Dim app1 = TryCast(CreateObject(PROG_ID), SolidWorks.Interop.sldworks.ISldWorks) app1.Visible = True 'Using Interaction.GetObject function Dim app2 = TryCast(GetObject("", PROG_ID), SolidWorks.Interop.sldworks.ISldWorks) app2.Visible = True 'Using Activator Dim progType = System.Type.GetTypeFromProgID(PROG_ID) Dim app3 = TryCast(System.Activator.CreateInstance(progType), SolidWorks.Interop.sldworks.ISldWorks) app3.Visible = True
I would recommend to use Activator::CreateInstance as this allows to connect to the session in 2 steps:
- As SOLIDWORKS application is registered as COM server we can create the type from its program identifier via Type::GetTypeFromProgID method
- Construct the instance of the type from the type definition.
This approach would allow better troubleshooting options in case of an error: if the first step failed it means that either COM class is not registered or cannot be accessed from the registry; otherwise this might indicate some permissions issues. Please read the Connect To SOLIDWORKS From Stand-Alone Application article for explanations of limitation of this approach.
Alternatively you can connect to active (already started) session of SOLIDWORKS using the Marshal::GetActiveObject method. Unlike calling the GetObject, this approach will ensure that there will be no new instances of SOLIDWORKS created and will throw an exception if there is no running SOLIDWORKS session to connect to.
Const PROG_ID As String = "SldWorks.Application" Dim app = TryCast(System.Runtime.InteropServices.Marshal.GetActiveObject(PROG_ID), SolidWorks.Interop.sldworks.ISldWorks)
Getting the running instance via ROT
In order to connect to already running specific session of SOLIDWORKS or to be able to create multiple sessions you can use Running Object Table APIs. Please read the Connect To SOLIDWORKS From Stand-Alone Application article for more details about this approach.
Imports System.Runtime.InteropServices Imports System.Runtime.InteropServices.ComTypes Imports SolidWorks.Interop.sldworks Module CodeStackSample <DllImport("ole32.dll")> Private Function CreateBindCtx(ByVal reserved As UInteger, <Out> ByRef ppbc As IBindCtx) As Integer End Function Sub Main() Const SW_PATH As String = "C:\Program Files\SOLIDWORKS Corp\SOLIDWORKS\SLDWORKS.exe" Try Dim app = StartSwApp(SW_PATH) Console.WriteLine(app.RevisionNumber()) Catch ex As Exception Console.WriteLine("Failed to connect to SOLIDWORKS instance: " & ex.Message) End Try Console.ReadLine() End Sub Function StartSwApp(ByVal appPath As String, _ ByVal Optional timeoutSec As Integer = 10) As ISldWorks Dim timeout = TimeSpan.FromSeconds(timeoutSec) Dim startTime = DateTime.Now Dim prc = Process.Start(appPath) Dim app As ISldWorks = Nothing While app Is Nothing If DateTime.Now - startTime > timeout Then Throw New TimeoutException() End If app = GetSwAppFromProcess(prc.Id) End While Return app End Function Function GetSwAppFromProcess(ByVal processId As Integer) As ISldWorks Dim monikerName = "SolidWorks_PID_" & processId.ToString() Dim context As IBindCtx = Nothing Dim rot As IRunningObjectTable = Nothing Dim monikers As IEnumMoniker = Nothing Try CreateBindCtx(0, context) context.GetRunningObjectTable(rot) rot.EnumRunning(monikers) Dim moniker = New IMoniker(0) {} While monikers.[Next](1, moniker, IntPtr.Zero) = 0 Dim curMoniker = moniker.First() Dim name As String = Nothing If curMoniker IsNot Nothing Then Try curMoniker.GetDisplayName(context, Nothing, name) Catch ex As UnauthorizedAccessException End Try End If If String.Equals(monikerName, name, StringComparison.CurrentCultureIgnoreCase) Then Dim app As Object = Nothing rot.GetObject(curMoniker, app) Return TryCast(app, ISldWorks) End If End While Finally If monikers IsNot Nothing Then Marshal.ReleaseComObject(monikers) End If If rot IsNot Nothing Then Marshal.ReleaseComObject(rot) End If If context IsNot Nothing Then Marshal.ReleaseComObject(context) End If End Try Return Nothing End Function End Module
In the above example new session of SOLIDWORKS is launched by starting new process from SOLIDWORKS application installation path. StartSwApp function requires the full path to sldworks.exe as first parameter and optional timeout in seconds as second parameter. Timeout will ensure that the application won't be locked in case process failed to start.
You can also make this call asynchronous and display some progress indication in your application while SOLIDWORKS process is starting:
Private Async Function StartSwAppAsync(ByVal appPath As String, _ ByVal Optional timeoutSec As Integer = 10) _ As System.Threading.Tasks.Task(Of SolidWorks.Interop.sldworks.ISldWorks) Return Await System.Threading.Tasks.Task.Run(Function() StartSwApp(appPath, timeoutSec)) End Function