测试篇 关于vs的obj的Debug目录占用
起因
我在这篇文 cad.net dll动态加载 上面提及了一个事情,在vs调试cad的时候如果这个时候使用 Assembly.Load(byte) 那么会出现obj\Debug占用而不是bin\Debug占用,这是为什么呢?
查阅了下面的类似的问题,发现都不太对的样子.....
https://blog.csdn.net/guangod/article/details/88799393
https://bbs.csdn.net/topics/390744522?utm_medium=distribute.pc_relevant_t0.none-task-discussion_topic-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-discussion_topic-BlogCommendFromBaidu-1.control
https://www.cnblogs.com/ifendou/p/9088265.html
测试文件
测试文件下载 这份文件的代码和本文不同,属于旧代码,可以和本文的解决方案对比看看.
受加载
然后我新建了一个net framework控制台工程: [受加载]
using RemoteAccess;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ConsoleApp1
{
class Program
{
[STAThread]
static void Main(string[] args)
{
while (true)
{
Console.WriteLine("输入路径:--------------------------------------------------");
var path = Console.ReadLine();
if (path != null)
{
var ad = new AssemblyDependent(path);
// ad.DebugDelObjFiles();这句是关键....它将实现删除占用
ad.Load();
Console.WriteLine("调用内部方法:--------------------------------------------------");
foreach (var item in ad.MyLoadAssemblys)
{
Invoke(item, "ClassLibrary1.Class1", "Princ");
}
Console.WriteLine("反馈:--------------------------------------------------");
if (ad.LoadOK)
{
Console.WriteLine(Environment.NewLine + "**链式加载成功!" + Environment.NewLine);
}
else
{
Console.WriteLine(ad.LoadErrorMessage);
}
}
}
}
/// <summary>
/// 调用载入的dll的方法
/// </summary>
/// <param name="assembly">程序集</param>
/// <param name="spaceClass">命名空间+类名</param>
/// <param name="methodName">方法名</param>
/// <param name="args">方法需要的参数</param>
/// <returns></returns>
public static object Invoke(Assembly assembly, string spaceClass, string methodName, params object[] args)
{
if (assembly == null)
throw new ArgumentNullException("没程序域");
Type spaceClassType = assembly.GetType(spaceClass);
if (spaceClassType == null)
throw new ArgumentNullException("命名空间.类型出错");
// 转大写匹配命令(如果是方法的话,这里可能有重载)
List<MethodInfo> methodInfos = new List<MethodInfo>();
foreach (var item in spaceClassType.GetMethods())
{
if (item.Name.ToUpper() == methodName.ToUpper())
{
methodInfos.Add(item);
}
}
if (methodInfos.Count == 0)
throw new ArgumentNullException("方法出错");
object spaceClassInstance = Activator.CreateInstance(spaceClassType);
object returnValue = null;
foreach (var methodInfo in methodInfos)
{
try
{
// 此句若出错表示运行域不在准确的域内,要去检查一下,此句也会导致GC释放出错
returnValue = methodInfo.Invoke(spaceClassInstance, args);
}
catch
{ }
}
return returnValue;
}
}
}
被加载
然后加载了一个小型的dll工程:[被加载]
代码没有什么意义...只是为了生成一个dll
using System;
namespace ClassLibrary1
{
public class Class1
{
public void Princ()
{
Console.WriteLine(Environment.NewLine + "a a a a a a a a a a a a a a " + Environment.NewLine);
}
}
}
操作
然后拖拉dll到控制台:
问题分析
出现了 obj\Debug占用!!
我们这下知道了几个信息:
- 问题与cad无关.
- 问题与winform和wpf无关.
- 问题net standard和net frameworl无关
- [链式加载]的
Assembly.ReflectionOnlyLoad(File.ReadAllBytes(dll)); 映射区加载并不导致问题;
Assembly.Load(File.ReadAllBytes(dll)); 导致问题的只有内存区加载; - 占用obj\Debug而不是bin\Debug...
- 重复编译四次[被加载]会通过编译..(说明了vs内部有机制释放
- 如果写了一个编译后事件,将bin\Debug的dll复制到H盘目录下:
copy $(TargetPath) "H:\"
然后拖拉H盘下的这个dll,再去编译一次.你会惊讶地发现:
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 CS2012 无法打开“D:\桌面\被加载\ClassLibrary1\obj\Debug\ClassLibrary1.pdb”进行写入 --“文件“D:\桌面\被加载\ClassLibrary1\obj\Debug\ClassLibrary1.pdb”正由另一进程使用,因此该进程无法访问此文件。” ClassLibrary1 D:\桌面\被加载\ClassLibrary1\CSC 1 活动
怎么也占用了呢?明明加载的都跨盘了......而且这个时候只需要再编译一次,就能通过...刚刚是四次....
说明vs会检索现有所有打开的vs程序下的工程??
查询了点资料,根据这里进行修改.csproj什么用都没有...
<BaseIntermediateOutputPath>myLibrary\obj\Debug</BaseIntermediateOutputPath>
解决方法
1.如之前的文章所知:最后的解决方法是非vs调试打开软件.
2.所以我决定在AssemblyDependent.Load前删除项目的某些文件,防止vs占用.它的实现方式,我重新修改了这个类,见 AssemblyDependent类在链式加载
其实不用删除也行,把他们移动到临时目录,加载之后再移动回来,当做什么都没发生.
var ad = new AssemblyDependent(path);
ad.DebugDelObjFiles(); //这句是关键....它将实现删除占用
ad.Load();
(完)