รับรุ่นของไฟล์ใน PowerShell


146

คุณจะรับข้อมูลรุ่นจาก.dllหรือ.exeไฟล์ใน PowerShell ได้อย่างไร

ผมสนใจเฉพาะในFile Versionแต่ข้อมูลรุ่นอื่น ๆ (นั่นคือCompany, Language, Product Nameฯลฯ ) จะเป็นประโยชน์เช่นกัน

คำตอบ:


140

เนื่องจาก PowerShell สามารถเรียกคลาสNET ได้คุณสามารถทำสิ่งต่อไปนี้:

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

หรือตามที่ระบุไว้ที่นี่ในรายการไฟล์:

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

หรือแม้กระทั่งดีกว่าเป็นสคริปต์: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/


8
ดู @Jaykul สำหรับวิธีแก้ปัญหาที่ไม่ต้องการวัตถุ. NET การตอบสนองของ IMHO Jaykul ควรจะได้รับเลือกให้เป็นคำตอบ :)
โทมัส Bratt

2
แม้ว่าคำตอบอื่น ๆ ให้คำสั่งที่สั้นกว่า แต่คำตอบทั้งหมดที่ฉันลองพิมพ์ข้อมูลมากเกินไปและตัดทอนพา ธ ของไฟล์เป็น "... " คำสั่งที่ 2 ในคำตอบนี้ให้สิ่งที่คุณต้องการทำงานกับไดเรกทอรีของไฟล์และจัดรูปแบบในแบบที่ง่ายต่อการดูวิธีแก้ไขเพื่อส่งคืนข้อมูลอื่น เพียงแค่เปลี่ยน. LegCopyright ในคำสั่งเป็น. FileVersion
Dennis

นี่เป็นรุ่นที่ถูกต้องสำหรับ. NET EXE คำตอบของ Jaykul ไม่ได้เป็นเวอร์ชั่นเดียวกัน
ashes999

ที่จริงไม่ถูกต้อง ดูget-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -forceและเปรียบเทียบ FilePrivatePart กับส่วนสุดท้ายของ FileVersion FileVersion แสดงสิ่งที่จัดส่งมา แต่ดั้งเดิมไม่ใช่เวอร์ชันที่ได้รับการแก้ไข คำสั่งนี้ในมืออื่น ๆ , การแสดงหมายเลขรุ่น patched: (ได้รับคำสั่ง C: \ Windows \ System32 \ ubpm.dll) .Version
Jaykul

ตัวอย่างที่ดีกว่าคือC: \ Windows \ System32 \ Lsasrv.dll ที่เพิ่งติดตั้งแล้วแต่ความจริงก็คือการ(Get-Command ... ).VersionคืนProductVersionไม่ใช่FileVersionและบางครั้งก็สำคัญ ดังนั้นสำหรับโซลูชันเต็มรูปแบบที่ส่งคืนFileVersion ที่อัปเดตจริงให้ตรวจสอบตัวอย่าง Update-TypeData ในคำตอบของฉันด้านล่าง
Jaykul

170

ทุกวันนี้คุณสามารถรับ FileVersionInfo จาก Get-Item หรือ Get-ChildItem แต่จะแสดง FileVersion ดั้งเดิมจากผลิตภัณฑ์ที่จัดส่งไม่ใช่เวอร์ชันที่อัปเดต ตัวอย่างเช่น

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

น่าสนใจคุณสามารถรับProductVersion ที่ปรับปรุงแล้ว (แก้ไข) โดยใช้สิ่งนี้:

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

ความแตกต่างที่ฉันทำระหว่าง "ดั้งเดิม" และ "แพตช์" นั้นเป็นเพราะวิธีการคำนวณ FileVersion ( ดูเอกสารที่นี่ ) โดยพื้นฐานตั้งแต่ Vista แล้ว Windows API GetFileVersionInfo กำลังสืบค้นส่วนของข้อมูลรุ่นจากไฟล์ภาษากลาง (exe / dll) และส่วนที่ไม่คงที่จากไฟล์ mui เฉพาะภาษา (ซึ่งไม่ได้รับการปรับปรุงทุกครั้งที่มีการเปลี่ยนแปลงไฟล์ )

ดังนั้นด้วยไฟล์เช่น lsasrv (ซึ่งถูกแทนที่เนื่องจากปัญหาด้านความปลอดภัยใน SSL / TLS / RDS ในเดือนพฤศจิกายน 2014) เวอร์ชันที่รายงานโดยคำสั่งทั้งสองนี้ (อย่างน้อยก็สักพักหนึ่งหลังจากวันที่นั้น) แตกต่างกันและอันที่สองคือ มากกว่ารุ่น "ถูกต้อง"

