Dapatkan versi file di PowerShell

146

Bagaimana Anda bisa mendapatkan informasi versi dari .dllatau .exefile di PowerShell?

Saya secara khusus tertarik File Version, meskipun informasi versi lainnya (yaitu, Company, Language, Product Name, dll) akan membantu juga.

Kaisar XLII
sumber

Jawaban:

140

Karena PowerShell dapat memanggil kelas .NET , Anda dapat melakukan hal berikut:

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

Atau seperti yang tercantum di sini pada daftar file:

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

Atau bahkan lebih bagus sebagai skrip: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/

Lars Truijens
sumber
8
Lihat @Jaykul untuk solusi yang tidak memerlukan objek .NET. Respons IMHO Jaykul seharusnya dipilih sebagai jawabannya :)
Thomas Bratt
2
Walaupun jawaban yang lain memberikan perintah yang lebih pendek, semua yang saya coba cetak terlalu banyak info dan memotong jalur file ke "...". Perintah ke-2 dalam jawaban ini memberikan apa yang Anda butuhkan, berfungsi untuk direktori file, dan memformat dengan cara yang mudah untuk melihat bagaimana memodifikasinya untuk mengembalikan info lainnya. Ubah saja .LegalCopyright pada perintah menjadi .FileVersion.
Dennis
Ini adalah versi yang benar untuk .NET EXEs. Jawaban Jaykul tidak mendapatkan versi yang sama.
ashes999
Itu sebenarnya tidak benar. Lihat get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -forcedan bandingkan FilePrivatePart dengan bagian terakhir dari FileVersion. FileVersion menunjukkan apa yang awalnya dikirim, dan bukan versi yang ditambal. Perintah ini, di sisi lain, menunjukkan nomor versi yang ditambal: (get-command C: \ Windows \ System32 \ ubpm.dll)
.Version
Contoh yang lebih baik adalah C yang baru ditambal : \ Windows \ System32 \ Lsasrv.dll ... tetapi kenyataannya adalah (Get-Command ... ).Versionmengembalikan ProductVersion bukan FileVersion , dan terkadang itu penting. Jadi untuk solusi lengkap yang benar-benar mengembalikan FileVersion yang diperbarui , lihat contoh Update-TypeData dalam jawaban saya di bawah ini.
Jaykul
170

Saat ini Anda bisa mendapatkan FileVersionInfo dari Get-Item atau Get-ChildItem, tetapi itu akan menampilkan FileVersion asli dari produk yang dikirim, dan bukan versi yang diperbarui. Misalnya:

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

Menariknya, Anda bisa mendapatkan ProductVersion yang diperbarui (ditambal) dengan menggunakan ini:

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

Perbedaan yang saya buat antara "asli" dan "ditambal" pada dasarnya karena cara FileVersion dihitung ( lihat dokumen di sini ). Pada dasarnya sejak Vista, Windows API GetFileVersionInfo menanyakan bagian dari informasi versi dari file netral bahasa (exe / dll) dan bagian tidak tetap dari file mui khusus bahasa (yang tidak diperbarui setiap kali file berubah ).

Jadi dengan file seperti lsasrv (yang diganti karena masalah keamanan di SSL / TLS / RDS pada November 2014) versi yang dilaporkan oleh kedua perintah ini (setidaknya untuk sementara waktu setelah tanggal itu) berbeda, dan yang kedua adalah lebih banyak versi "benar".

Namun, meskipun itu benar di LSASrv, dimungkinkan untuk ProductVersion dan FileVersion menjadi berbeda (itu umum, sebenarnya). Jadi satu-satunya cara untuk mendapatkan Fileversion yang diperbarui langsung dari file assembly adalah dengan membangunnya sendiri dari bagian-bagiannya, seperti ini:

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

Atau dengan menarik data dari ini:

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

Anda dapat dengan mudah menambahkan ini ke semua objek FileInfo dengan memperbarui TypeData di PowerShell:

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

Sekarang setiap kali Anda melakukannya Get-ChildItematau Get-ItemAnda akan memiliki FileVersionproperti yang menampilkan FileVersion yang diperbarui ...

