如何检测哪个.net语言正在调用我的代码



我正在构建一个库,它生成一个用户代理字符串,报告一些漂亮的数据,如操作系统版本和当前安装的。net框架版本。我很好奇:

是否有可能以编程方式检测哪种语言正在调用我的库?或者一旦编译成CIL,源语言是否完全不透明?

Edit:我把它变成了一个小库,封装了一些启发式方法,使其易于调用。

我想出了一个启发法,似乎很适合我自己的需要。

@Don的回答和这些问题给了我一些提示:
  • 反编译的DLL -线索,以帮助告诉它是否c#或VB.NET?
  • 反编译VB。. Net程序集产生具有无效成员变量名的代码;以$STATIC开头的名称$

警告:

  • 只区分VB。NET和c#,而不是任何其他CLR语言。如果没有足够的VB的证据,假设c#。
  • 这是一个有根据的猜测,所以假阳性的机会是> 0。
  • 一些提示是基于编译器实现的细节,这些细节可能会改变。
  • 这似乎也适用于单声道,但YMMV.
  • 这是一个昂贵的反射,所以在现实生活中,你想把它包装在Lazy<>或其他机制中,以确保它只被调用一次。
  • 正如@HABO提到的,这可能是也可能不是非常有用的信息。我最好奇的是,这是否可以做到。

var lang = DetectAssemblyLanguage(Assembly.GetCallingAssembly());
public static string DetectAssemblyLanguage(Assembly assembly)
{
    var referencedAssemblies = assembly
        .GetReferencedAssemblies()
        .Select(x => x.Name);
    var types = assembly
        .GetTypes();
    // Biggest hint: almost all VB.NET projects have a
    // hidden reference to the Microsoft.VisualBasic assembly
    bool referenceToMSVB = referencedAssemblies.Contains("Microsoft.VisualBasic");
    // VB.NET projects also typically reference the special
    // (YourProject).My.My* types that VB generates
    bool areMyTypesPresent = types.Select(x => x.FullName).Where(x => x.Contains(".My.My")).Any();
    // If a VB.NET project uses any anonymous types,
    // the compiler names them like VB$AnonymousType_0`1
    bool generatedVbNames = types.Select(x => x.Name).Where(x => x.StartsWith("VB$")).Any();
    // If a C# project uses dynamic, it'll have a reference to Microsoft.CSharp
    bool referenceToMSCS = referencedAssemblies.Contains("Microsoft.CSharp");
    // If a C# project uses any anonymous types,
    // the compiler names them like <>f__AnonymousType0`1
    bool generatedCsNames = types.Select(x => x.Name).Where(x => x.StartsWith("<>")).Any();
    var evidenceForVb = new bool[] 
    {
        referenceToMSVB,
        myTypesPresent,
        vbGeneratedNames
    };
    var evidenceForCsharp = new bool[] {
        true, // freebie. ensures ties go to C#
        referenceToMSCS,
        csGeneratedNames
    };
    var scoreForVb = evidenceForVb.Count(x => x)
                     - evidenceForCsharp.Count(x => x);
    // In the case of a tie, C# is assumed
    return scoreForVb > 0
        ? "vb"
        : "cs";
}

不幸的是,这是不可能的,正如您通过提到CIL所确定的那样。

我可以想到两种可能的解决方案:

  1. 如果相应的。net dll(调用代码的汇编)的PDB文件是可用的,那么您可以检查该文件以确定使用的语言。然而,这是一个很大的"如果",我会远离这样的解决方案。
  2. 检查调用程序集引用的程序集。有时(很少)可能会引用特定于语言的程序集。

相关内容

  • 没有找到相关文章

最新更新