Programmgesteuert die Versionsnummer einer DLL abrufen

151

Ist es möglich, die Versionsnummer programmgesteuert von einer beliebigen .NET-DLL abzurufen?

Wenn ja, wie?

J L.
quelle
10
Ich kann nicht glauben, dass dies vor 6 Minuten gefragt wurde, war gerade dabei, dasselbe zu fragen!
tpower
2
Schauen
JL.

Antworten:

119
Assembly assembly = Assembly.LoadFrom("MyAssembly.dll");
Version ver = assembly.GetName().Version;

Wichtig: Es ist zu beachten, dass dies nicht die beste Antwort auf die ursprüngliche Frage ist. Vergessen Sie nicht, mehr auf dieser Seite zu lesen.

Kris
quelle
28
Dies lädt MyAssembly.dll in die laufende AppDomain ... schlechte Idee.
staafl
12
Ich empfehle Assemblyname.GetAssemblyName, diese Probleme zu vermeiden
staafl
7
Das Laden einer Assembly in die Appdomain ist langsam, irreversibel (Sie können sie nicht entladen, ohne die Domain zu beenden), erfordert Berechtigungen und kann Nebenwirkungen verursachen, z. B. das Ausführen von beforefieldinitTypinitialisierern, und ist in diesem Fall einfach nicht erforderlich. Sind diese Gründe ausreichend?
Staafl
7
@staafl: Ja; nicht nur für mich, sondern auch für alle anderen, die diese Seite in Zukunft lesen.
Kris
6
FileVersionInfo.GetVersionInfo("foo.dll").FileVersionmacht den Job gut und lädt die DLL nicht in die Anwendung.
Jack
181

Dies funktioniert, wenn die DLL .net oder Win32 ist . Reflexionsmethoden funktionieren nur, wenn die DLL .net ist. Wenn Sie Reflection verwenden, müssen Sie außerdem die gesamte DLL in den Speicher laden. Die folgende Methode lädt die Assembly nicht in den Speicher.

// Get the file version.
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(@"C:\MyAssembly.dll");

// Print the file name and version number.
Console.WriteLine("File: " + myFileVersionInfo.FileDescription + '\n' +
                  "Version number: " + myFileVersionInfo.FileVersion);

Von: http://msdn.microsoft.com/en-us/library/system.diagnostics.fileversioninfo.fileversion.aspx

Originalquelle

Ben Anderson
quelle
5
Ich mag das. Warum sollten Sie sich die Mühe machen, die DLL zu laden und dann Reflection verwenden, um die Version zu erhalten, wenn alles, was Sie wirklich tun möchten, dies ist?
aggieNick02
@ben, könntest du den Beitrag bearbeiten? Ich sah, dass ich durch das Hinzufügen einer Abwertung -1 Wiederholung verloren hatte, an die ich mich nicht erinnern kann. Ich kann es nicht ändern, es sei denn, Sie bearbeiten den Beitrag. Prost!
Luke Duddridge
9
Wenn Sie möchten , um sicherzustellen , erhalten Sie die ausführbare Datei / dll momentan tatsächlich im Einsatz: anstelle einer statischen Dateinamen ( @"C:\MyAssembly.dll"oben), können Sie verwenden System.Reflection.Assembly.GetExecutingAssembly().Location(oder wenn eine DLL: Assembly.GetAssembly(typeof(AClassInTheDll)).Location)
Conrad
4
Dies ist der Unterschied zwischen den Attributen AssemblyVersion und AssemblyFileVersion. Die AssemblyFileVersion wird so gestempelt, dass die Windows-API den Wert abrufen kann. Die AssemblyVersion ist Teil des starken Namens und muss nicht unbedingt mit der AssemblyFileVersion identisch sein.
Daughey
51

Zunächst gibt es zwei mögliche "Versionen", die Sie interessieren könnten:

  • Windows-Dateisystem-Dateiversion, anwendbar auf alle ausführbaren Dateien

  • Assembly-Build-Version, die vom Compiler in eine .NET-Assembly eingebettet wird (gilt natürlich nur für .NET-Assembly-DLL- und -Exe-Dateien)

Im ersteren Fall sollten Sie die Antwort von Ben Anderson verwenden. Im letzteren Fall verwenden Sie AssemblyName.GetAssemblyName(@"c:\path\to\file.dll").Versionoder Tataros Antwort, falls die Assembly durch Ihren Code referenziert wird.

