Nhận phiên bản tệp trong PowerShell


146

Làm cách nào bạn có thể lấy thông tin phiên bản từ một .dllhoặc .exetệp trong PowerShell?

Tôi đang quan tâm đặc biệt trong File Version, mặc dù thông tin phiên bản khác (có nghĩa là, Company, Language, Product Name, vv) sẽ rất hữu ích là tốt.

Câu trả lời:


140

Vì PowerShell có thể gọi các lớp .NET , bạn có thể làm như sau:

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

Hoặc như được lưu ý ở đây trên một danh sách các tập tin:

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

Hoặc thậm chí đẹp hơn như một tập lệnh: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-inif/


8
Xem @Jaykul để biết giải pháp không yêu cầu đối tượng .NET. Câu trả lời của IMHO Jaykul nên được chọn là câu trả lời :)
Thomas Bratt

2
Mặc dù các câu trả lời khác đưa ra các lệnh ngắn hơn, nhưng tất cả những câu tôi đã thử in ra quá nhiều thông tin và cắt ngắn đường dẫn tệp thành "...". Lệnh thứ 2 trong câu trả lời này chỉ cung cấp những gì bạn cần, hoạt động cho một thư mục tệp và định dạng theo cách dễ dàng để xem cách sửa đổi nó để trả về thông tin khác. Chỉ cần thay đổi .LegalCopyright trong lệnh thành .ileVersion.
Dennis

Đây là phiên bản chính xác cho .NET EXEs. Câu trả lời của Jaykul không có cùng phiên bản.
tro999

Điều đó thực sự không đúng. Nhìn vào get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -forcevà so sánh FilePrivatePart với phần cuối cùng của FileVersion. FileVersion hiển thị những gì ban đầu được vận chuyển, và không phải là phiên bản vá. Lệnh này, mặt khác, chương trình số phiên bản vá: (get-lệnh C: \ Windows \ System32 \ ubpm.dll) .Version
Jaykul

Một ví dụ tốt hơn sẽ là bản vá lỗi C: \ Windows \ System32 \ Lsasrv.dll ... nhưng sự thật là (Get-Command ... ).Versiontrả về ProductVersion chứ không phải FileVersion và đôi khi có vấn đề. Vì vậy, để có một giải pháp đầy đủ thực sự trả về FileVersion được cập nhật , hãy xem ví dụ Update-TypeData trong câu trả lời của tôi dưới đây.
Jaykul

170

Ngày nay, bạn có thể nhận FileVersionInfo từ Get-Item hoặc Get-ChildItem, nhưng nó sẽ hiển thị FileVersion gốc từ sản phẩm được vận chuyển chứ không phải phiên bản cập nhật. Ví dụ:

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

Thật thú vị, bạn có thể nhận được ProductVersion được cập nhật (đã vá) bằng cách sử dụng:

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

Sự khác biệt mà tôi tạo ra giữa "bản gốc" và "bản vá" về cơ bản là do cách tính FileVersion ( xem các tài liệu ở đây ). Về cơ bản kể từ Vista, API Windows GetFileVersionInfo đang truy vấn một phần thông tin phiên bản từ tệp trung lập ngôn ngữ (exe / dll) và phần không cố định từ tệp mui xe cụ thể (không được cập nhật mỗi khi tệp thay đổi ).

Vì vậy, với một tệp như lsasrv (đã bị thay thế do sự cố bảo mật trong SSL / TLS / RDS vào tháng 11 năm 2014), các phiên bản được báo cáo bởi hai lệnh này (ít nhất là trong một thời gian sau ngày đó) là khác nhau và thứ hai là phiên bản "chính xác" hơn.

Tuy nhiên, mặc dù điều đó đúng trong LSASrv, nhưng ProductVersion và FileVersion có thể khác nhau (thực tế là nó phổ biến). Vì vậy, cách duy nhất để có được Fileversion được cập nhật trực tiếp từ tệp lắp ráp là tự xây dựng nó từ các bộ phận, đại loại như thế này:

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

Hoặc bằng cách lấy dữ liệu từ đây:

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

Bạn có thể dễ dàng thêm phần này vào tất cả các đối tượng FileInfo bằng cách cập nhật TypeData trong PowerShell:

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

Bây giờ mỗi khi bạn làm Get-ChildItemhoặc Get-Itembạn sẽ có một thuộc FileVersiontính hiển thị FileVersion được cập nhật ...


