测试篇 关于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控制台工程: [受加载]

AssemblyDependent类在链式加载

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到控制台:

img

img

问题分析

出现了 obj\Debug占用!!

我们这下知道了几个信息:

  1. 问题与cad无关.
  2. 问题与winform和wpf无关.
  3. 问题net standard和net frameworl无关
  4. [链式加载]
    Assembly.ReflectionOnlyLoad(File.ReadAllBytes(dll)); 映射区加载并不导致问题;
    Assembly.Load(File.ReadAllBytes(dll)); 导致问题的只有内存区加载;
  5. 占用obj\Debug而不是bin\Debug...
  6. 重复编译四次[被加载]会通过编译..(说明了vs内部有机制释放
  7. 如果写了一个编译后事件,将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();

(完)

posted @ 2020-11-25 00:25  惊惊  阅读(608)  评论(0编辑  收藏  举报