Beachten Sie, dass Sie alle Antworten ignorieren können, die .Load()/ .LoadFrom()Methoden verwenden, da diese die Assembly tatsächlich in die aktuelle AppDomain laden - analog zum Fällen eines Baums, um zu sehen, wie alt er ist.

staafl
quelle
32

Hier ist eine gute Möglichkeit, mit ein wenig Reflexion eine Version einer DLL zu erhalten, die eine bestimmte Klasse enthält:

var ver = System.Reflection.Assembly.GetAssembly(typeof(!Class!)).GetName().Version;

Einfach ersetzen! Klasse! mit dem Namen einer Klasse, die in der DLL definiert ist, deren Version Sie erhalten möchten.

Dies ist meine bevorzugte Methode, da ich den Dateipfad nicht ändern muss, wenn ich die DLLs für verschiedene Bereitstellungen verschiebe.

Totero
quelle
3
Beachten Sie, dass dies nur funktioniert, wenn die betreffende Baugruppe von der aktuellen statisch referenziert wird.
staafl
2
Dies ist die beste Antwort, da die DLL nicht unbedingt die Eintragsbaugruppe ist, nicht einmal die Baugruppe, von der aus sie aufgerufen wird
CAD-Typ
1
Unter stackoverflow.com/a/909583/492 finden Sie Informationen zu verschiedenen Versionsinformationen. zBFileVersionInfo
CAD Kerl
22

Um es für die gestartete Assembly zu erhalten (Winform, Konsolen-App usw.)

using System.Reflection;
...
Assembly.GetEntryAssembly().GetName().Version
Agent_9191
quelle
6
GetExecutingAssembly () könnte ebenfalls hilfreich sein.
Bolt Thunder
10

Kris, Ihre Version funktioniert hervorragend, wenn Sie die Assembly aus der eigentlichen DLL-Datei laden müssen (und wenn die DLL vorhanden ist!). Es wird jedoch ein viel unerwünschter Fehler angezeigt, wenn die DLL EINGEBETTET ist (dh keine Datei, sondern eine eingebettete DLL).

Die andere Sache ist, wenn man ein Versionsschema mit so etwas wie " 1.2012.0508.0101 " verwendet, wenn man die Versionszeichenfolge erhält, erhält man tatsächlich " 1.2012.518.101 "; Beachten Sie die fehlenden Nullen .

