2012-03-24 5 views
3

Ich habe vor kurzem eine C# -App geschrieben, die auf einigen PCs nicht ausgeführt wurde. Das Problem war, dass ich eine Methode verwendete, die nur in der SP1-Version des .NET-Frameworks 3.5 hinzugefügt wurde. Exception is occuring only on my machine: Method not found: WaitHandle.WaitOne(Int32)Gibt es ein Tool zum Überprüfen der .NET Framework Version?

Meine Frage:

Wenn die Methode aufgerufen wurde, würde ich eine MethodNotFound Ausnahme, wie in diesem Problem umgehen Gibt es ein Tool, das meinen Code untersuchen, und mir die Mindestversion sagen (statisch?) des .NET Framework, das ich brauche (einschließlich Service Packs)?

Scheint wie es wäre praktisch, obwohl ich nicht sicher bin, wie häufig das ist.

+6

Microsoft vermasselte, dass sie Methoden zu Mscorlib-Klassen hinzugefügt, aber die [AssemblyVersion] nicht geändert haben. Sie haben diese Lektion gelernt und spezifische Gegenmaßnahmen gegen diesen Fehler in .NET 4 ergriffen. Sie können wirklich nichts tun, außer sicherzustellen, dass die richtige Version von .NET bereitgestellt wird. Bei einem Setup-Projekt, wenn Sie Ihre Voraussetzungen nicht gut genug kommunizieren können. Einfach zu erledigen. –

+0

Ich denke, ein anderes Szenario, in dem mir das passiert, ist, dass ich Code schreibe, aber ich merke nicht, dass ich Methoden verwende, die nicht funktionieren, wenn ich den Code auf eine andere Plattform (XBOX oder WP7) übertragen möchte. Ich verwende Methoden und Klassen, die nicht portierbar sind - aber zumindest warnt mich der Compiler davor. –

Antwort

0

Ich kenne keine Tools, um die Mindestversion des Frameworks zu identifizieren, mit dem der Code arbeiten muss. Sie können jedoch selbst festlegen, welche Version des Frameworks Ihre Anwendung benötigt oder unterstützt, indem Sie die Konfigurationseinstellungen requiredRuntime und supportedRuntime verwenden.

Beim Laden der Anwendung löst die CLR dann einen Fehler aus und informiert den Benutzer, wenn die installierten Versionen nicht ausreichen, um den Code auszuführen.

+1

Der Punkt ist, dass in diesem Fall der Kern geändert wurde, aber die Version nicht. Siehe auch Hans Passants Kommentar. – Abel

1

Alles, was hier geschrieben wurde, ist natürlich korrekt, aber die ursprüngliche Frage wurde noch nicht beantwortet. Theoretisch könnten Sie ein solches Werkzeug selbst schreiben, indem Sie den Code durchlaufen und sehen, ob Sie einen Verweis auf eine Methode finden, die zuerst in diesem SP1 existierte. Hier ist ein grobes Beispiel, die Cecil verwendet die Baugruppe zu analysieren:

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); 
    } 
    } 
} 

Offensichtlich ist dieses Beispiel nimmt nur, dass ein Verfahren in Betracht, aber es sollte möglich sein, auf sie zu erweitern, wenn Sie wirklich brauchen. :)

+0

Zu beachten: Mono * gibt 'IEnumerable' hier frei, so dass Sie LINQ-Abfragen gegen die Bits in der Binärdatei verwenden können :) –

+0

@BillyONeal Definitiv! Ich habe einfach keine richtige IDE auf diesem PC und hatte nicht das Gefühl, in der falschen Reihenfolge LINQ falsch zu schreiben. ;) – hangy

+0

Dargestellt. Ich möchte immer auf mein Lieblingsfeature von Cecil hinweisen: P –

Verwandte Themen