在本教程中,我将演示如何使用 VB.NET 和Microsoft Visual Studio从进程外(也称为独立)应用程序(例如Windows Forms,Windows Console)连接到SOLIDWORKS应用程序。
有关本文中讨论的方法的更详细说明,请阅读《如何使用SOLIDWORKS API创建独立(exe)应用程序》一文。
创建新项目
我将使用Microsoft Visual Studio开发环境。您可以使用任何版本的 Visual Studio。相同的代码适用于专业版、精简版或社区版。
在Visual Studio中创建新的 VB.NET 项目
选择 VB.NET 控制台应用程序项目模板
向项目添加程序集引用
对于面向 Framework 4.0 的项目,我建议将“嵌入互操作类型”选项设置为 false。否则,由于类型转换问题,在调用 SOLIDWORKS API 时,应用程序可能会出现不可预测的行为。
嵌入互操作程序集的选项
现在我们可以添加代码以连接到 SOLIDWORKS 实例。
创建或连接到SOLIDWORKS实例
连接到 COM 服务器的最常见和最快速的方法可能是使用CreateObject方法(https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.interaction.createobject)。替代方法是:Activator::CreateInstance(https://learn.microsoft.com/zh-cn/dotnet/api/system.activator.createinstance)和 GetObject(https://learn.microsoft.com/zh-cn/dotnet/api/microsoft.visualbasic.interaction.getobject)。请注意,如果 GetObject 无法连接到活动会话,它将创建新实例。
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
我建议使用 Activator::CreateInstance,因为这允许通过 2 个步骤连接到会话:
这种方法将在发生错误时提供更好的故障排除选项:如果第一步失败,则意味着 COM 类未注册或无法从注册表访问;否则,这可能表示存在某些权限问题。请阅读《如何使用SOLIDWORKS API创建独立(exe)应用程序》一文,了解此方法的限制说明。
或者,您可以使用 Marshal::GetActiveObject方法(https://learn.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.marshal.getactiveobject)连接到SOLIDWORKS的活动(已启动)会话。与调用 GetObject 不同,此方法将确保不会创建新的 SOLIDWORKS 实例,并且如果没有要连接的正在运行的 SOLIDWORKS 会话,则会引发异常。
Const PROG_ID As String = "SldWorks.Application"
Dim app = TryCast(System.Runtime.InteropServices.Marshal.GetActiveObject(PROG_ID),
SolidWorks.Interop.sldworks.ISldWorks)
通过 ROT 获取正在运行的实例
为了连接到已经运行的特定 SOLIDWORKS 会话或能够创建多个会话,您可以使用正在运行的对象表 API。请阅读《如何使用SOLIDWORKS API创建独立(exe)应用程序》一文,了解有关此方法的更多详细信息。
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
在上面的示例中,通过从SOLIDWORKS应用程序安装路径启动新进程来启动SOLIDWORKS的新会话。StartSwApp 函数需要 sldworks.exe的完整路径作为第一个参数,可选的timeout(超时,以秒为单位)作为第二个参数。超时将确保在进程无法启动的情况下应用程序不会被锁定。
您还可以使用异步调用,以便在SOLIDWORKS启动时在应用程序中显示一些进度指示:
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
文章翻译自https://www.codestack.net/
仅供学习使用。