Pobierz wersję pliku w programie PowerShell

146

Jak uzyskać informacje o wersji z pliku .dlllub .exew programie PowerShell?

Jestem szczególnie zainteresowany File Version, chociaż inne informacje o wersji (czyli Company, Language, Product Name, itd.) Byłby pomocny.

Cesarz XLII
źródło

Odpowiedzi:

140

Ponieważ PowerShell może wywoływać klasy .NET , możesz wykonać następujące czynności:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo("somefilepath").FileVersion

Lub jak zaznaczono tutaj na liście plików:

get-childitem * -include *.dll,*.exe | foreach-object { "{0}`t{1}" -f $_.Name, [System.Diagnostics.FileVersionInfo]::GetVersionInfo($_).FileVersion }

Lub nawet ładniejszy jako skrypt: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/

Lars Truijens
źródło
8
Zobacz @Jaykul, aby zapoznać się z rozwiązaniem, które nie wymaga obiektu .NET. Odpowiedź IMHO Jaykula powinna zostać wybrana jako odpowiedź :)
Thomas Bratt,
2
Chociaż inne odpowiedzi dają krótsze polecenia, wszystkie z nich, które próbowałem, wypisują za dużo informacji i skracają ścieżkę do pliku do „...”. Drugie polecenie w tej odpowiedzi podaje dokładnie to, czego potrzebujesz, działa dla katalogu plików i formatuje w taki sposób, że łatwo jest zobaczyć, jak je zmodyfikować, aby zwrócić inne informacje. Po prostu zmień .LegalCopyright w poleceniu na .FileVersion.
Dennis
To jest poprawna wersja dla plików .NET EXE. Odpowiedź Jaykula nie ma tej samej wersji.
popioły 999
To właściwie nie w porządku. Przyjrzyj się get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -forcei porównaj FilePrivatePart z ostatnią częścią FileVersion. FileVersion pokazuje, co zostało pierwotnie wysłane, a nie poprawioną wersję. Z drugiej strony to polecenie pokazuje numer poprawionej wersji: (get-command C: \ Windows \ System32 \ ubpm.dll).
Wersja
Lepszym przykładem może być niedawno załatany C: \ Windows \ System32 \ Lsasrv.dll ... ale prawda jest taka, że (Get-Command ... ).Versionzwraca ProductVersion, a nie FileVersion , i czasami ma to znaczenie. Aby uzyskać pełne rozwiązanie, które faktycznie zwraca zaktualizowaną wersję pliku, zapoznaj się z przykładem Update-TypeData w mojej odpowiedzi poniżej.
Jaykul
170

Obecnie możesz pobrać FileVersionInfo z Get-Item lub Get-ChildItem, ale pokaże on oryginalny plik FileVersion z dostarczonego produktu, a nie zaktualizowaną wersję. Na przykład:

(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.FileVersion

Co ciekawe, zaktualizowaną (załataną) wersję ProductVersion można pobrać za pomocą tego:

(Get-Command C:\Windows\System32\Lsasrv.dll).Version

Rozróżnienie, które robię między „oryginalnym” i „załatanym”, wynika zasadniczo ze sposobu obliczania FileVersion ( zobacz dokumentację tutaj ). Zasadniczo od czasu Vista, GetFileVersionInfo API systemu Windows odpytuje część informacji o wersji z pliku neutralnego językowo (exe / dll), a nie naprawioną część z pliku mui specyficznego dla języka (który nie jest aktualizowany za każdym razem, gdy zmieniają się pliki ).

Tak więc w przypadku pliku takiego jak lsasrv (który został zastąpiony z powodu problemów z bezpieczeństwem w SSL / TLS / RDS w listopadzie 2014 r.) Wersje zgłaszane przez te dwie komendy (przynajmniej przez chwilę po tej dacie) były różne, a druga to bardziej „poprawna” wersja.

Jednak chociaż jest to poprawne w LSASrv, możliwe jest, że ProductVersion i FileVersion będą różne (w rzeczywistości jest to powszechne). Tak więc jedynym sposobem uzyskania zaktualizowanej wersji Fileversion bezpośrednio z pliku zespołu jest samodzielne zbudowanie jej z części, coś takiego:

Get-Item C:\Windows\System32\Lsasrv.dll | ft FileName, File*Part

Lub pobierając dane z tego:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName)

Możesz łatwo dodać to do wszystkich obiektów FileInfo, aktualizując TypeData w PowerShell:

Update-TypeData -TypeName System.IO.FileInfo -MemberName FileVersion -MemberType ScriptProperty -Value {
   [System.Diagnostics.FileVersionInfo]::GetVersionInfo($this.FullName) | % {
      [Version](($_.FileMajorPart, $_.FileMinorPart, $_.FileBuildPart, $_.FilePrivatePart)-join".") 
   }
}

