Obtener la versión del archivo en PowerShell

146

¿Cómo puede obtener la información de la versión de un archivo .dllo .exeen PowerShell?

Estoy interesado específicamente en File Version, aunque otra información de la versión (es decir, Company, Language, Product Name, etc.) sería útil también.

Emperador XLII
fuente

Respuestas:

140

Como PowerShell puede llamar a clases .NET , puede hacer lo siguiente:

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

O como se indica aquí en una lista de archivos:

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

O incluso mejor como un script: https://jtruher3.wordpress.com/2006/05/14/powershell-and-file-version-information/

Lars Truijens
fuente
8
Consulte @Jaykul para obtener una solución que no requiere un objeto .NET. En mi humilde opinión, la respuesta de Jaykul debería haber sido seleccionada como la respuesta :)
Thomas Bratt
2
Aunque las otras respuestas dan comandos más cortos, todos los que probé imprimen demasiada información y truncan la ruta del archivo a "...". El segundo comando en esta respuesta proporciona justo lo que necesita, funciona para un directorio de archivos y está formateando de manera que sea fácil ver cómo modificarlo para devolver otra información. Simplemente cambie .LegalCopyright en el comando a .FileVersion.
Dennis
Esta es la versión correcta para .NET EXEs. La respuesta de Jaykul no tiene la misma versión.
cenizas999
Eso en realidad no está bien. Mire get-item C:\Windows\System32\ubpm.dll | % VersionInfo | fl * -forcey compare FilePrivatePart con la última parte de FileVersion. FileVersion muestra lo que se envió originalmente, y no la versión parcheada. Este comando, por otro lado, muestra el número de versión parcheado: (get-command C: \ Windows \ System32 \ ubpm.dll)
Versión
Un mejor ejemplo sería el parcheado recientemente C: \ Windows \ System32 \ Lsasrv.dll ... pero la verdad es que (Get-Command ... ).Versiondevuelve ProductVersion, no FileVersion , y a veces eso es importante. Entonces, para obtener una solución completa que realmente devuelva la FileVersion actualizada , consulte el ejemplo Update-TypeData en mi respuesta a continuación.
Jaykul
170

Hoy en día puede obtener FileVersionInfo de Get-Item o Get-ChildItem, pero mostrará la FileVersion original del producto enviado, y no la versión actualizada. Por ejemplo:

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

Curiosamente, se puede obtener la actualización (parche) ProductVersion utilizando la siguiente:

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

La distinción que estoy haciendo entre "original" y "parcheado" se debe básicamente a la forma en que se calcula la FileVersion ( ver los documentos aquí ). Básicamente desde Vista, la API de Windows GetFileVersionInfo está consultando parte de la información de la versión del archivo de idioma neutral (exe / dll) y la parte no fija de un archivo mui específico del idioma (que no se actualiza cada vez que cambian los archivos )

Entonces, con un archivo como lsasrv (que fue reemplazado debido a problemas de seguridad en SSL / TLS / RDS en noviembre de 2014), las versiones informadas por estos dos comandos (al menos durante un tiempo después de esa fecha) fueron diferentes, y el segundo es el versión más "correcta".

Sin embargo, aunque es correcto en LSASrv, es posible que ProductVersion y FileVersion sean diferentes (de hecho, es común). Entonces, la única forma de obtener la Fileversion actualizada directamente desde el archivo de ensamblaje es construirla usted mismo a partir de las partes, algo como esto:

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

O extrayendo los datos de esto:

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

Puede agregar esto fácilmente a todos los objetos FileInfo actualizando TypeData en PowerShell:

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

Ahora, cada vez que lo haga Get-ChildItemo Get-Itemtendrá una FileVersionpropiedad que muestra la FileVersion actualizada ...

