当前位置: 首页 > news >正文

CATIA二次开发(2)C#启用AOT

微软为.net引入了AOT技术,这样源代码可以编译为二进制代码,而不是IL代码。IL代码是虚拟机用代码,运行时由虚拟机即时编译(JIT)成二进制,然后再运行,IL代码极容易被逆向;二进制代码是在开发时就编译成二进制,运行时直接二进制代码本地运行,不需要虚拟机在运行时临时再编译一遍。JIT的好处就是跨平台更容易;AOT的好处就是速度更快,而且不容易被逆向。

如果希望软件发布后不要被逆向,那就要选择AOT。

AOT对控制台程序和类库支持挺好,但是对于GUI程序支持都很差,不论是WinForm、WPF、WinUI还是MAUI。而基于CATIA二次开发的软件必然是GUI的,所以AOT的支持是个麻烦。处理方法就是:把GUI程序的界面和功能做剥离,把功能AOT编译成类库,供JIT的GUI界面调用。

Visual Studio解决方案设置

GUI界面和类库的分别设置

Visual Studio创建一个解决方案,类型选WPF应用程序,类别选择.net,别选.net Framework。

取消勾选“将解决方案和项目放在同一个目录中。

解决方案下包含多个项目,这多个项目其中一个时WPF的GUI界面,另外再创建一个C#的类库。新建的时候可以给WPF项目的名称,C#类库等到新建类库项目时再给。

名字和目录设置好后下一步就创建好了。

然后在“解决方案资源管理器”的“解决方案”上点“右键->添加->新建项目”,在对话框中类型选择C#类库,并设定名字和目录。

在“解决方案资源管理器”上左键点击C#类库,在xml编辑界面的<PropertyGroup>节点插入<PublishAot>true</PublishAot>

<PropertyGroup><PublishAot>true</PublishAot>
</PropertyGroup>

在“解决方案资源管理器”上右键点击C#类库,在弹出菜单中选“属性”,可以设置目标平台,比如x64

GUI界面对类库的依赖设置

GUI界面程序必要依赖类库。如果不顾一切,其实可以把C#类库编译发布后,以DllImport或者LibraryImport供GUI界面调用。但既然开发者有类库源代码,那最好还是直接依赖,这样在IDE中有提示和跳转,方便很多。

在“解决方案资源管理器”上的GUI界面项目下的“依赖项”点右键,“添加项目引用”,Visual Studio会自动识别到当前解决方案中的其他项目——C#类库项目,勾选就可以了。将来在开发或者发布的时候Visual Studio会根据解决方案自动识别依赖关系,自动处理编译顺序和打包。

设定COM依赖

在C#类库的“依赖项”点右键,进入COM选单,把CATIA V5的各个COM都勾选上。如果在C#类库对所有需要的CATIA COM函数都做了封装,理论上GUI界面可以完全不用管CATIA COM,但是正常来讲这是不可能的,所以GUI界面也要把CATIA COM的依赖都勾选。

C#类库的编写

编辑C#类库的源码文件

