学习内容:从零开始定制一个SolidWorks插件

		作为了一个职业的二次开发人员,我曾经创建插件"无数"。但从未像今天这篇文章这样,从空项目开始,之前的文章中我有介绍,要么使用SolidWorks API模板,要么使用了第三方框架。但是其实这两种办法其实都太臃肿了,里面包括了太多的一些东西,比如菜单呀,事件,毕竟有时候做个小插件可能都不涉及,不需要那么多功能。
		为了更好的理解,我介绍一下从零开始定制一个插件的几个步骤,这里以VS2022来做演示,后面代码也会开源。

net farmework 版本的选择

	正常来说,Solidworks对.net Framework没有严格的要求,最新的.net 6也是可以创建插件的,只是说sw每个版本自带的.net 版本是不一样的,大家可以查看安装包里面有个PreReqs文件夹,里面可以看到对应的版本。现在win11 和一些win10上面已经默认不带.net2.0 和.net3.5了,所以目前最好的就是.net 4.0,相对来说支持的广泛一些。

打开VS2022,选择创建新项目

492b51a931e203a9d7030ac8b6da5f8b

这里一定是去选择.net Framework的版本,其它的版本是不一样的。

e2f512710585bd6bd2156e806a7c27b7

这里指定框架版本,自己设置新的路径,点击 创建。

成功之后如下图:

24e533204b122fd0adeeb4923bfbb929

dll的引用

要做SolidWorks的插件,肯定要引用官方提供的dll文件,文件在sw安装目录下面,如果不记得在哪,可以看下快捷方式的属性。

或者用电脑上的Everything软件搜索Sldworks.exe,看我这电脑上有2个版本,就能看出来两个路径。

2f2071b367fb8ee71dc63cac2296ccb8

至于引用哪一个版本的,好像不是太重要,因为高版本基本上向下兼容,在不调用高版本api的情况下,用低版本也可以。

我们就随便找个版本吧,进入到安装目录下\API\redist

6e49d631a111f37f27e94a64eae5d7c8

这里面dll比较多,但常用的是:

e0a2fcdc714122fce06987642fcc62ad

当然还有个,上层目录下也有这几个dll

8755e963172b306973503608e7e64c1a

我们先打开项目的目录:

7a289931a5ecb895c5bc9ad0281257f3

我在这里新建一个文件夹ReferenceDLL

f6fd5c9afa91d2dd3626c2d5ceb87197

然后把关键的dll复制进来

258d0b949e0dec96a9f7e507147cc1d6

5c64af9d6440c1bad7ccec4d1cf463f4

然后浏览到上面我们创建的文件夹,引用这4个dll

073a724f4a6c3b7877155139d30e8489

然后设置一下dll的互操作类型:

6017a2f133a90770b70067037db867f3

64位的设置

现在大部分电脑已经是64位了,如果需要生成的dll是64位的,可以这样修改:

22b90c332b497e3d9b1b5e336ecedbca

在弹出的界面中选择:

78804c160d96747918e6cc404bb51ee7

COM的显示

19354b6de112d8574f5e632f332a4945

此处要勾上。(当前也可以在类里面用属性显示定义COM可见。)

ISwAddin接口

首先重命名以前的Class1为你想要的名称,我这里改为AddinStudy.然后双击选中AddinStudy这个类,前方会出现重命名文件为xxxx.cs.
我们点一下,这样这个文件名也会变更了。

c5fa9e5d07366bcf0c6bd468f7ee42b3

所以当前状态为:

5fe1852e254cbf267c6f158cf1ff34c2

然后,我们让这个类继承接口类ISwAddin ,前让VS自动引用对应的命名空间。

f0c2ebdb48dbeaa297f3ce2cc8d8c33a

然后继续让VS自动实现接口:

6c7e63987af58c2d2dbbdb7751c6ce5e

此时代码就是:

 public class AddinStudy:ISwAddin
    {
        public bool ConnectToSW(object ThisSW, int Cookie)
        {
            throw new NotImplementedException();
        }

        public bool DisconnectFromSW()
        {
            throw new NotImplementedException();
        }
    }

现在里面执行都是抛异常的,所以我们来改一下。

fe39d2ce69d254a4b785a602cc475260

然后,我们要给我们的插件加上名称的描述,不然Solidworks怎么知道插件的名称呢。

就是显示在插件管理界面里的信息。

5e51da35d46165e30f17948f799c16ca

这里我们就要引用 using SolidWorksTools;

然后再加上属性:

[SwAddin(

Description = “SolidWorksAddinStudy description”,

Title = “SolidWorksAddinStudy”,

LoadAtStartup = true

)]

当前完整代码:

using SolidWorks.Interop.swpublished;
using SolidWorksTools;
using System.Windows.Forms;

namespace SolidWorksAddinStudy
{
    [SwAddin(
    Description = "SolidWorksAddinStudy description",
    Title = "SolidWorksAddinStudy",
    LoadAtStartup = true
    )]
    public class AddinStudy : ISwAddin
    {
        private ISldWorks iSwApp = null;

        public ISldWorks SwApp
        {
            get { return iSwApp; }
        }

        public AddinStudy()
        {
            
        }
        public bool ConnectToSW(object ThisSW, int Cookie)
        {
            iSwApp = (ISldWorks)ThisSW;

            iSwApp.SendMsgToUser("SolidWorks正在加载此插件...");

            return true;
        }

        public bool DisconnectFromSW()
        {
            return true;
        }
    }
}

DLL注册