10
Và để làm cho câu trả lời này tương đương với câu trả lời được chấp nhận của Lars, chỉ cần sử dụng(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
rand0m1

1
Tôi tò mò về việc Get-Commandáp dụng cho một tập tin dll. Bạn có thể giải thích về tác dụng của nó?
Stephane Rolland

3
Cảnh báo FileVersionInfo.FileVersion là một đại diện chuỗi có thể không cập nhật. Bạn nên xem FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart. Xem GetFileVersionInfo () trả về thông tin phiên bản của tệp sai
bdeem 24/2/2015

1
@Jaykul Để làm rõ nhận xét / câu hỏi trước đây của tôi: câu trả lời ban đầu cho thấy cách lấy ProductVersion trong PowerShell thông qua một số kết luận thú vị, bởi vì ProductVersion có thể mang tính biểu thị nhiều hơn so với FileVersion. Câu trả lời ban đầu không đề cập đến thuộc tính VersionInfo. ProducttVersion, có thể vì câu trả lời trước ngày đó. Là (Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersionmột cách đơn giản mới hơn để có được thông tin ProductVersion giống như tài liệu trong câu trả lời? Tôi không thực sự tin tưởng Microsoft sử dụng thuật ngữ này ProductVersionmột cách nhất quán.
Tydaeus

2
@Tydaeus Nó không mới. Bạn có thể tra cứu nó trên các tài liệu và xem nó đi được bao xa (.NET 1.1). Câu trả lời của tôi đề cập đến ProductVersion, nhưng phiên bản chúng tôi đang tính toán với tất cả mã ScriptProperty đó là Phiên bản TẬP TIN thực sự, không phải là ProductVersion. Chúng đôi khi giống nhau, nhưng không phải lúc nào cũng vậy. 😔 Và thật không may, mỗi ví dụ thực tế tôi đưa ra với những thay đổi trong phiên bản dịch vụ tiếp theo của Windows 😉 docs.microsoft.com/en-us/dotnet/api/...
Jaykul

50

'dir' là một bí danh cho Get-ChildItem, nó sẽ trả về một lớp System.IO.FileInfo khi bạn gọi nó từ hệ thống tệp có phiên bản là một thuộc tính. Vì thế ...

Để có được thông tin phiên bản của một tệp duy nhất, hãy làm điều này:

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     :

Đối với nhiều tệp này:

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

Hữu ích ở chỗ bạn cũng bao gồm các dữ liệu meta phổ biến khác (như tên và mô tả công ty).
David Faivre

16

Tôi thích cài đặt Tiện ích mở rộng cộng đồng PowerShell và chỉ sử dụng chức năng Get-FileVersionInfo mà nó cung cấp.

Thích như vậy:

Get-FileVersionInfo MyAssugging.dll

với đầu ra như:

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

Tôi đã sử dụng nó chống lại toàn bộ thư mục lắp ráp rất thành công.


12

Tôi nhận ra điều này đã được trả lời, nhưng nếu bất cứ ai quan tâm đến việc nhập ít ký tự hơn, tôi tin rằng đây là cách viết ngắn nhất trong PS v3 +:

ls application.exe | % versioninfo
  • ls là bí danh cho Get-ChildItem
  • % là bí danh cho ForEach-Object
  • versioninfo đây là một cách viết tốc ký {$_.VersionInfo}

Lợi ích của việc sử dụng lstheo cách này là bạn có thể dễ dàng điều chỉnh nó để tìm kiếm một tệp nhất định trong các thư mục con. Ví dụ: lệnh sau sẽ trả về thông tin phiên bản cho tất cả các tệp được gọi application.exetrong các thư mục con:

ls application.exe -r | % versioninfo
  • -r là bí danh cho -Recurse

Bạn có thể tinh chỉnh thêm điều này bằng cách thêm vào -ea silentlycontinueđể bỏ qua những thứ như lỗi cấp phép trong các thư mục bạn không thể tìm kiếm:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea là bí danh cho -ErrorAction

Cuối cùng, nếu bạn nhận được dấu chấm lửng (...) trong kết quả của mình, bạn có thể nối thêm | flđể trả về thông tin ở định dạng khác. Điều này trả về nhiều chi tiết hơn, mặc dù được định dạng trong một danh sách, thay vì trên một dòng trên mỗi kết quả:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl là bí danh cho Format-List

Tôi nhận ra điều này rất giống với câu trả lời của xcud trong đó lsdircả hai đều là bí danh Get-ChildItem. Nhưng tôi hy vọng phương pháp "ngắn nhất" của mình sẽ giúp được ai đó.

Ví dụ cuối cùng có thể được viết dài tay theo cách sau:

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

... nhưng tôi nghĩ rằng cách của tôi là mát mẻ hơn và, đối với một số người, dễ nhớ hơn. (Nhưng chủ yếu là mát hơn).


11

Một cách khác để làm điều đó là sử dụng kỹ thuật truy cập tệp tích hợp:

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

Bạn cũng có thể nhận bất kỳ thuộc tính cụ thể nào từ VersionInfo, do đó:

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

Điều này khá gần với kỹ thuật dir.


(get-item \\ "$ computerName" \ "C $ \ Chương trình tập tin \ Symantec AntiVirus \ VPDN_LU.exe"). VersionInfo.FileVersion hoạt động với tôi. Tôi cần thêm một tên máy tính từ một vòng lặp.
Tequila

7

Điều này dựa trên các câu trả lời khác, nhưng chính xác là những gì tôi đã theo sau:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion

Tôi tò mò về việc Get-Commandáp dụng cho một tập tin dll. Bạn có thể giải thích về tác dụng của nó (trước cả khi gọi thuộc tính FileVersionInfo) không?
Stephane Rolland

tập tin dll chứa FileVersionInfogiống như tập tin exe làm. Áp dụng lệnh này vào đường dẫn sẽ nhận được thông tin phiên bản tệp!
noelicus

4
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")

4

Tôi thấy điều này hữu ích:

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
}

Đây có phải là VBScript không?
macetw

1
Không, đó là quyền hạn
Chriseyre2000

2

Như EBGreen đã nói, [System.Diagnostics.FileVersionInfo] :: GetVersionInfo (đường dẫn) sẽ hoạt động, nhưng hãy nhớ rằng bạn cũng có thể nhận được tất cả các thành viên của FileVersionInfo, ví dụ:

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

Bạn sẽ có thể sử dụng mọi thành viên của FileVersionInfo được ghi lại ở đây, điều này sẽ giúp bạn cơ bản bất cứ điều gì bạn muốn về tệp.


1

Đây là một phương pháp thay thế. Nó sử dụng Get-WmiObject CIM_DATAFILE để chọn phiên bản.

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version

sử dụng đường dẫn chia sẻ với khoảng trắng trong tên, tôi nhận được "Không thể tìm thấy 'Phiên bản' trên đối tượng này. Xác minh rằng thuộc tính tồn tại."
AnneTheAgile
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.