抱歉,我早先答应了,但回答迟了。
我的想法涉及使用运行时代码编译器以及反射来动态生成包含所有这些常量的类。
所以我看到的步骤(或伪代码)是:
- 对于每个 .h 文件,读取所有以
#define 开头的行并存储这些行。
- 使用
Microsoft.CSharp.CSharpCodeProvider() 和一个空模板文件,在内存中编译一个DLL,其中包含一个公开public const int ALPHA_REACTOR_CODE = 99641; 样式常量的类。
- 使用
Assembly.GetType(string) 获取生成的类的类型
- 使用反射和采用常量名称的方法来访问值。
如果这是我们的攻击计划,这里有一些可能对您有所帮助的 sn-ps 代码。
1.加载 .h 文件
这是非常基本的文件读取,关键技巧是通过#define 过滤您的行,然后解析为Dictionary<string, int>。
lines.Where(line => line.StartsWith("#define", true, CultureInfo.CurrentCulture))
.Select(line => line.Split(' ').Skip(1))
.ToDictionary(lineParts => lineParts.First(), lineParts => int.Parse(lineParts.Last()));
这将生成一个包含所有定义的字典。您可能需要在.ToDictionary() 之前调用.Distict(),以防有重复定义。
2。生成程序集
这是您使用Microsoft.CSharp.CSharpCodeProvider() 生成内存中程序集的地方。这里的诀窍是有一个“GenerateCode.cs”文件,其中包含一个类的基本结构。这必须设置为 EmbeddedResource,否则它会尝试编译(不起作用)。
using System;
namespace GeneratedCode
{{
public class GeneratedConstants
{{
{0}
}}
}}
您会注意到{0},我们使用它和string.Format 将常量插入文件中。
使用assembly.GetManifestResourceStream() 获取此模板文件的流,使用普通StreamReader 将其读入内存中的一个大字符串。
使用StringBuilder 和基本string.Format() 格式以及值字典生成常量。
StringBuilder builder = new StringBuilder();
foreach (var constant in dict)
{
builder.AppendFormat(CultureInfo.CurrentCulture, "public const int {0} = {1};", constant.Key, constant.Value);
}
然后只需使用 string.Format() 将构建器字符串插入到生成的类字符串中(使用{0})
然后,您只需要使用Microsoft.CSharp.CSharpCodeProvider() 在内存中生成一个程序集。
using (CSharpCodeProvider provider = new CSharpCodeProvider())
{
parameters.ReferencedAssemblies.Add("System.dll");
parameters.ReferencedAssemblies.Add("System.Core.dll");
CompilerResults results = provider.CompileAssemblyFromSource(parameters, sourceCode);
}
3 & 4. 使用反射
现在你有一个程序集,其中包含一个类型,其中定义了你的常量,你可以使用assembly.GetType("GeneratedCode.GeneratedConstants"); 来获取类型,并使用反射来获取常量,一次一个或一起。
查看这篇博客文章,其中介绍了如何使用反射获取 const:http://weblogs.asp.net/whaggard/archive/2003/02/20/2708.aspx
嗯,希望对你有所帮助。这不是一个过于复杂的解决方案,但有一些活动部件。
祝你好运!