Teraz za każdym razem, gdy to zrobisz, Get-ChildItemlub Get-Itembędziesz mieć FileVersionwłaściwość, która pokazuje zaktualizowaną wersję pliku ...

Jaykul
źródło
10
Aby to było odpowiednikiem zaakceptowanej odpowiedzi Larsa, po prostu użyj(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
rand0m1,
1
Jestem zaintrygowany Get-Commandzastosowanym do pliku dll. Czy mógłbyś wyjaśnić jego efekt?
Stephane Rolland
3
Ostrzeżenie FileVersionInfo.FileVersion to ciąg znaków, który może nie być aktualny. Powinieneś spojrzeć na FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart. Zobacz GetFileVersionInfo () zwraca informacje o błędnej wersji pliku
bdeem,
1
@Jaykul Aby wyjaśnić mój wcześniejszy komentarz / pytanie: oryginalna odpowiedź pokazuje, jak uzyskać wersję produktu w PowerShell poprzez kilka interesujących rozwiązań, ponieważ ProductVersion może być bardziej orientacyjna niż FileVersion. Oryginalna odpowiedź nie wspomina o właściwości VersionInfo.ProductVersion, prawdopodobnie dlatego, że odpowiedź jest przed nią. Czy (Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersionnowszy, prostszy sposób na uzyskanie tych samych informacji o ProductVersion, jak opisano w odpowiedzi? Nie ufam firmie Microsoft w ProductVersionkonsekwentnym używaniu tego terminu .
Tydaeus
2
@Tydaeus To nie jest nowe. Możesz sprawdzić to w dokumentach i zobaczyć, jak daleko sięga wstecz (.NET 1.1) 😏. Moja odpowiedź wspomina o ProductVersion, ale wersja, którą obliczamy z całym tym kodem ScriptProperty, jest prawdziwą wersją PLIKU, a nie wersją produktu. Czasami są takie same, ale nie zawsze. 😔 I niestety, każdy przykład ze świata rzeczywistego, który wymyślam ze zmianami w następnej wersji usługi systemu Windows 😉 docs.microsoft.com/en-us/dotnet/api/…
Jaykul
50

„dir” jest aliasem dla Get-ChildItem, który zwróci klasę System.IO.FileInfo, gdy wywołujesz ją z systemu plików, który ma VersionInfo jako właściwość. Więc ...

Aby uzyskać informacje o wersji pojedynczego pliku, wykonaj następujące czynności:

PS C:\Windows> (dir .\write.exe).VersionInfo | fl


OriginalFilename : write
FileDescription  : Windows Write
ProductName      : Microsoft® Windows® Operating System
Comments         :
CompanyName      : Microsoft Corporation
FileName         : C:\Windows\write.exe
FileVersion      : 6.1.7600.16385 (win7_rtm.090713-1255)
ProductVersion   : 6.1.7600.16385
IsDebug          : False
IsPatched        : False
IsPreRelease     : False
IsPrivateBuild   : False
IsSpecialBuild   : False
Language         : English (United States)
LegalCopyright   : © Microsoft Corporation. All rights reserved.
LegalTrademarks  :
PrivateBuild     :
SpecialBuild     :

W przypadku wielu plików:

PS C:\Windows> dir *.exe | %{ $_.VersionInfo }

ProductVersion   FileVersion      FileName
--------------   -----------      --------
6.1.7600.16385   6.1.7600.1638... C:\Windows\bfsvc.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\explorer.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\fveupdate.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\HelpPane.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\hh.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\notepad.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\regedit.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\splwow64.exe
1,7,0,0          1,7,0,0          C:\Windows\twunk_16.exe
1,7,1,0          1,7,1,0          C:\Windows\twunk_32.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\winhlp32.exe
6.1.7600.16385   6.1.7600.1638... C:\Windows\write.exe
xcud
źródło
Pomocne jest to, że dołączasz również inne popularne metadane (takie jak nazwa i opis firmy).
David Faivre
16

Wolę zainstalować rozszerzenia społeczności PowerShell i po prostu użyć funkcji Get-FileVersionInfo, którą zapewnia.

Tak jak to:

Get-FileVersionInfo MyAssembly.dll

z wyjściem takim jak:

ProductVersion FileVersion FileName
-------------- ----------- --------
1.0.2907.18095 1.0.2907.18095 C: \ Path \ To \ MyAssembly.dll

Użyłem go przeciwko całemu katalogowi zestawów z wielkim sukcesem.

David Mohundro
źródło
12

Zdaję sobie sprawę, że już na to odpowiedziano, ale jeśli ktoś jest zainteresowany wpisaniem mniejszej liczby znaków, uważam, że jest to najkrótszy sposób napisania tego w PS v3 +:

ls application.exe | % versioninfo
  • ls jest aliasem dla Get-ChildItem
  • % jest aliasem dla ForEach-Object
  • versioninfo tutaj jest skrótowy sposób pisania {$_.VersionInfo}

Zaletą używania lsw ten sposób jest to, że można go łatwo dostosować do wyszukiwania danego pliku w podfolderach. Na przykład poniższe polecenie zwróci informacje o wersji dla wszystkich plików wywoływanych application.exew podfolderach:

ls application.exe -r | % versioninfo
  • -r jest aliasem dla -Recurse

Możesz to dodatkowo uściślić, dodając, -ea silentlycontinueaby ignorować takie rzeczy, jak błędy uprawnień w folderach, których nie możesz przeszukiwać:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea jest aliasem dla -ErrorAction

Wreszcie, jeśli otrzymujesz wielokropki (...) w wynikach, możesz dołączyć, | flaby zwrócić informacje w innym formacie. Zwraca to znacznie więcej szczegółów, mimo że jest sformatowane w formie listy, a nie w jednym wierszu na wynik:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl jest aliasem dla Format-List

Zdaję sobie sprawę, że jest to bardzo podobne do odpowiedzi xcud pod tym względem lsi diroba są aliasami dla Get-ChildItem. Ale mam nadzieję, że moja „najkrótsza” metoda komuś pomoże.

Ostatni przykład można napisać odręcznie w następujący sposób:

Get-ChildItem -Filter application.exe -Recurse -ErrorAction SilentlyContinue | ForEach-Object {$_.VersionInfo} | Format-List

... ale myślę, że moja droga jest fajniejsza i dla niektórych łatwiejsza do zapamiętania. (Ale głównie fajniejsze).

oliver-clare
źródło
11

Innym sposobem jest użycie wbudowanej techniki dostępu do plików:

(get-item .\filename.exe).VersionInfo | FL

Możesz również pobrać określoną właściwość z VersionInfo, a zatem:

(get-item .\filename.exe).VersionInfo.FileVersion

Jest to dość zbliżone do techniki reż.

Wes
źródło
(get-item \\ "$ computerName" \ "C $ \ Program Files \ Symantec AntiVirus \ VPDN_LU.exe"). VersionInfo.FileVersion działało dla mnie. Musiałem dodać nazwę komputera z pętli.
Tequila
7

Jest to oparte na innych odpowiedziach, ale dokładnie o to mi chodziło:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
noelicus
źródło
Jestem zaintrygowany Get-Commandzastosowanym do pliku dll. Czy mógłbyś bardziej szczegółowo opisać jego efekt (jeszcze przed wywołaniem właściwości FileVersionInfo)?
Stephane Rolland
Pliki dll zawierają FileVersionInfotak samo, jak pliki exe. Zastosowanie tego polecenia do ścieżki spowoduje uzyskanie informacji o wersji pliku!
noelicus
4
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")
EBGreen
źródło
4

Uważam, że to przydatne:

function Get-Version($filePath)
{
   $name = @{Name="Name";Expression= {split-path -leaf $_.FileName}}
   $path = @{Name="Path";Expression= {split-path $_.FileName}}
   dir -recurse -path $filePath | % { if ($_.Name -match "(.*dll|.*exe)$") {$_.VersionInfo}} | select FileVersion, $name, $path
}
Chriseyre2000
źródło
Czy to jest VBScript?
macetw
1
Nie, to powershell
Chriseyre2000
2

Jak powiedział EBGreen, [System.Diagnostics.FileVersionInfo] :: GetVersionInfo (ścieżka) będzie działać, ale pamiętaj, że możesz również pobrać wszystkie elementy członkowskie FileVersionInfo, na przykład:

[System.Diagnostics.FileVersionInfo]::GetVersionInfo(path).CompanyName

Powinieneś być w stanie użyć każdego członka FileVersionInfo udokumentowanego tutaj, co da ci w zasadzie wszystko, czego możesz chcieć w pliku.

Adam Haile
źródło
1

Tutaj alternatywna metoda. Używa Get-WmiObject CIM_DATAFILE do wyboru wersji.

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version
Knuckle-Dragger
źródło
używając ścieżki udziału ze spacjami w nazwie, otrzymałem informację „Nie można znaleźć właściwości„ Wersja ”w tym obiekcie. Sprawdź, czy właściwość istnieje.”
AnneTheAgile