2012-03-24 57 views
3

我最近寫了一個C#應用程序,它不能在某些PC上運行。問題是我使用的只是在3.5版本的.NET框架的SP1版本中添加的方法。是否有一個工具來檢查最小的.NET框架版本?

當方法被調用時,我會得到一個MethodNotFound例外,像這樣的問題:Exception is occuring only on my machine: Method not found: WaitHandle.WaitOne(Int32)

我的問題:是否有一個工具,將檢查我的代碼,並告訴我的最低版本(靜態?)我需要的.NET框架(包括服務包)?

似乎它會很方便,雖然我不知道這是多麼普遍。

+6

微軟搞砸了,他們將方法添加到mscorlib類,但沒有改變[AssemblyVersion]。他們在.NET 4中學到了這一課,並針對這個錯誤採取了具體的對策。確實沒有什麼可以做,但要確保部署適當版本的.NET。使用安裝項目,如果你不能足夠好地傳達你的先決條件。容易做到。 – 2012-03-24 23:01:35

+0

我認爲另一種情況發生在我身上的是我編寫的代碼,但是我沒有意識到我使用的方法在我計劃將代碼轉移到另一個平臺(XBOX或WP7)時不起作用。我使用不可移植的方法和類 - 但至少編譯器會爲此提醒我。 – 2012-03-25 02:25:33

回答

0

我不知道有什麼工具可以確定您的代碼需要工作的框架的最低版本。 但是,您可以使用requiredRuntime和supportedRuntime配置設置自行指定它,以聲明應用程序需要或支持哪個版本的框架。

當加載應用程序時,CLR會提出錯誤並通知用戶安裝的版本是否不足以執行您的代碼。

+1

問題是,在這種情況下,核心發生了變化,但版本沒有變化。另見Hans Passant的評論。 – Abel 2012-03-24 23:04:47

1

當然,這裏所寫的所有內容都是正確的,但原始問題尚未得到解答。理論上,您可以通過遍歷代碼來自己編寫這樣的工具,並查看是否找到對此SP1中首先存在的方法的引用。下面是一個使用Cecil解析裝配粗例如:

namespace SampleNamespace 
{ 
    using System; 
    using Mono.Cecil; 
    using Mono.Cecil.Cil; 

    internal static class Program 
    { 
    public static void Main(string[] args) 
    { 
     foreach (string arg in args) 
     { 
     Console.WriteLine("{0}: {1}", arg, NeedsDotNet35SP1(arg)); 
     Console.ReadLine(); 
     } 
    } 

    private static bool NeedsDotNet35SP1(string fileName) 
    { 
     return NeedsDotNet35SP1(ModuleDefinition.ReadModule(fileName)); 
    } 

    private static bool NeedsDotNet35SP1(ModuleDefinition module) 
    { 
     if (TargetRuntime.Net_2_0 != module.Runtime) 
     { 
     // I don't care about .NET 1.0, 1.1. or 4.0 for this example. 
     return false; 
     } 

     foreach (TypeDefinition type in module.Types) 
     { 
     if (NeedsDotNet35SP1(type)) 
     { 
      return true; 
     } 
     } 

     return false; 
    } 

    private static bool NeedsDotNet35SP1(TypeDefinition type) 
    { 
     foreach (MethodDefinition method in type.Methods) 
     { 
     if (NeedsDotNet35SP1(method)) 
     { 
      return true; 
     } 
     } 

     return false; 
    } 

    private static bool NeedsDotNet35SP1(MethodDefinition method) 
    { 
     return NeedsDotNet35SP1(method.Body); 
    } 

    private static bool NeedsDotNet35SP1(MethodBody body) 
    { 
     foreach (Instruction instruction in body.Instructions) 
     { 
     if (NeedsDotNet35SP1(instruction)) 
     { 
      return true; 
     } 
     } 

     return false; 
    } 

    private static bool NeedsDotNet35SP1(Instruction instruction) 
    { 
     if (OperandType.InlineMethod != instruction.OpCode.OperandType) 
     { 
     return false; 
     } 

     return NeedsDotNet35SP1((MethodReference)instruction.Operand); 
    } 

    private static bool NeedsDotNet35SP1(MethodReference method) 
    { 
     return method.FullName.Equals(
     "System.Boolean System.Threading.WaitHandle::WaitOne(System.Int32)", 
     StringComparison.OrdinalIgnoreCase); 
    } 
    } 
} 

顯然,這個例子只需要一個方法考慮進去,但它應該是可以擴大就可以了,如果你真的需要。 :)

+0

值得注意的是:Mono *在這裏暴露了IEnumerable,因此您可以使用LINQ查詢來處理二進制中的位。 – 2012-03-25 00:37:35

+0

@BillyONeal當然!我只是在這臺PC上沒有適當的IDE,並且不想在運行中隨意地寫錯誤的LINQ。 ;) – hangy 2012-03-25 00:51:34

+0

圖。總是喜歡指出我最喜歡的Cecil:P功能 – 2012-03-25 02:33:40

相關問題