原理:制作一个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 I4
Editor 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.html
var 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;
}
#endif
if (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); //直接删除其中的文件
else
DeleteFolder(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 Dispose
public 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);
}
#endregion
public System.Windows.Forms.RichTextBox richTextBox1;
}
}
(咨询收费)联系↓↓↓