2008-10-09 8 views
20

Eine kleine Funktion eines großen Programms untersucht Baugruppen in einem Ordner und ersetzt veraltete Baugruppen durch die neuesten Versionen. Zu diesem Zweck muss es die Versionsnummern der vorhandenen Assemblydateien lesen, ohne diese Assemblys tatsächlich in den ausführenden Prozess zu laden.Wie bekomme ich die Version einer Assembly, ohne sie zu laden?

+0

In welcher Sprache codierst du? –

+0

@RB: Sprache spielt keine Rolle, weil man die gleichen Klassen verwenden würde, um die Informationen zu erhalten. –

+0

Sie müssen Jop's oder Joels Antwort die richtige Antwort geben. Ich würde sie bis zu einer Million stimmen, wenn ich könnte. Ich wollte schon seit Jahren wissen, wie das geht. – MusiGenesis

Antwort

32

Ich fand folgende in this article.

using System.Reflection; 
using System.IO; 

... 

// Get current and updated assemblies 
AssemblyName currentAssemblyName = AssemblyName.GetAssemblyName(currentAssemblyPath); 
AssemblyName updatedAssemblyName = AssemblyName.GetAssemblyName(updatedAssemblyPath); 

// Compare both versions 
if (updatedAssemblyName.Version.CompareTo(currentAssemblyName.Version) <= 0) 
{ 
    // There's nothing to update 
    return; 
} 

// Update older version 
File.Copy(updatedAssemblyPath, currentAssemblyPath, true); 
+0

Mist. Wie immer für mich funktioniert dies nicht auf dem Compact Framework. AssemblyName ist vorhanden, AssemblyName.GetAssemblyName jedoch nicht. – MusiGenesis

+0

Ein älterer Trick, den ich verwendet habe (zum Durchsuchen von Plug-in-Assemblys), war, eine Sandbox-AppDomain zu erstellen, sie dort zu laden und dann die AppDomain zu schließen, wenn ich fertig war. Nicht sicher über CF. –

+0

Haben Sie ein Codebeispiel für den Sandbox-Ansatz? – MusiGenesis

9

Verwenden Sie AssemblyName.GetAssemblyName("assembly.dll");, dann analysieren Sie den Namen. Nach MSDN:

Dies nur, wenn die Datei Manifest enthält eine Baugruppe arbeiten. Diese Methode bewirkt, dass die Datei geöffnet und geschlossen wird, aber die Assembly ist nicht dieser Domäne hinzugefügt.

+0

Ich versuche nicht an all die Hacks zu denken, die ich implementiert habe, um eine Versionsnummer zu bekommen, ohne die Datei zu laden. Ja, – MusiGenesis

11

Abhängig von den Dateien, könnte eine Option FileVersionInfo sein - das heißt

FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(path) 
string ver = fvi.FileVersion; 

Das Problem ist, dass diese auf dem Code hängt das [AssemblyFileVersion] Attribut, und es das [AssemblyVersion] Attribut entspricht.

Ich denke, ich würde zuerst die AssemblyName-Optionen betrachten, die von anderen vorgeschlagen werden.

+1

Ein Vergleich der FileVersionInfo könnte ebenfalls nützlich sein. Ein Update für eine Bibliothek, das Fehler behebt, aber die API nicht ändert, könnte die gleiche Assembly-Version haben, sollte aber eine andere Dateiversion haben. In vielen Fällen kann die AssemblyFileVersion die zu überprüfende sein. –

+0

Tipp: Die Verwendung von FileVersionInfo befindet sich im System.Diagnostics-Namespace, den Sie importieren müssten. –

+0

@eithe, um fair zu sein, können Sie nur Strg + drücken. (mit dem Schwerpunkt auf einem unaufgelösten Typ) und die IDE wird es finden und für Sie hinzufügen ...dann müssen Sie sich Namespaces nicht merken –

0

Nur für den Rekord: So erhalten Sie die Dateiversion in C# .NET Compact Framework. Es ist im Grunde von OpenNETCF, aber sehr viel kürzer und exakter, so dass es kopiert werden kann. Hoffe, dass es helfen wird ...

public static Version GetFileVersionCe(string fileName) 
{ 
    int handle = 0; 
    int length = GetFileVersionInfoSize(fileName, ref handle); 
    Version v = null; 
    if (length > 0) 
    { 
     IntPtr buffer = System.Runtime.InteropServices.Marshal.AllocHGlobal(length); 
     if (GetFileVersionInfo(fileName, handle, length, buffer)) 
     { 
      IntPtr fixedbuffer = IntPtr.Zero; 
      int fixedlen = 0; 
      if (VerQueryValue(buffer, "\\", ref fixedbuffer, ref fixedlen)) 
      { 
       byte[] fixedversioninfo = new byte[fixedlen]; 
       System.Runtime.InteropServices.Marshal.Copy(fixedbuffer, fixedversioninfo, 0, fixedlen); 
       v = new Version(
        BitConverter.ToInt16(fixedversioninfo, 10), 
        BitConverter.ToInt16(fixedversioninfo, 8), 
        BitConverter.ToInt16(fixedversioninfo, 14), 
        BitConverter.ToInt16(fixedversioninfo, 12)); 
      } 
     } 
     Marshal.FreeHGlobal(buffer); 
    } 
    return v; 
} 

[DllImport("coredll", EntryPoint = "GetFileVersionInfo", SetLastError = true)] 
private static extern bool GetFileVersionInfo(string filename, int handle, int len, IntPtr buffer); 
[DllImport("coredll", EntryPoint = "GetFileVersionInfoSize", SetLastError = true)] 
private static extern int GetFileVersionInfoSize(string filename, ref int handle); 
[DllImport("coredll", EntryPoint = "VerQueryValue", SetLastError = true)] 
private static extern bool VerQueryValue(IntPtr buffer, string subblock, ref IntPtr blockbuffer, ref int len); 
Verwandte Themen