อย่างไรก็ตามแม้ว่าจะถูกต้องใน LSASrv แต่เป็นไปได้ที่ ProductVersion และ FileVersion จะแตกต่างกัน ดังนั้นวิธีเดียวที่จะได้รับFileversion ที่ได้รับการอัพเดตโดยตรงจากไฟล์ประกอบคือการสร้างมันขึ้นมาเองจากส่วนต่างๆดังนี้:

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

หรือดึงข้อมูลจากสิ่งนี้:

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

คุณสามารถเพิ่มสิ่งนี้ไปยังวัตถุ FileInfo ทั้งหมดโดยการปรับปรุง TypeData ใน PowerShell:

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

ตอนนี้ทุกครั้งที่คุณทำGet-ChildItemหรือGet-ItemคุณจะมีFileVersionคุณสมบัติที่แสดง FileVersion ที่อัปเดต ...


10
และเพื่อให้สิ่งนี้เทียบเท่ากับคำตอบที่ยอมรับของ Lars เพียงใช้(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
rand0m1

1
ฉันรู้สึกทึ่งกับการGet-Commandใช้กับไฟล์ dll คุณช่วยอธิบายเกี่ยวกับผลกระทบของมันได้อย่างละเอียดหรือไม่?
Stephane Rolland

3
คำเตือน FileVersionInfo.FileVersion เป็นการแสดงสตริงที่อาจไม่ทันสมัย คุณควรดูที่ FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart ดูGetFileVersionInfo () ส่งคืนข้อมูลเวอร์ชันของไฟล์ผิด
bdeem

1
@ Jaykul เพื่อชี้แจงความเห็น / คำถามก่อนหน้านี้ของฉัน: คำตอบเดิมแสดงให้เห็นถึงวิธีการรับ ProductVersion ใน PowerShell ผ่านการโน้มน้าวใจที่น่าสนใจเนื่องจาก ProductVersion อาจบ่งบอกได้มากกว่า FileVersion คำตอบดั้งเดิมไม่ได้กล่าวถึงคุณสมบัติ VersionInfo.ProductVersion อาจเป็นเพราะคำตอบนั้นเป็นวันที่ล่วงหน้า เป็น(Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersionวิธีที่ใหม่กว่าที่ง่ายกว่าในการรับข้อมูล ProductVersion เช่นเดียวกับที่บันทึกไว้ในคำตอบหรือไม่ ฉันไม่เชื่อถือ Microsoft ให้ใช้คำนี้ProductVersionอย่างสม่ำเสมอ
Tydaeus

2
@Tydaeus ไม่ใช่เรื่องใหม่ คุณสามารถค้นหาบนเอกสารและดูว่ามันจะไปไกลแค่ไหน (. NET 1.1) คำตอบของฉันพูดถึง ProductVersion แต่รุ่นที่เรากำลังคำนวณด้วยรหัส ScriptProperty ทั้งหมดนั้นเป็นเวอร์ชั่นไฟล์จริงไม่ใช่ ProductVersion บางครั้งเหมือนกัน แต่ไม่เสมอไป 😔และขออภัยทุกตัวอย่างจริงของโลกผมมาทันกับการเปลี่ยนแปลงในรุ่นต่อไปของการบริการของ Windows 😉 docs.microsoft.com/en-us/dotnet/api/...
Jaykul

50

'dir' เป็นนามแฝงสำหรับ Get-ChildItem ซึ่งจะส่งคืนคลาส System.IO.FileInfo เมื่อคุณเรียกใช้จากระบบไฟล์ที่มี VersionInfo เป็นคุณสมบัติ ดังนั้น ...

ในการรับข้อมูลรุ่นของไฟล์เดียวให้ทำดังนี้

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     :

สำหรับหลายไฟล์นี้:

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

มีประโยชน์ในการที่คุณรวมข้อมูลเมตาทั่วไปอื่น ๆ เช่นกัน (เช่นชื่อ บริษัท และคำอธิบาย)
David Faivre

16

ฉันต้องการติดตั้งPowerShell Community Extensionsและเพียงแค่ใช้ฟังก์ชัน Get-FileVersionInfo ที่มีให้

ชอบมาก

Get-FileVersionInfo MyAssembly.dll

ด้วยผลลัพธ์เช่น:

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

ฉันใช้มันกับไดเรกทอรีทั้งหมดของการชุมนุมที่ประสบความสำเร็จ


12

ฉันรู้ว่าสิ่งนี้ได้รับคำตอบแล้ว แต่ถ้าใครสนใจพิมพ์ตัวอักษรน้อยลงฉันเชื่อว่านี่เป็นวิธีที่สั้นที่สุดในการเขียนใน PS v3 +:

ls application.exe | % versioninfo
  • ls เป็นชื่อแทน Get-ChildItem
  • % เป็นชื่อแทน ForEach-Object
  • versioninfo นี่เป็นวิธีจดชวเลข {$_.VersionInfo}

ประโยชน์ของการใช้งานlsในลักษณะนี้คือคุณสามารถปรับเปลี่ยนได้อย่างง่ายดายเพื่อค้นหาไฟล์ที่กำหนดภายในโฟลเดอร์ย่อย ตัวอย่างเช่นคำสั่งต่อไปนี้จะส่งคืนข้อมูลเวอร์ชันสำหรับไฟล์ทั้งหมดที่เรียกว่าapplication.exeภายในโฟลเดอร์ย่อย:

ls application.exe -r | % versioninfo
  • -r เป็นชื่อแทน -Recurse

คุณสามารถปรับแต่งสิ่งนี้เพิ่มเติมโดยการเพิ่ม-ea silentlycontinueเพื่อละเว้นสิ่งต่าง ๆ เช่นข้อผิดพลาดการอนุญาตในโฟลเดอร์ที่คุณไม่สามารถค้นหา:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea เป็นชื่อแทน -ErrorAction

สุดท้ายหากคุณได้รับจุดไข่ปลา (... ) ในผลลัพธ์ของคุณคุณสามารถผนวก| flเพื่อส่งคืนข้อมูลในรูปแบบอื่น สิ่งนี้จะส่งกลับรายละเอียดมากขึ้นแม้ว่าจะมีการจัดรูปแบบในรายการ แต่จะอยู่ในบรรทัดเดียวต่อผลลัพธ์:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl เป็นชื่อแทน Format-List

ฉันรู้นี้จะคล้ายกับการตอบกลับ xcud ในที่lsและมีชื่อแทนทั้งdir Get-ChildItemแต่ฉันหวังว่าวิธี "สั้นที่สุด" ของฉันจะช่วยใครซักคน

ตัวอย่างสุดท้ายสามารถเขียนด้วยมือได้ดังนี้:

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

... แต่ฉันคิดว่าวิธีการของฉันเจ๋งกว่าและง่ายกว่าที่จะจำได้ (แต่ส่วนใหญ่เย็นกว่า)


11

อีกวิธีหนึ่งในการทำคือใช้เทคนิคการเข้าถึงไฟล์ในตัว:

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

นอกจากนี้คุณยังสามารถนำคุณสมบัติเฉพาะออกจาก VersionInfo ได้เช่น:

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

นี่ค่อนข้างใกล้กับเทคนิค dir


(get-item \\ "$ computerName" \ "AntiVirus \ VPDN_LU.exe Files \ Symantec C $ \ Program" VersionInfo.FileVersion ใช้งานได้สำหรับฉัน ฉันต้องการเพิ่มชื่อคอมพิวเตอร์จากลูป
เตกีล่า

7

นี่ขึ้นอยู่กับคำตอบอื่น ๆ แต่เป็นสิ่งที่ฉันเป็นหลังจาก:

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

ฉันรู้สึกทึ่งกับการGet-Commandใช้กับไฟล์ dll คุณสามารถอธิบายรายละเอียดเกี่ยวกับเอฟเฟกต์ของมันได้ (ก่อนที่จะเรียกใช้ FileVersionInfo ของคุณสมบัติ)
Stephane Rolland

ไฟล์ dll มีFileVersionInfoเช่นเดียวกับไฟล์ exe ทำ การใช้คำสั่งนี้กับพา ธ จะได้รับข้อมูลเวอร์ชันของไฟล์!
noelicus


4

ฉันพบว่ามีประโยชน์นี้:

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
}

นี่เป็น VBScript หรือไม่
macetw

1
ไม่มี PowerShell
Chriseyre2000

2

ดังที่ EBGreen กล่าวว่า [System.Diagnostics.FileVersionInfo] :: GetVersionInfo (เส้นทาง) จะใช้งานได้ แต่โปรดจำไว้ว่าคุณสามารถรับสมาชิกทั้งหมดของ FileVersionInfo ได้เช่น:

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

คุณควรจะสามารถใช้สมาชิกทุกคนของ FileVersionInfo ที่จัดทำเอกสารไว้ที่นี่ซึ่งจะทำให้คุณได้รับสิ่งที่คุณต้องการเกี่ยวกับไฟล์


1

นี่คือวิธีการทางเลือก มันใช้ Get-WmiObject CIM_DATAFILE เพื่อเลือกรุ่น

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

ใช้เส้นทางที่ใช้ร่วมกันที่มีช่องว่างในชื่อฉันได้รับ "ไม่พบคุณสมบัติ 'รุ่น' ในวัตถุนี้ตรวจสอบว่ามีคุณสมบัติอยู่"
AnneTheAgile
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.