Programowo pobierz numer wersji biblioteki DLL


151

Czy możliwe jest programowe uzyskanie numeru wersji z dowolnej biblioteki DLL .NET?

Jeśli tak, w jaki sposób?


10
Nie mogę uwierzyć, że zostało to zadane 6 minut temu, właśnie o to samo!
tpower

2
sprawdź też ten link do wersji z automatycznym zwiększaniem - blog.mbcharbonneau.com/2007/03/13/ ...
JL.

Odpowiedzi:


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

Ważne: należy zauważyć, że nie jest to najlepsza odpowiedź na pierwotne pytanie. Nie zapomnij przeczytać więcej na tej stronie.


28
Spowoduje to załadowanie MyAssembly.dll do działającej domeny AppDomain ... zły pomysł.
staafl

12
Polecam Assemblyname.GetAssemblyNameunikać tych problemów
staafl

7
ładowanie zestawu do domeny aplikacji jest powolne, nieodwracalne (nie można go zwolnić bez zabijania domeny), wymaga uprawnień i może powodować efekty uboczne, takie jak wykonywanie beforefieldinitinicjatorów typu, i po prostu nie jest wymagane w tym przypadku. Czy te powody są wystarczające?
staafl

7
@staafl: Tak; nie tylko dla mnie, ale także dla wszystkich innych, którzy będą czytali tę stronę w przyszłości.
Kris,

6
FileVersionInfo.GetVersionInfo("foo.dll").FileVersiondobrze wykonuje swoją pracę i nie ładuje biblioteki DLL do aplikacji.
Jack

181

Działa to, jeśli dll to .net lub Win32 . Metody odbicia działają tylko wtedy, gdy dll to .net. Ponadto, jeśli używasz odbicia, masz narzut ładowania całej biblioteki dll do pamięci. Poniższa metoda nie ładuje zestawu do pamięci.

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

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

Pierwotnym źródłem


5
Lubię to. Dlaczego miałbyś zawracać sobie głowę ładowaniem biblioteki dll, a następnie używać odbicia tylko po to, aby pobrać wersję, skoro tak naprawdę chcesz tylko zrobić to ???
aggieNick02,

@ben, czy możesz edytować post? Widziałem, że straciłem -1 rep. Od dodania głosu przeciw, którego nie pamiętam. nie pozwolę mi go zmienić, chyba że edytujesz post. Twoje zdrowie!
Luke Duddridge

9
Jeśli chcesz, aby upewnić się dostać wykonywalny / dll rzeczywiście obecnie w użyciu: zamiast nazwy pliku statycznego ( @"C:\MyAssembly.dll"powyżej), można użyć System.Reflection.Assembly.GetExecutingAssembly().Location(czy dll: Assembly.GetAssembly(typeof(AClassInTheDll)).Location)
Conrad

4
Jest to różnica między atrybutami AssemblyVersion i AssemblyFileVersion. AssemblyFileVersion jest stemplowana w taki sposób, jak interfejs API systemu Windows może pobrać wartość. AssemblyVersion jest częścią silnej nazwy i niekoniecznie jest tym samym, co AssemblyFileVersion.
daughey

51

Przede wszystkim istnieją dwie możliwe `` wersje '', które mogą Cię zainteresować:

  • Wersja systemu plików Windows, mająca zastosowanie do wszystkich plików wykonywalnych

  • Wersja kompilacji zestawu, która jest osadzana w zestawie .NET przez kompilator (oczywiście dotyczy tylko plików DLL zestawu .NET i plików exe)

W pierwszym przypadku powinieneś użyć odpowiedzi Bena Andersona; w tym drugim przypadku użyj AssemblyName.GetAssemblyName(@"c:\path\to\file.dll").Versionlub odpowiedz Tataro, na wypadek gdyby twój kod odwoływał się do zestawu.

Zauważ, że możesz zignorować wszystkie odpowiedzi, które używają .Load()/ .LoadFrom()metody, ponieważ w rzeczywistości ładują one zestaw w bieżącej domenie AppDomain - co jest analogiczne do wycinania drzewa, aby zobaczyć, ile ma lat.


32

Oto przyjemny sposób wykorzystania odrobiny refleksji w celu uzyskania wersji biblioteki DLL zawierającej określoną klasę:

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