Hier sind einige zusätzliche Funktionen, um die Version einer DLL (eingebettet oder aus der DLL-Datei) abzurufen:

    public static System.Reflection.Assembly GetAssembly(string pAssemblyName)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if (string.IsNullOrEmpty(pAssemblyName)) { return tMyAssembly; }
        tMyAssembly = GetAssemblyEmbedded(pAssemblyName);
        if (tMyAssembly == null) { GetAssemblyDLL(pAssemblyName); }

        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)


    public static System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if(string.IsNullOrEmpty(pAssemblyDisplayName)) { return tMyAssembly; }
        try //try #a
        {
            tMyAssembly = System.Reflection.Assembly.Load(pAssemblyDisplayName);
        }// try #a
        catch (Exception ex)
        {
            string m = ex.Message;
        }// try #a
        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyEmbedded(string pAssemblyDisplayName)


    public static System.Reflection.Assembly GetAssemblyDLL(string pAssemblyNameDLL)
    {
        System.Reflection.Assembly tMyAssembly = null;

        if (string.IsNullOrEmpty(pAssemblyNameDLL)) { return tMyAssembly; }
        try //try #a
        {
            if (!pAssemblyNameDLL.ToLower().EndsWith(".dll")) { pAssemblyNameDLL += ".dll"; }
            tMyAssembly = System.Reflection.Assembly.LoadFrom(pAssemblyNameDLL);
        }// try #a
        catch (Exception ex)
        {
            string m = ex.Message;
        }// try #a
        return tMyAssembly;
    }//System.Reflection.Assembly GetAssemblyFile(string pAssemblyNameDLL)


    public static string GetVersionStringFromAssembly(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssembly(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)


    public static string GetVersionString(Version pVersion)
    {
        string tVersion = "Unknown";
        if (pVersion == null) { return tVersion; }
        tVersion = GetVersionString(pVersion.ToString());
        return tVersion;
    }//string GetVersionString(Version pVersion)


    public static string GetVersionString(string pVersionString)
    {
        string tVersion = "Unknown";
        string[] aVersion;

        if (string.IsNullOrEmpty(pVersionString)) { return tVersion; }
        aVersion = pVersionString.Split('.');
        if (aVersion.Length > 0) { tVersion = aVersion[0]; }
        if (aVersion.Length > 1) { tVersion += "." + aVersion[1]; }
        if (aVersion.Length > 2) { tVersion += "." + aVersion[2].PadLeft(4, '0'); }
        if (aVersion.Length > 3) { tVersion += "." + aVersion[3].PadLeft(4, '0'); }

        return tVersion;
    }//string GetVersionString(Version pVersion)


    public static string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssemblyEmbedded(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)


    public static string GetVersionStringFromAssemblyDLL(string pAssemblyDisplayName)
    {
        string tVersion = "Unknown";
        System.Reflection.Assembly tMyAssembly = null;

        tMyAssembly = GetAssemblyDLL(pAssemblyDisplayName);
        if (tMyAssembly == null) { return tVersion; }
        tVersion = GetVersionString(tMyAssembly.GetName().Version.ToString());
        return tVersion;
    }//string GetVersionStringFromAssemblyEmbedded(string pAssemblyDisplayName)
MacSpudster
quelle
2
var versionAttrib = new AssemblyName(Assembly.GetExecutingAssembly().FullName);
Unbesiegbar
quelle
2

Die Antwort von @Ben hat sich für mich als nützlich erwiesen. Ich musste jedoch die Produktversion überprüfen, da dies das Hauptinkrement in meiner Software war und der semantischen Versionierung folgte.

myFileVersionInfo.ProductVersion

Diese Methode hat meine Erwartungen erfüllt

Update: Anstatt den DLL-Pfad im Programm explizit zu erwähnen (wie in der Produktionsversion erforderlich), können wir die Produktversion mit Assembly abrufen.

Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo =FileVersionInfo.GetVersionInfo(assembly.Location); 
string ProdVersion= fileVersionInfo.ProductVersion;
Prasan Dutt
quelle
Hinweis: Wenn die Version ein Sternchen für einen automatisch inkrementierten Wert enthält, gibt diese Methode das Sternchen anstelle der tatsächlich generierten Zahl zurück (dh es funktioniert nicht, wenn Sie 1.0. * In Ihre Assembly-Informationen einfügen).
Ronen Ness
Ja! Ich habe mich jedoch für Jeniks Automatisierung für das Versions-Upgrade entschieden, damit die Assembly immer eine perfekte Kombination der DLL-Version hat.
Prasan Dutt
1

Sie können die Methoden System.Reflection.Assembly.Load * () verwenden und dann deren AssemblyInfo abrufen.

Ariel
quelle
0

Während die ursprüngliche Frage möglicherweise nicht spezifisch für einen Webdienst war, finden Sie hier einen vollständigen testWebService, den Sie hinzufügen können, um eine nicht zwischengespeicherte Antwort des Webdienstes sowie die Dateiversion anzuzeigen. Wir verwenden die Dateiversion anstelle der Assemblyversion, da wir eine Version kennen möchten. Mit allen Assemblyversionen 1.0.0.0 kann die Website jedoch problemlos gepatcht werden (Signatur- und Anforderungslink noch aktiv!). Ersetzen Sie @ Class @ durch den Namen des Web-API-Controllers, in den dieser Dienst eingebettet ist. Dies ist gut für ein Go / Nogo in einem Webdienst und eine schnelle Versionsprüfung.

  [Route("api/testWebService")]
  [AllowAnonymous]
  [HttpGet]
  public HttpResponseMessage TestWebService()
  {
      HttpResponseMessage responseMessage = Request.CreateResponse(HttpStatusCode.OK);
      string loc = Assembly.GetAssembly(typeof(@Class@)).Location;
      FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(loc);
      responseMessage.Content = new StringContent($"<h2>The XXXXX web service GET test succeeded.</h2>{DateTime.Now}<br/><br/>File Version: {versionInfo.FileVersion}");
      responseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("text/html");
      Request.RegisterForDispose(responseMessage);
      return responseMessage;
  }

Ich fand es auch notwendig, Folgendes unter web.config unter Konfiguration hinzuzufügen, um es wirklich anonym zu machen

<location path="api/testwebservice">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>
Wray Smallwood
quelle