Mam plik wykonywalny i chciałbym wiedzieć, które wersje platformy .NET należy uruchomić.
Czy istnieje łatwy sposób na znalezienie gdzieś tych informacji?
Odpowiedzi:
Myślę, że najbliższym możliwym niezawodnym rozwiązaniem jest określenie, która wersja CLR jest wymagana. Można to zrobić, używając ILDASM i patrząc na węzeł „MANIFEST” lub reflektor i patrząc na widok demontażu węzła „Application.exe” jako IL. W obu przypadkach jest komentarz wskazujący na wersję CLR. W ILDASM komentarz to „// Wersja metadanych”, a w Reflektorze komentarz to „Docelowa wersja środowiska wykonawczego”.
Oto przykłady aplikacji .NET WinForms o nazwie WindowsFormsApplication1.exe:
ILDASM:
// Metadata version: v2.0.50727
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
.assembly extern System
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
Reflektor:
.module WindowsFormsApplication1.exe
.subsystem 0x0002
// MVID: {CA3D2090-16C5-4899-953E-4736D6BC0FA8}
// Target Runtime Version: v2.0.50727
Możesz również przejrzeć listę zestawów, do których istnieją odwołania, i poszukać odwołania o najwyższym numerze wersji.
Ponownie, używając ILDASM patrząc na dane węzła „MANIFEST”:
.assembly extern System.Drawing
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 2:0:0:0
}
.assembly extern System.Core
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 3:5:0:0
}
I używając Reflectora, patrząc na dissambly (nadal jako IL) dla każdego wymienionego odniesienia:
.assembly extern System.Core
{
.ver 3:5:0:0
.publickeytoken = (B7 7A 5C 56 19 34 E0 89)
}
Znajdując odwołanie z metadanymi najwyższej wersji, można określić, z której wersji Framework pochodzi, z którego pochodzi, co wskazywałoby, że do uruchomienia aplikacji potrzebna jest ta sama wersja Framework zainstalowana. Biorąc to pod uwagę, nie traktowałbym tego jako w 100% niezawodnego, ale nie sądzę, że wkrótce się to zmieni.
Używając Notatnika , sprzed trzech dekad, rozmiaru 200 KB, preinstalowanego narzędzia:
notepad appname.exe
, F3
aż .NET Framework,version=vX.Y
pojawi sięv2.
... wciąż 100 razy łatwiejsze niż instalowanie gigabajtów narzędzi do analizowania sieci i śmieci.Każdy inny edytor / przeglądarka może otworzyć pliki binarne też, jak Notepad ++ lub wielkim text / hex widza TotalCommander za Lister .
Bardziej uproszczonym podejściem byłoby użycie dotPeek i zobaczenie, co pojawia się w drzewie.
Możesz teraz użyć ILSpy do zbadania struktury docelowej zestawu. Po załadowaniu zestawu kliknij katalog główny węzła zestawu i możesz znaleźć informacje w deklaracji TargetFramework:
[assembly: TargetFramework(".NETFramework,Version=v4.5", FrameworkDisplayName = ".NET Framework 4.5")]
Z kodu, którego możesz użyć, Assembly.ImageRuntimeVersion
ale patrząc na plik prawdopodobnie najlepiej byłoby użyć reflektora i sprawdzić, do której wersji mscorlib
się odwołujesz.
Edycja: jeszcze lepiej byłoby użyć ildasm , otworzyć zestaw, a następnie wyświetlić manifest zestawu. Pierwszy wiersz manifestu zawiera dokładną wersję środowiska CLR, dla którego został zbudowany zestaw.
Możesz użyć narzędzia o nazwie CorFlags.exe. Jest już od .NET 2.0 i wiem na pewno, że jest zawarty w Windows SDK 7.0. Domyślnie (w systemie Windows XP Pro) jest instalowany w C: \ Program Files \ Microsoft SDKs \ Windows \ v7.0A \ bin \ CorFlags.exe. Podaj mu ścieżkę do pliku zarządzanego modułu (bez żadnych innych flag wiersza polecenia), aby wyświetlić jego informacje nagłówkowe, w tym wersję.
Należy pamiętać, że to narzędzie jest przeznaczone do modyfikowania nagłówka PE32 modułu, więc nie używaj żadnej z flag, dopóki dokładnie nie przeczytasz dokumentacji .
Możesz też po prostu dowiedzieć się, jakie odniesienie do System.Core ma. Dzięki temu dowiesz się, z jakiej wersji .NET Framework korzysta ta aplikacja. W przypadku wersji 2.0 wersja System.Core to 2.0.xxx.xxx. W przypadku wersji 3.5 będzie to 3.5.xxx.xxx itd.
Wersję .NET pliku można uzyskać w systemie Windows za pomocą programu PowerShell. Poniższy skrypt;
$path=’.\’
$ErrorActionPreference = "SilentlyContinue"
$files=Get-ChildItem -Path $path -Recurse -include *.dll,*.exe
foreach($file in $files)
{
$filename = $file.BaseName
$version = $([System.Reflection.Assembly]::ReflectionOnlyLoadFrom($file.FullName).GetCustomAttributesData() |
select-object -ExpandProperty ConstructorArguments |
select-object -ExpandProperty Value |
select-string -Pattern '.NET')
Write-Output "$filename,$version"
}
Zauważ, że wynik wyodrębnił wersję .NET dla plików exe w tym folderze, ale zrobi to również dla dll.