【发布时间】:2011-12-21 16:44:10
【问题描述】:
我正在将 32 位 Web 应用程序迁移到 64 位,但我们的插件加载器代码存在一些问题。
在 32 位版本中,我们扫描 webapps bin 目录中的所有 .net dll,然后使用 Assembly.Load 加载它们以检查我们的插件属性是否存在。
我们使用公共域代码以一种相当漂亮的方式做到了这一点:
/// <summary>
/// Returns true if the file specified is a real CLR type,
/// otherwise false is returned.
/// False is also returned in the case of an exception being caught
/// </summary>
/// <param name="file">A string representing the file to check for
/// CLR validity</param>
/// <returns>True if the file specified is a real CLR type,
/// otherwise false is returned.
/// False is also returned in the case of an exception being
/// caught</returns>
public static bool IsDotNetAssembly(String file)
{
Stream fs = new FileStream(@file, FileMode.Open, FileAccess.Read);
try
{
BinaryReader reader = new BinaryReader(fs);
//PE Header starts @ 0x3C (60). Its a 4 byte header.
fs.Position = 0x3C;
uint peHeader = reader.ReadUInt32();
//Moving to PE Header start location...
fs.Position = peHeader;
uint peHeaderSignature = reader.ReadUInt32();
ushort machine = reader.ReadUInt16();
ushort sections = reader.ReadUInt16();
uint timestamp = reader.ReadUInt32();
uint pSymbolTable = reader.ReadUInt32();
uint noOfSymbol = reader.ReadUInt32();
ushort optionalHeaderSize = reader.ReadUInt16();
ushort characteristics = reader.ReadUInt16();
// PE Optional Headers
// To go directly to the datadictionary, we'll increase the stream's current position to with 96 (0x60).
// 28 bytes for Standard fields
// 68 bytes for NT-specific fields
// 128 bytes DataDictionary
// DataDictionay has 16 directories
// 8 bytes per directory (4 bytes RVA and 4 bytes of Size.)
// 15th directory consist of CLR header! (if its 0, it is not a CLR file )
uint[] dataDictionaryRVA = new uint[16];
uint[] dataDictionarySize = new uint[16];
ushort dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
fs.Position = dataDictionaryStart;
for (int i = 0; i < 15; i++)
{
dataDictionaryRVA[i] = reader.ReadUInt32();
dataDictionarySize[i] = reader.ReadUInt32();
}
if (dataDictionaryRVA[14] == 0)
{
fs.Close();
return false;
}
else
{
fs.Close();
return true;
}
}
catch (Exception)
{
return false;
}
finally
{
fs.Close();
}
}
现在的问题是我们现在必须处理 64 位或独立于平台的 dll,并且偏移量似乎已经改变并且这段代码失败了。有谁知道对上述代码的正确修改,以便为有效的 64 位或平台无关的 dll 返回 true?
【问题讨论】:
-
你真的要使用上面的代码吗?
-
漂亮吗?更像是实现特定的、假设的和必然会让你陷入困境的……哦等等,它已经做到了。 :)
-
Web 应用程序非常庞大 - 在 bin 目录中有超过 100 个 dll。许多 dll 不是我们应用程序的插件,而且许多不是 clr dll,因此使用 Assembly.Load 不是一个好的选择。
标签: c# parsing dll 64-bit portable-executable