接下来就是要写注册表事件了,当注册dll的时候需要写一信息到注册表里面方便solidworks在下一次开启的时候可以读到插件信息。
下面的代码直接是从api帮助中拿出来的。
        #region SolidWorks Registration

        [ComRegisterFunctionAttribute]
        public static void RegisterFunction(Type t)
        {
            #region Get Custom Attribute: SwAddinAttribute

            SwAddinAttribute SWattr = null;
            Type type = typeof(**AddinStudy**);

            foreach (System.Attribute attr in type.GetCustomAttributes(false))
            {
                if (attr is SwAddinAttribute)
                {
                    SWattr = attr as SwAddinAttribute;
                    break;
                }
            }

            #endregion Get Custom Attribute: SwAddinAttribute

            try
            {
                Microsoft.Win32.RegistryKey hklm = Microsoft.Win32.Registry.LocalMachine;
                Microsoft.Win32.RegistryKey hkcu = Microsoft.Win32.Registry.CurrentUser;

                string keyname = "SOFTWARE\\SolidWorks\\Addins\\{" + t.GUID.ToString() + "}";
                Microsoft.Win32.RegistryKey addinkey = hklm.CreateSubKey(keyname);
                addinkey.SetValue(null, 0);

                addinkey.SetValue("Description", SWattr.Description);
                addinkey.SetValue("Title", SWattr.Title);

                keyname = "Software\\SolidWorks\\AddInsStartup\\{" + t.GUID.ToString() + "}";
                addinkey = hkcu.CreateSubKey(keyname);
                addinkey.SetValue(null, Convert.ToInt32(SWattr.LoadAtStartup), Microsoft.Win32.RegistryValueKind.DWord);
            }
            catch (System.NullReferenceException nl)
            {
                Console.WriteLine("There was a problem registering this dll: SWattr is null. \n\"" + nl.Message + "\"");
                System.Windows.Forms.MessageBox.Show("There was a problem registering this dll: SWattr is null.\n\"" + nl.Message + "\"");
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);

                System.Windows.Forms.MessageBox.Show("There was a problem registering the function: \n\"" + e.Message + "\"");
            }
        }

        [ComUnregisterFunctionAttribute]
        public static void UnregisterFunction(Type t)
        {
            try
            {
                Microsoft.Win32.RegistryKey hklm = Microsoft.Win32.Registry.LocalMachine;
                Microsoft.Win32.RegistryKey hkcu = Microsoft.Win32.Registry.CurrentUser;

                string keyname = "SOFTWARE\\SolidWorks\\Addins\\{" + t.GUID.ToString() + "}";
                hklm.DeleteSubKey(keyname);

                keyname = "Software\\SolidWorks\\AddInsStartup\\{" + t.GUID.ToString() + "}";
                hkcu.DeleteSubKey(keyname);
            }
            catch (System.NullReferenceException nl)
            {
                Console.WriteLine("There was a problem unregistering this dll: " + nl.Message);
                System.Windows.Forms.MessageBox.Show("There was a problem unregistering this dll: \n\"" + nl.Message + "\"");
            }
            catch (System.Exception e)
            {
                Console.WriteLine("There was a problem unregistering this dll: " + e.Message);
                System.Windows.Forms.MessageBox.Show("There was a problem unregistering this dll: \n\"" + e.Message + "\"");
            }
        }

        #endregion SolidWorks Registration


在这里,我们需要对此插件类设置Com可见,并设置一个Guid(可通过VS上面的菜单工具创建GUID来弄个新的。)

288b0300ec69cfcb29a7bf06d649f8a9

此时,点击生成/或者重新生成,检查 是否可以生成dll.

d8ed5a2a9e98d87e0a2d8f4c1fe1ac59

3c8f24f422b355fa614ed06dc1fb9ea5

提示成功。

上一步我们完成了最简单的插件,我们要看一下如果注册,.net的dll都是要注册才能使用,所以这就是为什么插件会让你先注册一下,或者用安装包安装。

注册的话我们要用到regasm.exe这个文件。

大家可以Everything搜索一下,注意看,我们要用到的是64位的,v4.0的,所以我们复制这个exe到 生成的Debug目录下:

90c9e5ad5703b91731145d3b5e4b9b51

fc131cbb32155324fc3eb38906fbf437

然后在这目录下新建两个bat文件,一个用于安装,一个用于卸载。(注意下面的dll 要和你生成的dll名称一样)

set path=%~d0
cd %path%
cd /d %~dp0

RegAsm.exe SolidWorksAddinStudy.dll /codebase
pause


set path=%~d0
cd %path%
cd /d %~dp0

RegAsm.exe SolidWorksAddinStudy.dll /u
pause

所以,当前Debug目录下就有像这样:

a4c032a1578c36d3da775388dcca4dae

选中安装.bat 右击 --以管理员运行

8ab7cee55fe15e36c28df87215ff9e2b

检查里面是否是提示注册成功。

5280001923320dab770d76c9697c52cf

此时打开solidworks,没有意外的话会出现提示对话框

f158641c1017aff2c7d1449facecb26e

然后SolidWorks里面就可以看到插件了。

17435b59378f2b1085cd5410bab0910a

调试

先设置调试exe路径:

0685ef1a08275fda81735d9c73877a05

然后再这里打个断点:

3b63625925f15ee6b7764e864e602fc9

然后直接启动,就会在Solidworks加载此dll的时候进来,这时候就可以进行调试状态了,但是这样调试的时候Solidworks里面的显示是不能动的,也无法操作。所以常用的方案是另外封装一个dll,在Exe里面进行调试,最后插件直接调用公用的dll来执行任务。

Git仓库

https://gitee.com/painezeng/SolidWorksAddinStudy

这样一个最简单的插件已经可以加载了,下篇文章再看一下怎么加载菜单吧