Jaykul
sumber
10
Dan untuk membuat ini setara dengan jawaban yang diterima Lars, cukup gunakan(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
rand0m1
1
Saya tertarik dengan Get-Commandaplikasi file dll. Bisakah Anda menguraikan efeknya?
Stephane Rolland
3
Peringatan FileVersionInfo.FileVersion adalah representasi string yang mungkin tidak mutakhir. Anda harus melihat FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart. Lihat GetFileVersionInfo () mengembalikan informasi versi file yang salah
bdeem
1
@Jaykul Untuk mengklarifikasi komentar / pertanyaan saya sebelumnya: jawaban asli menunjukkan bagaimana mendapatkan ProductVersion di PowerShell melalui beberapa konvolusi yang menarik, karena ProductVersion mungkin lebih indikatif daripada FileVersion. Jawaban asli tidak menyebutkan properti VersionInfo.ProductVersion, mungkin karena jawabannya sudah ada sebelumnya. Apakah (Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersioncara baru yang lebih sederhana untuk mendapatkan informasi ProductVersion yang sama seperti yang didokumentasikan dalam jawabannya? Saya tidak benar-benar percaya Microsoft untuk menggunakan istilah ini ProductVersionsecara konsisten.
Tydaeus
2
@ Tydaeus Ini bukan hal baru. Anda dapat mencarinya di dokumen dan melihat seberapa jauh ke belakang (.NET 1.1) 😏. Jawaban saya menyebutkan ProductVersion, tetapi versi yang kami hitung dengan semua kode ScriptProperty itu adalah Versi FILE yang asli, bukan ProductVersion. Mereka terkadang sama, tetapi tidak selalu. Unfortunately Dan sayangnya, setiap contoh di dunia nyata saya muncul dengan perubahan dalam rilis layanan Windows berikutnya 😉 docs.microsoft.com/en-us/dotnet/api/…
Jaykul
50

'dir' adalah alias untuk Get-ChildItem yang akan mengembalikan kelas System.IO.FileInfo saat Anda memanggilnya dari sistem file yang memiliki VersionInfo sebagai properti. Jadi ...

Untuk mendapatkan info versi satu file, lakukan ini:

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     :

Untuk banyak file ini:

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
sumber
Bermanfaat karena Anda memasukkan data meta umum lainnya juga (seperti nama dan deskripsi perusahaan).
David Faivre
16

Saya lebih suka menginstal Ekstensi Komunitas PowerShell dan cukup gunakan fungsi Get-FileVersionInfo yang disediakannya.

Seperti itu:

Dapatkan-FileVersionInfo MyAssembly.dll

dengan output seperti:

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

Saya telah menggunakannya terhadap seluruh direktori majelis dengan sukses besar.

David Mohundro
sumber
12

Saya menyadari ini sudah dijawab, tetapi jika ada yang tertarik untuk mengetik lebih sedikit karakter, saya yakin ini adalah cara terpendek menulis ini di PS v3 +:

ls application.exe | % versioninfo
  • ls adalah alias untuk Get-ChildItem
  • % adalah alias untuk ForEach-Object
  • versioninfo di sini adalah cara penulisan yang singkat {$_.VersionInfo}

Manfaat menggunakan lscara ini adalah Anda dapat dengan mudah mengadaptasinya untuk mencari file yang diberikan dalam subfolder. Misalnya, perintah berikut akan mengembalikan info versi untuk semua file yang dipanggil application.exedalam subfolder:

ls application.exe -r | % versioninfo
  • -r adalah alias untuk -Recurse

Anda dapat memperbaiki ini lebih lanjut dengan menambahkan -ea silentlycontinueuntuk mengabaikan hal-hal seperti kesalahan izin dalam folder yang tidak dapat Anda cari:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea adalah alias untuk -ErrorAction

Terakhir, jika Anda mendapatkan elips (...) di hasil Anda, Anda dapat menambahkan | fluntuk mengembalikan informasi dalam format yang berbeda. Ini menghasilkan lebih banyak detail, meskipun diformat dalam daftar, bukan pada satu baris per hasil:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl adalah alias untuk Format-List

Saya menyadari ini sangat mirip dengan balasan xcud dalam hal itu lsdan dirkeduanya alias untuk Get-ChildItem. Tapi saya berharap metode "terpendek" saya akan membantu seseorang.

Contoh terakhir dapat ditulis dengan tulisan tangan sebagai berikut:

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

... tapi saya pikir cara saya lebih dingin dan, bagi sebagian orang, lebih mudah diingat. (Tapi kebanyakan lebih dingin).

oliver-clare
sumber
11

Cara lain untuk melakukannya adalah dengan menggunakan teknik akses file bawaan:

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

Anda juga bisa mendapatkan properti tertentu dari VersionInfo, dengan demikian:

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

Ini cukup dekat dengan teknik dir.

Wes
sumber
(get-item \\ "$ computerName" \ "C $ \ Program Files \ Symantec AntiVirus \ VPDN_LU.exe"). VersionInfo.FileVersion bekerja untuk saya. Saya perlu menambahkan nama komputer dari satu lingkaran.
Tequila
7

Ini didasarkan pada jawaban lain, tetapi persis seperti apa yang saya cari:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
Noelicus
sumber
Saya tertarik dengan Get-Commandaplikasi file dll. Bisakah Anda menguraikan efeknya (bahkan sebelum memanggil properti FileVersionInfo)?
Stephane Rolland
File dll mengandung FileVersionInfoseperti halnya file exe. Menerapkan perintah ini ke jalur akan mendapatkan info versi file!
noelicus
4
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")
EBGreen
sumber
4

Saya menemukan ini berguna:

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
sumber
Apakah ini VBScript?
macetw
1
Tidak itu powershell
Chriseyre2000
2

Seperti yang dikatakan EBGreen, [System.Diagnostics.FileVersionInfo] :: GetVersionInfo (path) akan berfungsi, tetapi ingat bahwa Anda juga bisa mendapatkan semua anggota FileVersionInfo, misalnya:

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

Anda harus dapat menggunakan setiap anggota FileVersionInfo yang didokumentasikan di sini, yang pada dasarnya akan memberi Anda apa pun yang Anda inginkan tentang file tersebut.

Adam Haile
sumber
1

Berikut metode alternatif. Ini menggunakan Get-WmiObject CIM_DATAFILE untuk memilih versi.

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version
Knuckle-Dragger
sumber
menggunakan jalur berbagi dengan spasi di namanya, saya mendapatkan "Properti 'Versi' tidak dapat ditemukan pada objek ini. Verifikasi bahwa properti itu ada."
AnneTheAgile