原理:制作一个dll工具,此dll工具可动态加载调试代码所生成的dll。
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using Autodesk.AutoCAD.ApplicationServices.Core;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using LoadaDotNet;
namespace load
{public class Class1{private bool ev = false;[CommandMethod("netloadx")]public void Netloadx()//输入netloadx可动态加载程序的二进制文件{//IL_0017: Unknown result type (might be due to invalid IL or missing references)//IL_001d: Expected O, but got Unknown//IL_0036: Unknown result type (might be due to invalid IL or missing references)//IL_003c: Invalid comparison between Unknown and I4Editor editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;string text = "山水qq443440204";OpenFileDialog val = new OpenFileDialog();((FileDialog)val).Filter = "dll文件(*.dll)|*.dll";((FileDialog)val).Title = "打开dll文件";if ((int)((CommonDialog)val).ShowDialog() != 1){return;}text = ((FileDialog)val).FileName;AssemblyDependent assemblyDependent = new AssemblyDependent(text);bool flag = true;AssemblyDependent.LoadDllMessage[] array = assemblyDependent.Load().ToArray();foreach (AssemblyDependent.LoadDllMessage loadDllMessage in array){if (!loadDllMessage.LoadYes){editor.WriteMessage("\n" + loadDllMessage.Path + "失败!");flag = false;}}if (flag){editor.WriteMessage("\n加载成功!\n");}}[CommandMethod("ww")]public void ww()//输入ww可自动加载目录下的ifoxdemo{var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;var db = doc.Database;var ed = doc.Editor;var ad = new AssemblyDependent(@"G:\Csharp\Ifox\IfoxDemo\IfoxDemo\bin\Debug\net48\IfoxDemo.dll"); //写上你dll的路径var msg = ad.Load();bool allyes = true;foreach (var item in msg){if (!item.LoadYes){ed.WriteMessage("\n**" + item.Path + "**重复版本号,无需再次加载!" + System.Environment.NewLine);allyes = false;}}if (allyes){ed.WriteMessage("\n加载成功!\n");}if (!ev) { System.AppDomain.CurrentDomain.AssemblyResolve += RunTimeCurrentDomain.DefaultAssemblyResolve; ev = true; }}[CommandMethod("www")]public void www()//输入www自动加载路径下的demo.dll{var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;var db = doc.Database;var ed = doc.Editor;var ad = new AssemblyDependent(@"G:\Csharp\Demo\Demo\bin\Debug\Demo.dll"); //写上你dll的路径var msg= ad.Load();bool allyes = true;foreach (var item in msg){if (!item.LoadYes){ed.WriteMessage("\n**" + item.Path +"**重复版本号,无需再次加载!" + System.Environment.NewLine);allyes = false;}}if (allyes){ed.WriteMessage( "\n加载成功!\n");}if (!ev) { System.AppDomain.CurrentDomain.AssemblyResolve += RunTimeCurrentDomain.DefaultAssemblyResolve; ev = true; }}[CommandMethod("sxcx")]public void 属性查询()//输入sxcs可查询实体属性{List<Entity> ents = SelectEntities<Entity>();if (ents is null || ents.Count == 0){Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("未选择!\n");return;}object obj = ents[0];string str = "";str += "对象全部属性: \n";str += "类型: " + obj.GetType() + "\n";PropertyInfo[] pis = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);foreach (var pi in pis){try { str += pi.Name + " : " + pi.GetValue(obj, null).ToString() + "\n"; }catch { str += pi.Name + " " + "Null" + "\n"; }}str += "\n";//MessageBox.Show(str);TextForm f = new TextForm();f.richTextBox1.Text = str;Autodesk.AutoCAD.ApplicationServices.Application.ShowModalDialog(f);}public List<T> SelectEntities<T>() where T : Entity{List<T> result = new List<T>();Editor editor = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.Editor;var pso = new PromptSelectionOptions();pso.MessageForAdding = "\n请选择:";PromptSelectionResult psr = editor.GetSelection(pso);if (psr.Status == PromptStatus.OK){ObjectId[] objectids = psr.Value.GetObjectIds();Database database = HostApplicationServices.WorkingDatabase;using (Transaction tran = database.TransactionManager.StartTransaction()){foreach (var item in objectids){Entity entity = item.GetObject(OpenMode.ForRead) as Entity;if (entity is T){result.Add(entity as T);}}}}return result;}}
}
第二个:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;namespace load
{[Serializable]public class AssemblyDependent : IDisposable{string _dllFile;/// <summary>/// cad程序域依赖_内存区(不可以卸载)/// </summary>private Assembly[] _cadAs;/// <summary>/// cad程序域依赖_映射区(不可以卸载)/// </summary>private Assembly[] _cadAsRef;/// <summary>/// 加载DLL成功后获取到的程序集/// </summary>public List<Assembly> MyLoadAssemblys { get; private set; }/// <summary>/// 当前域加载事件,运行时出错的话,就靠这个事件来解决/// </summary>public event ResolveEventHandler CurrentDomainAssemblyResolveEvent{add{AppDomain.CurrentDomain.AssemblyResolve += value;}remove{AppDomain.CurrentDomain.AssemblyResolve -= value;}}/// <summary>/// 链式加载dll依赖/// </summary>/// <param name="dllFile"></param>public AssemblyDependent(string dllFile){_dllFile = Path.GetFullPath(dllFile);//相对路径要先转换 Path.GetFullPath(dllFile);//cad程序集的依赖_cadAs = AppDomain.CurrentDomain.GetAssemblies();//映射区_cadAsRef = AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies();//被加载的都存放在这里MyLoadAssemblys = new List<Assembly>();}/// <summary>/// 返回的类型,描述加载的错误/// </summary>public class LoadDllMessage{public string Path;public bool LoadYes;public LoadDllMessage(string path, bool loadYes){Path = path;LoadYes = loadYes;}public override string ToString(){if (LoadYes){return "加载成功:" + Path;}return "加载失败:" + Path;}}/// <summary>/// 加载信息集合/// </summary>List<LoadDllMessage> LoadYesList;bool _byteLoad;/// <summary>/// 加载程序集/// </summary>/// <param name="byteLoad">true字节加载,false文件加载</param>/// <returns>返回加载链的</returns>public List<LoadDllMessage> Load(bool byteLoad = true){_byteLoad = byteLoad;if (!File.Exists(_dllFile)){throw new ArgumentNullException("路径不存在");}LoadYesList = new List<LoadDllMessage>();//查询加载链之后再逆向加载,确保前面不丢失var allRefs = GetAllRefPaths(_dllFile);allRefs.Reverse();foreach (var path in allRefs){try{//路径转程序集名string assName = AssemblyName.GetAssemblyName(path).FullName;//路径转程序集名var assembly = _cadAs.FirstOrDefault(a => a.FullName == assName);if (assembly != null){LoadYesList.Add(new LoadDllMessage(path, false));//版本号没变不加载continue;}byte[] buffer = null;bool flag = true;//实现字节加载if (path == _dllFile){LoadOK = true;}
#if DEBUG//为了实现Debug时候出现断点,见链接,加依赖// https://www.cnblogs.com/DasonKwok/p/10510218.html// https://www.cnblogs.com/DasonKwok/p/10523279.htmlvar dir = Path.GetDirectoryName(path);var pdbName = Path.GetFileNameWithoutExtension(path) + ".pdb";var pdbFullName = Path.Combine(dir, pdbName);if (File.Exists(pdbFullName) && _byteLoad){var pdbbuffer = File.ReadAllBytes(pdbFullName);buffer = File.ReadAllBytes(path);var ass = Assembly.Load(buffer, pdbbuffer);MyLoadAssemblys.Add(ass);flag = false;}
#endifif (flag){Assembly ass = null;if (_byteLoad){buffer = File.ReadAllBytes(path);ass = Assembly.Load(buffer);}else{ass = Assembly.LoadFile(path);}MyLoadAssemblys.Add(ass);}LoadYesList.Add(new LoadDllMessage(path, true));//加载成功}catch{LoadYesList.Add(new LoadDllMessage(path, false));//错误造成}}MyLoadAssemblys.Reverse();return LoadYesList;}//链条后面的不再理会,因为相同的dll引用辨识无意义/// <summary>/// 第一个dll加载是否成功/// </summary>public bool LoadOK { get; private set; }/// <summary>/// 加载出错信息/// </summary>public string LoadErrorMessage{get{var sb = new StringBuilder();bool allyes = true;foreach (var item in LoadYesList){if (!item.LoadYes){sb.Append(Environment.NewLine + "** 此文件已加载过,重复名称,重复版本号,本次不加载!");sb.Append(Environment.NewLine + item.ToString());sb.Append(Environment.NewLine);allyes = false;}}if (allyes){sb.Append(Environment.NewLine + "** 链式加载成功!");sb.Append(Environment.NewLine);}return sb.ToString();}}/// <summary>/// 获取加载链/// </summary>/// <param name="dll"></param>/// <param name="dlls"></param>/// <returns></returns>List<string> GetAllRefPaths(string dll, List<string> dlls = null){if (dlls == null){dlls = new List<string>();}if (dlls.Contains(dll) || !File.Exists(dll)){return dlls;}dlls.Add(dll);//路径转程序集名string assName = AssemblyName.GetAssemblyName(dll).FullName;//在当前程序域的assemblyAs内存区和assemblyAsRef映射区找这个程序集名Assembly assemblyAs = _cadAs.FirstOrDefault(a => a.FullName == assName);Assembly assemblyAsRef;//内存区有表示加载过//映射区有表示查找过但没有加载(一般来说不存在.只是debug会注释掉Assembly.Load的时候用来测试)if (assemblyAs != null){assemblyAsRef = assemblyAs;}else{assemblyAsRef = _cadAsRef.FirstOrDefault(a => a.FullName == assName);//内存区和映射区都没有的话就把dll加载到映射区,用来找依赖表if (assemblyAsRef == null){// assemblyAsRef = Assembly.ReflectionOnlyLoad(dll); 没有依赖会直接报错var byteRef = File.ReadAllBytes(dll);assemblyAsRef = Assembly.ReflectionOnlyLoad(byteRef);}}//遍历依赖,如果存在dll拖拉加载目录就加入dlls集合foreach (var assemblyName in assemblyAsRef.GetReferencedAssemblies()){//dll拖拉加载路径-搜索路径(可以增加到这个dll下面的所有文件夹?)string directoryName = Path.GetDirectoryName(dll);var path = directoryName + "\\" + assemblyName.Name;var paths = new string[]{path + ".dll",path + ".exe"};foreach (var patha in paths){GetAllRefPaths(patha, dlls);}}return dlls;}/// <summary>/// 递归删除文件夹目录及文件/// </summary>/// <param name="dir"></param>/// <returns></returns>static void DeleteFolder(string dir){if (Directory.Exists(dir)) //如果存在这个文件夹删除之{foreach (string d in Directory.GetFileSystemEntries(dir)){if (File.Exists(d))File.Delete(d); //直接删除其中的文件elseDeleteFolder(d); //递归删除子文件夹}Directory.Delete(dir, true); //删除已空文件夹}}/// <summary>/// Debug的时候删除obj目录,防止占用/// </summary>public void DebugDelObjFiles(){try{var filename = Path.GetFileNameWithoutExtension(_dllFile);var path = Path.GetDirectoryName(_dllFile);var pdb = path + "\\" + filename + ".pdb";if (File.Exists(pdb)){File.Delete(pdb);}var list = path.Split('\\');if (list[list.Length - 1] == "Debug" && list[list.Length - 2] == "bin"){var bin = path.LastIndexOf("bin");var proj = path.Substring(0, bin);var obj = proj + "obj";DeleteFolder(obj);}}catch{ }}#region Disposepublic bool Disposed = false;/// <summary>/// 显式调用Dispose方法,继承IDisposable/// </summary>public void Dispose(){//由手动释放Dispose(true);//通知垃圾回收机制不再调用终结器(析构器)_跑了这里就不会跑析构函数了GC.SuppressFinalize(this);}/// <summary>/// 析构函数,以备忘记了显式调用Dispose方法/// </summary>~AssemblyDependent(){//由系统释放Dispose(false);}/// <summary>/// 释放/// </summary>/// <param name="ing"></param>protected virtual void Dispose(bool ing){if (Disposed){//不重复释放return;}//让类型知道自己已经被释放Disposed = true;GC.Collect();}#endregion}
}
第三个:
using System;
using System.Linq;
using System.Reflection;namespace load
{public static class RunTimeCurrentDomain{#region 程序域运行事件 // 动态编译要注意所有的引用外的dll的加载顺序// cad2008若没有这个事件,会使动态命令执行时候无法引用当前的程序集函数// 跨程序集反射// 动态加载时,dll的地址会在系统的动态目录里,而它所处的程序集(运行域)是在动态目录里.// netload会把所处的运行域给改到cad自己的,而动态编译不通过netload,所以要自己去改.// 这相当于是dll注入的意思,只是动态编译的这个"dll"不存在实体,只是一段内存./// <summary>/// 程序域运行事件/// </summary> public static Assembly DefaultAssemblyResolve(object sender, ResolveEventArgs args){var cad = AppDomain.CurrentDomain.GetAssemblies();/*获取名称和版本号都一致的,调用它*/Assembly load = null;load = cad.FirstOrDefault(a => a.GetName().FullName == args.Name);if (load == null){/*获取名称一致,但是版本号不同的,调用最后的可用版本*/var ag = args.Name.Split(',')[0];//获取 最后一个符合条件的,//否则a.dll引用b.dll函数的时候,b.dll修改重生成之后,加载进去会调用第一个版本的b.dll foreach (var item in cad){if (item.GetName().FullName.Split(',')[0] == ag){//为什么加载的程序版本号最后要是*//因为vs会帮你迭代这个版本号,所以最后的可用就是循环到最后的.load = item;}}}return load;}#endregion}
}
第四个sxcx:
namespace LoadaDotNet
{partial class TextForm{/// <summary>/// Required designer variable./// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// Clean up any resources being used./// </summary>/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows Form Designer generated code/// <summary>/// Required method for Designer support - do not modify/// the contents of this method with the code editor./// </summary>private void InitializeComponent(){this.richTextBox1 = new System.Windows.Forms.RichTextBox();this.SuspendLayout();// // richTextBox1// this.richTextBox1.Location = new System.Drawing.Point(11, 11);this.richTextBox1.Margin = new System.Windows.Forms.Padding(2);this.richTextBox1.Name = "richTextBox1";this.richTextBox1.Size = new System.Drawing.Size(455, 947);this.richTextBox1.TabIndex = 0;this.richTextBox1.Text = "";// // TextForm// this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(477, 969);this.Controls.Add(this.richTextBox1);this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));this.Margin = new System.Windows.Forms.Padding(2);this.Name = "TextForm";this.Text = "属性查询 (山水443440204)";this.TransparencyKey = System.Drawing.Color.White;this.ResumeLayout(false);}#endregionpublic System.Windows.Forms.RichTextBox richTextBox1;}
}
(咨询收费)联系↓↓↓