#nullable enable
// 引入CATIA命名空间
using INFITF;
using MECMOD;
using PARTITF;
using ProductStructureTypeLib;
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Text;
using System.Windows;
namespace CATIAConnect
{public class Connect{private INFITF.Application mainInstance;public INFITF.Application CATIAInstance { get { return mainInstance; } }public Connect(){GetOrStartCatia();}public void GetOrStartCatia(bool makeVisible = true){try{// 首先尝试获取已运行的实例object? comInstance = CustomMarshal.GetActiveObject("CATIA.Application");mainInstance = comInstance == null ? throw new COMException() : (INFITF.Application)comInstance;}catch (COMException comExc){// 启动新的CATIA进程实例}}}// https://www.catiawidgets.net/2024/03/10/c-catia-connection/public static partial class CustomMarshal{internal const String OLEAUT32 = "oleaut32.dll";internal const String OLE32 = "ole32.dll";[System.Security.SecurityCritical]  // auto-generated_requiredpublic static object? GetActiveObject(String progID, bool throwOnError = false){object? obj;Guid clsid;int hr;// Call CLSIDFromProgIDEx first then fall back on CLSIDFromProgID if// CLSIDFromProgIDEx doesn't exist.try{hr = CLSIDFromProgIDEx(progID, out clsid, out hr);if (hr != 0) // S_OK in HRESULT{Marshal.ThrowExceptionForHR(hr);}}catch (Exception){hr = CLSIDFromProgID(progID, out clsid, out hr);if (hr != 0) // S_OK in HRESULT{if (throwOnError)Marshal.ThrowExceptionForHR(hr);return null;}}try{hr = GetActiveObject(clsid, IntPtr.Zero, out obj);if (hr != 0) // S_OK in HRESULT{if (throwOnError)Marshal.ThrowExceptionForHR(hr);}}catch (Exception){return null;}return obj;}//https://learn.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.preservesigattribute?view=net-8.0//https://learn.microsoft.com/zh-cn/dotnet/api/system.runtime.interopservices.dllimportattribute?view=net-8.0//[DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]//[DllImport(OLE32, PreserveSig = false)][LibraryImport(OLE32)][ResourceExposure(ResourceScope.None)][SuppressUnmanagedCodeSecurity][System.Security.SecurityCritical]  // auto-generatedprivate static partial int CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid, out int @return);//[DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]//[DllImport(OLE32, PreserveSig = false)][LibraryImport(OLE32)][ResourceExposure(ResourceScope.None)][SuppressUnmanagedCodeSecurity][System.Security.SecurityCritical]  // auto-generatedprivate static partial int CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid, out int @return);//[DllImport(Microsoft.Win32.Win32Native.OLEAUT32, PreserveSig = false)][DllImport(OLEAUT32, PreserveSig = true)][ResourceExposure(ResourceScope.None)][SuppressUnmanagedCodeSecurity][System.Security.SecurityCritical]  // auto-generatedprivate static extern int GetActiveObject([MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, IntPtr pvReserved, [MarshalAs(UnmanagedType.IUnknown)] out object ppunk);}
}

在类库中提供一个属性,并设置为只读(只有get,没有set),以供GUI界面调用。

而且尽可能的把DllImport替换为了LibraryImport,PreserveSig设置为true,尽可能将HRESULT返回,这里的演示代码只是做了简单处理,实际产品开发中可以做更丰富的处理。

GUI界面的编写

编辑GUI界面的源代码

#nullable enable
// 引入CATIA命名空间
using INFITF;
using MECMOD;
using PARTITF;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using CATIAConnect;
using System.Runtime.InteropServices;
using CATPspPlantShipTypeLib;namespace CATIAFrontEnd
{/// <summary>/// Interaction logic for MainWindow.xaml/// </summary>public partial class MainWindow : System.Windows.Window{private CATIAConnect.Connect? connect;public MainWindow(){InitializeComponent();try{connect = new CATIAConnect.Connect();}catch (COMException){connect = null;}}private void MyButtonClick(object sender, RoutedEventArgs e){MECMOD.PartDocument ActivePartDocument = (MECMOD.PartDocument)connect.CATIAInstance.ActiveDocument;MECMOD.Part ActivePart = ActivePartDocument.Part;myButton.Content = ActivePart.get_Name();}}
}

连接到CATIA后,通过属性获取CATIA进程实例,然后针对这个实例进行各种操作。

http://www.dtcms.com/a/426778.html

相关文章:

  • Linux 驱动开发与内核通信机制——超详细教程
  • 【langgraph】本地部署方法及实例分析
  • Linux入门指南:从零掌握基础指令
  • 做笔记的网站源码江永网站建设
  • 是时候重启了:AIGC将如何重构UI设计师的学习路径与知识体系?
  • uniapp 请求接口封装和使用
  • AIGC重构数据可视化:你是进化中的“驯兽师”还是被替代的“画图工”?
  • Apache Doris 内部数据裁剪与过滤机制的实现原理
  • 专业做网站流程小程序开发步骤大全
  • C语言基础之指针2
  • 淘客网站怎么做 知乎wordpress淘宝联盟插件
  • flink工作流程
  • openHarmony之storage_daemon:分区挂载与设备节点管理机制讲解
  • 建站怎么赚钱个人官方网站怎么建设
  • 学习笔记093——Windows系统如何定时备份远程服务器的mysql文件到本地?
  • 操作系统内核架构深度解析:从单内核、微内核到鸿蒙分布式设计
  • MySQL 架构全景解析
  • .NET MVC中实现后台商品列表功能
  • oracle logwr,ckpt,dbwn 如何协同工作的
  • C# 网络通讯核心知识点笔记
  • Ubuntu之apt安装ClickHouse数据库
  • 在线音乐网站开发现状网站全屏弹出窗口
  • 泛型在Java集合框架中的应用有哪些?
  • 服务器中使用Docker部署前端项目
  • mysql之二进制日志
  • 【完整源码+数据集+部署教程】染色体图像分割系统: yolov8-seg-KernelWarehouse
  • Docker MySQL 使用全流程
  • Visual Studio主题、字体、快捷键、开发环境设置,自用
  • 火山 19 混音伴音 接口
  • Bean精细化控制属性序列化反序列化