跳到主要内容

从独立应用程序或宏调用SOLIDWORKS插件对象的函数

本文介绍如何通过使用SOLIDWORKS API检索插件对象来从独立应用程序或宏调用SOLIDWORKS插件的函数。

这基于与此视频教程中显示的启用COM通信的相同技术,以便从VBA宏中重用.NET函数:

{% youtube { id: lTEONui2H0s } %}

在插件中启用API

要在插件中启用API,需要遵循几个规则:

  • 插件必须实现COM可见接口,该接口公开COM可见函数。
  • 这些函数的所有参数和返回值也必须是COM可见的。
  • 插件必须生成带有这些API函数定义的类型库(TLB)。

在开发C#应用程序时,需要创建COM可见接口并在插件中实现它。

[ComVisible(true)]
public interface IMyAddInApi
{
void FooApiMethod();
}

[ComVisible(true), Guid("799A191E-A4CF-4622-9E77-EA1A9EF07621")]
public class MyAddIn : ISwAddIn
{
...
public void FooApiMethod()
{
//Implement
}
}

如果在Visual Studio中选择了“注册COM互操作”选项,则会自动将所有COM可见的函数、类和接口添加到tlb文件中。

为插件生成的类型库{ width=550 }

具有API的示例插件

以下插件示例是使用SwEx.AddIn Framework构建的,但是相同的技术也适用于使用不同方法构建的插件。

该插件在“工具”菜单下添加了一个菜单命令,允许创建圆柱体特征。

插件菜单{ width=350 }

当从菜单中调用时,圆柱体将具有硬编码的参数值。

从插件菜单创建的圆柱体几何特征{ width=350 }

同时,插件公开了名为CreateCylinder的公共API,允许创建圆柱体。API有两个参数:

  • 直径
  • 高度

并返回指向IFeature的指针。由于SOLIDWORKS API是COM可见的,插件可以直接在通信中使用此接口。

CreateCylinder函数本身由插件的Create Cylinder命令使用。

C#插件源代码

using CodeStack.SwEx.AddIn;
using CodeStack.SwEx.AddIn.Attributes;
using CodeStack.SwEx.AddIn.Enums;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace CodeStack.Examples.CreateGeometryAddIn
{
[SwEx.Common.Attributes.Title("Create Geometry")]
public enum Commans_e
{
[CommandItemInfo(swWorkspaceTypes_e.Part)]
[SwEx.Common.Attributes.Title("Create Cylinder")]
CreateCylinder
}

[ComVisible(true)]
public interface IGeometryAddIn
{
IFeature CreateCylinder(double diam, double height);
}

[AutoRegister("CreateGeometryAddIn", "Sample add-in for creating geometry", true)]
[ComVisible(true), Guid("799A191E-A4CF-4622-9E77-EA1A9EF07621")]
[ProgId("CodeStack.GeometryAddIn")]
public class AddIn : SwAddInEx, IGeometryAddIn
{
public override bool OnConnect()
{
this.AddCommandGroup<Commans_e>(OnButtonClick);

return true;
}

private void OnButtonClick(Commans_e cmd)
{
try
{
switch (cmd)
{
case Commans_e.CreateCylinder:
CreateCylinder(0.1, 0.1);
break;
}
}
catch(Exception ex)
{
Trace.WriteLine(ex.Message);
App.SendMsgToUser2("Failed to create geometry",
(int)swMessageBoxIcon_e.swMbStop, (int)swMessageBoxBtn_e.swMbOk);
}
}

public IFeature CreateCylinder(double diam, double height)
{
var part = App.ActiveDoc as IPartDoc;

if (part == null)
{
throw new NotSupportedException("Only part document are supported");
}

var modeler = App.IGetModeler();

var body = modeler.CreateBodyFromCyl(new double[]
{
0, 0, 0,
0, 1, 0,
diam / 2, height
});

if (body != null)
{
var feat = part.CreateFeatureFromBody3(body, false,
(int)swCreateFeatureBodyOpts_e.swCreateFeatureBodySimplify) as IFeature;

if (feat != null)
{
return feat;
}
else
{
throw new NullReferenceException("Failed to create feature from body");
}
}
else
{
throw new NullReferenceException("Failed to create body. Make sure that the parameters are valid");
}
}
}
}

访问插件