Jaykul
fuente
10
Y para que esto sea el equivalente de la respuesta aceptada de Lars, simplemente use(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
rand0m1
1
Estoy intrigado por lo Get-Commandaplicado a un archivo dll. ¿Podrías dar más detalles sobre su efecto?
Stephane Rolland
3
Advertencia FileVersionInfo.FileVersion es una representación de cadena que puede no estar actualizada. Debe mirar FileVersionInfo.FileMajorPart, FileMinorPart, FileBuildPart, FilePrivatePart. Ver GetFileVersionInfo () devuelve información de versión del archivo incorrecto
bdeem
1
@ Jaykul Para aclarar mi comentario / pregunta anterior: la respuesta original demuestra cómo obtener ProductVersion en PowerShell a través de algunas convoluciones interesantes, porque ProductVersion puede ser más indicativo que FileVersion. La respuesta original no menciona la propiedad VersionInfo.ProductVersion, posiblemente porque la respuesta es anterior. ¿Es (Get-Item C:\Windows\System32\Lsasrv.dll).VersionInfo.ProductVersionuna forma más nueva y sencilla de obtener la misma información de ProductVersion que se documenta en la respuesta? Realmente no confío en que Microsoft use el término de manera ProductVersionconsistente.
Tydaeus
2
@Tydaeus No es nuevo. Puede buscarlo en documentos y ver qué tan atrás va (.NET 1.1) 😏. Mi respuesta menciona ProductVersion, pero la versión que estamos calculando con todo ese código ScriptProperty es la versión de ARCHIVO real, no la ProductVersion. A veces son lo mismo, pero no siempre. 😔 Y desafortunadamente, en cada ejemplo del mundo real se me ocurren cambios en la próxima versión de servicio de Windows 😉 docs.microsoft.com/en-us/dotnet/api/…
Jaykul
50

'dir' es un alias para Get-ChildItem que devolverá una clase System.IO.FileInfo cuando lo llame desde el sistema de archivos que tiene VersionInfo como propiedad. Entonces ...

Para obtener la información de la versión de un solo archivo, haga esto:

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     :

Para múltiples archivos esto:

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
fuente
Es útil porque también incluye otros metadatos comunes (como el nombre y la descripción de la empresa).
David Faivre
16

Prefiero instalar PowerShell Community Extensions y simplemente usar la función Get-FileVersionInfo que proporciona.

Al igual que:

Get-FileVersionInfo MyAssembly.dll

con salida como:

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

Lo he usado contra todo un directorio de ensamblajes con gran éxito.

David Mohundro
fuente
12

Me doy cuenta de que esto ya ha sido respondido, pero si alguien está interesado en escribir menos caracteres, creo que esta es la forma más corta de escribir esto en PS v3 +:

ls application.exe | % versioninfo
  • ls es un alias para Get-ChildItem
  • % es un alias para ForEach-Object
  • versioninfo aquí hay una forma abreviada de escribir {$_.VersionInfo}

El beneficio de usar lsde esta manera es que puede adaptarlo fácilmente para buscar un archivo determinado dentro de las subcarpetas. Por ejemplo, el siguiente comando devolverá información de la versión para todos los archivos llamados application.exedentro de las subcarpetas:

ls application.exe -r | % versioninfo
  • -r es un alias para -Recurse

Puede refinar aún más esto agregando -ea silentlycontinuepara ignorar cosas como errores de permisos en carpetas que no puede buscar:

ls application.exe -r -ea silentlycontinue | % versioninfo
  • -ea es un alias para -ErrorAction

Finalmente, si obtiene puntos suspensivos (...) en sus resultados, puede adjuntar | flpara devolver la información en un formato diferente. Esto devuelve muchos más detalles, aunque formateados en una lista, en lugar de en una línea por resultado:

ls application.exe -r -ea silentlycontinue | % versioninfo | fl
  • fl es un alias para Format-List

Me doy cuenta de que esto es muy similar a la respuesta de xcud en eso lsy dirson alias para ambos Get-ChildItem. Pero espero que mi método "más corto" ayude a alguien.

El último ejemplo podría escribirse a mano de la siguiente manera:

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

... pero creo que mi camino es más fresco y, para algunos, más fácil de recordar. (Pero sobre todo más fresco).

Oliver-Clare
fuente
11

Otra forma de hacerlo es usar la técnica de acceso a archivos incorporada:

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

También puede obtener cualquier propiedad particular de VersionInfo, por lo tanto:

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

Esto está bastante cerca de la técnica dir.

Wes
fuente
(get-item \\ "$ computerName" \ "C $ \ Archivos de programa \ Symantec AntiVirus \ VPDN_LU.exe"). VersionInfo.FileVersion funcionó para mí. Necesitaba agregar un nombre de computadora desde un bucle.
Tequila
7

Esto se basa en las otras respuestas, pero es exactamente lo que estaba buscando:

(Get-Command C:\Path\YourFile.Dll).FileVersionInfo.FileVersion
noelicus
fuente
Estoy intrigado por lo Get-Commandaplicado a un archivo dll. ¿Podría dar más detalles sobre su efecto (incluso antes de llamar a la propiedad FileVersionInfo)?
Stephane Rolland
Los archivos dll contienen lo FileVersionInfomismo que los archivos exe. ¡Aplicando este comando a la ruta obtendrá la información de la versión del archivo!
noelicus
4
[System.Diagnostics.FileVersionInfo]::GetVersionInfo("Path\To\File.dll")
EBGreen
fuente
4

Esto me parece útil:

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
fuente
¿Es esto un VBScript?
macetw
1
No, es
PowerShell
2

Como dijo EBGreen, [System.Diagnostics.FileVersionInfo] :: GetVersionInfo (ruta) funcionará, pero recuerde que también puede obtener todos los miembros de FileVersionInfo, por ejemplo:

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

Debería poder utilizar a todos los miembros de FileVersionInfo documentados aquí, que le proporcionarán básicamente todo lo que pueda desear sobre el archivo.

Adam Haile
fuente
1

Aquí un método alternativo. Utiliza Get-WmiObject CIM_DATAFILE para seleccionar la versión.

(Get-WmiObject -Class CIM_DataFile -Filter "Name='C:\\Windows\\explorer.exe'" | Select-Object Version).Version
Knuckle-Dragger
fuente
usando una ruta compartida con espacios en el nombre, obtuve "La propiedad 'Versión' no se puede encontrar en este objeto. Verifique que la propiedad existe".
AnneTheAgile