Wystarczy wymienić! Klasa! z nazwą klasy zdefiniowanej w bibliotece DLL, której wersję chcesz pobrać.

Jest to moja preferowana metoda, ponieważ jeśli przenoszę biblioteki DLL dla różnych wdrożeń, nie muszę zmieniać ścieżki pliku.


3
Należy zauważyć, że działa to tylko wtedy, gdy do danego zestawu odwołuje się statycznie bieżący.
staafl

2
To najlepsza odpowiedź, ponieważ biblioteka DLL niekoniecznie jest zestawem wejściowym, a nawet zestawem, z którego jest wywoływany
CAD bloke

1
Odwiedź stronę stackoverflow.com/a/909583/492, aby uzyskać informacje o różnych typach wersji. np.FileVersionInfo
gość z CAD

22

Aby pobrać go dla uruchomionego zestawu (winform, aplikacja konsoli itp.)

using System.Reflection;
...
Assembly.GetEntryAssembly().GetName().Version

6
Może również pomóc GetExecutingAssembly ().
Bolt Thunder

10

Kris, twoja wersja działa świetnie, gdy trzeba załadować zestaw z rzeczywistego pliku DLL (i jeśli biblioteka DLL tam jest!), Jednak pojawi się dużo niechciany błąd, jeśli biblioteka DLL jest wbudowana (tj. Nie jest plikiem, ale osadzonym DLL).

Inną rzeczą jest to, że jeśli ktoś używa schematu wersjonowania z czymś w rodzaju „ 1.2012.0508.0101 ”, kiedy otrzyma się ciąg wersji, w rzeczywistości otrzyma się „ 1.2012.518.101 ”; zanotuj brakujące zera .

Oto kilka dodatkowych funkcji umożliwiających uzyskanie wersji biblioteki DLL (osadzonej lub z pliku DLL):

    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)


2

Pomocna okazała się dla mnie odpowiedź @Ben. Musiałem jednak sprawdzić wersję produktu, ponieważ była to główna zmiana zachodząca w moim oprogramowaniu, a następnie wersjonowanie semantyczne.

myFileVersionInfo.ProductVersion

Ta metoda spełniła moje oczekiwania

Aktualizacja: Zamiast jawnie wymieniać ścieżkę dll w programie (w razie potrzeby w wersji produkcyjnej), możemy pobrać wersję produktu za pomocą Assembly.

Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo =FileVersionInfo.GetVersionInfo(assembly.Location); 
string ProdVersion= fileVersionInfo.ProductVersion;

Uwaga: jeśli wersja zawiera gwiazdkę dla wartości automatycznie zwiększanej, ta metoda zwróci gwiazdkę zamiast faktycznie wygenerowanej liczby (tj. Nie działa, jeśli umieścisz 1.0. * W informacjach o zespole).
Ronen Ness

Tak! Jednak wybrałem automatyzację Jeniks do aktualizacji wersji, więc montaż zawsze ma idealne połączenie wersji dll.
Prasan Dutt

1

Możesz użyć metod System.Reflection.Assembly.Load * (), a następnie pobrać ich AssemblyInfo.


0

Chociaż pierwotne pytanie mogło nie być specyficzne dla usługi sieciowej, oto kompletna usługa testWebService, którą można dodać, aby wyświetlić odpowiedź niebuforowaną w usłudze sieciowej oraz wersję pliku. Używamy wersji pliku zamiast wersji zestawu, ponieważ chcemy znać wersję, ale przy wszystkich wersjach zestawu 1.0.0.0 witrynę internetową można łatwo załatać (łącze do podpisywania i żądania nadal jest aktywne!). Zastąp @ Class @ nazwą kontrolera internetowego interfejsu API, w którym jest osadzona ta usługa. Jest to dobre rozwiązanie dla go / nogo w usłudze sieciowej oraz szybkie sprawdzenie wersji.

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

Uznałem również, że konieczne jest dodanie następującego pliku do web.config w ramach konfiguracji, aby uczynić go prawdziwie anonimowym

<location path="api/testwebservice">
    <system.web>
        <authorization>
            <allow users="*" />
        </authorization>
    </system.web>
</location>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.