轮子和做轮子

前言:上午无事,离午饭还有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。

啰里吧唆半天,吃饭去

你可能感兴趣的:(轮子和做轮子)