要访问插件及其API,需要检索指向插件接口的指针。可以使用SOLIDWORKS API函数ISldWorks::GetAddInObject通过程序ID(ProgID)或全局唯一标识符(GUID)获取插件的指针。

下面的代码片段通过其GUID从插件中检索指针。这是通过在插件类上使用Guid属性分配的值:

Set swGeomAddIn = swApp.GetAddInObject("{799A191E-A4CF-4622-9E77-EA1A9EF07621}")

或者可以通过其ProgId检索插件。如果未显式指定ProgId,则它等于Namespace.ClassName

Set swGeomAddIn = swApp.GetAddInObject("CodeStack.Examples.CreateGeometryAddIn.AddIn")

建议通过ProgId属性显式指定ProgId。在这种情况下,可以在重构时更改类和命名空间而保持ProgId不变。

[ComVisible(true), Guid("799A191E-A4CF-4622-9E77-EA1A9EF07621")]
[ProgId("CodeStack.MyAddIn")]
public class AddIn : ISwAddIn
{
}

从宏调用插件API

  • 创建新的VBA宏
  • 在VBA编辑器的“工具->引用”菜单中添加对插件类型库的引用

将插件类型库添加到宏{ width=450 }

请注意,该接口将在对象浏览器中可见:

插件API函数在对象浏览器中可见{ width=350 }

VBA宏调用插件函数

Dim swApp As SldWorks.SldWorks

Sub main()

Set swApp = Application.SldWorks

Dim swGeomAddIn As CreateGeometryAddIn.IGeometryAddIn

Set swGeomAddIn = swApp.GetAddInObject("CodeStack.GeometryAddIn")

Dim swFeat As SldWorks.Feature
Set swFeat = swGeomAddIn.CreateCylinder(0.2, 0.5)
swFeat.Name = "MyCylinder"

End Sub

此宏将使用自定义参数创建圆柱体,并使用返回的特征指针对其进行重命名。

从宏创建的圆柱体几何特征{ width=350 }

请注意,插件错误在宏中正确抛出。例如,当提供无效输入时,将生成以下异常:

在宏中抛出的带有描述的异常{ width=500 }

从独立应用程序调用插件

与VBA宏类似,还可以从独立应用程序中自动化插件。为了实现类型安全,需要添加对插件dll的引用。请注意,如果插件是.NET插件,则无法将.tlb文件添加为引用,而是需要添加实际的插件dll。

VB.NET独立应用程序

Imports CodeStack.Examples.CreateGeometryAddIn
Imports SolidWorks.Interop.sldworks

Module Module

Sub Main()

Dim app As ISldWorks = GetObject("", "SldWorks.Application")
Dim geomAddIn As IGeometryAddIn = app.GetAddInObject("CodeStack.GeometryAddIn")
Dim feat As IFeature = geomAddIn.CreateCylinder(0.2, 0.2)
feat.Name = "MyCylinder"

End Sub

End Module

C#独立应用程序

using CodeStack.Examples.CreateGeometryAddIn;
using SolidWorks.Interop.sldworks;
using System;

namespace ConsoleAddIn
{
class Program
{
static void Main(string[] args)
{
var app = Activator.CreateInstance(Type.GetTypeFromProgID("SldWorks.Application")) as ISldWorks;
var geomAddIn = app.GetAddInObject("CodeStack.GeometryAddIn") as IGeometryAddIn;
var feat = geomAddIn.CreateCylinder(0.2, 0.2);
feat.Name = "MyCylinder";
}
}
}

异常也可以从独立应用程序中处理

在.NET应用程序中抛出的.NET异常{ width=550 }

连接到SOLIDWORKS实例的上述方法(Activator::CreateInstance或GetObject方法)在某些情况下可能会创建新的不可见SOLIDWORKS实例,而不是连接到现有会话。这些实例将作为后台应用程序创建,不加载任何插件,因此代码将失败。要强制连接到SOLIDWORKS的活动会话,请参阅通过从运行对象表(ROT)查询COM实例进行连接文章。

注意事项

虽然可以避免声明COM可见接口和对象,并使用dynamic从.NET应用程序中检索和调用插件函数,但是出于以下原因,不建议使用此方法:

  • 它不是类型安全的
  • 性能可能会受到显著影响,因为框架需要在内存中查找和查找适当的对象
  • 可能会出现意外行为,因为可能会映射到不正确的对象

GitHub上下载源代码。