• 轮子和做轮子


    前言:上午无事,离午饭还有1小时的时间,弄篇文章。

    近日,被分配到一个工作,就是给之前一个同事写的tool加个UI,并且增加一些新的功能。之前的形式是一个功能的lib,一个前台的console。。从我陆续开始动手开始,UI设计我也就替代了,但是之前这位仁兄写的tool已经严重阻碍了我的新功能的开发,而且还有bug,近日已经遇到了2个。

    简单说一下这个tool的功能:就是dump生成文件里的resource,大家都知道resource是PE里最复杂的功能,其格式内容有字符串,图片,音视频,XML等。当然,我们的这个tool目前只有dump string的功能,能dump native和managed PE的resource。一次只能dump一个PE file。

    native的string功能实现,用的是win32 API,然后P/Invoke,略过不提。

    managed PE,用的是BCL里的ResoureManger class,其之前的功能已经实现,也确实能dump出resource string。

    下面我来详细说一下期间我遇到的bug:

    1 一个assembly从不同的location load进同一个appdomain,你会遇到一个exception:

    Unhandled Exception: System.IO.FileLoadException: API restriction: The assembly
    'file:///D:\dll\new\main\FSharp.Core - Copy (2) - Copy - Copy - Copy.dll' has al
    ready loaded from a different location. It cannot be loaded from a new location
    within the same appdomain.

    这个exception 是怎么产生的呢?

    因为你要dump assembly 的resource吧,那么就要将assembly load到当前的appdomain里吧,这样你的ResourceManager才能分析其中的内容。但是如果同一个assembly,从不同的location load,文件名可以相同也可以不同,因为其判断唯一性不是根据其文件名,而是根据其metadata里的信息。

    那么这个时候该怎么办呢?

    两个办法:

    1. 阻止同一个assembly load twice 到同一个appdomain
    2. 创建一个新的appdomain来load 相同的assembly

    我一开始走的第2个方案,其sample code也是可行的,但是由于一下原因考虑,放弃了:

    1. 创建新的appdomain之后,牵扯到跨appdomain通信的问题,代码复杂度增加
    2. 如果频繁创建appdomain,效率不高
    3. 如果在新的appdomain里load assembly,再回到default appdomain,我需要预先load此assembly的dependency的assembly,这样的话就需要分析assembly的metadata。复杂度剧增

    那么我就开始转回到第一个方案,那么我怎么能确定assembly的唯一性呢,文件名是不可行的,我想到了两个方案:

    1. 分析PE的metadata
    2. 用checksum

    我用了第二个方案,用了MD5的hash,来保证唯一性,简单易行,但是可能会耽误一些时间,尤其在大文件的loading的时候,会比较耗时。不过目前因为resource file超过10M的都很小,所以也是权宜之计。


    第2个bug:

    在这个tool dump完之后,会以log的形式输出结果。但是当你在dump完之后再次按下dump按钮,就会抛出:

    XXX文件被XXX进程占用

    这个bug我目前还没怎么分析,估计应该不太难,或者很难。我猜应该是某个file handle没有正确的close吧。唉,我爱擦屁股。


    其实这些问题,都是太依赖微软工具的结果,用了某一个Class,从而导致之后的功能根本无法扩展,因为其核心功能是用的BCL的某一个class,某一个API。

    关于这个tool,我想如果想通用一劳永逸的话,不如抛开API,直接去metadata里找resource。


    微软造就了dev,也弱化了dev。


    啰里吧唆半天,吃饭去

  • 相关阅读:
    SDNU 1123.Encoding
    SDNU 1120.ISBN号码
    SDNU 1119.Intelligent IME(水题)
    SDNU 1115.谁拿了最多奖学金(水题)
    解决Docker运行命令时提示"Got permission denied while trying to connect to the Docker daemon socket"类情况
    jupyter notebook修改默认浏览器
    CentOS切换用户命令su or su+username
    图像内插,双线性插值等
    python求最大公约数和最小公倍数
    Python split()方法
  • 原文地址:https://www.cnblogs.com/diggingdeeply/p/2278949.html
Copyright © 2020-2023  润新知