从独立应用程序或宏调用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 }
请注意,该接口将在对象浏览器中可见:
{ 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";
}
}
}
异常也可以从独立应用程序中处理
{ width=550 }
连接到SOLIDWORKS实例的上述方法(Activator::CreateInstance或GetObject方法)在某些情况下可能会创建新的不可见SOLIDWORKS实例,而不是连接到现有会话。这些实例将作为后台应用程序创建,不加载任何插件,因此代码将失败。要强制连接到SOLIDWORKS的活动会话,请参阅通过从运行对象表(ROT)查询COM实例进行连接文章。
注意事项
虽然可以避免声明COM可见接口和对象,并使用dynamic从.NET应用程序中检索和调用插件函数,但是出于以下原因,不建议使用此方法:
- 它不是类型安全的
- 性能可能会受到显著影响,因为框架需要在内存中查找和查找适当的对象
- 可能会出现意外行为,因为可能会映射到不正确的对象
在GitHub上下载源代码。