11

I have a VBScript that checks for the existence of a file in a directory on a remote machine. I am looking to retrieve the "Product Version" for said file (NOT "File Version"), but I can't seem to figure out how to do that in VBScript.

I'm currently using Scripting.FileSystemObject to check for the existence of the file.

Thanks.

JMax
  • 26,109
  • 12
  • 69
  • 88
Aaron Alton
  • 22,728
  • 6
  • 34
  • 32
  • Here's a very similar question about JScript - [Detecting the version and company name of an exe using JScript](http://stackoverflow.com/questions/1674134/) – Helen Jun 07 '10 at 20:28

5 Answers5

12

I use a function that is slightly modified from the previous example. The function takes the path and file name and returns the "Product Version"

Function GetProductVersion (sFilePath, sProgram)
Dim FSO,objShell, objFolder, objFolderItem, i 
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(sFilePath & "\" & sProgram) Then
    Set objShell = CreateObject("Shell.Application")
    Set objFolder = objShell.Namespace(sFilePath)
    Set objFolderItem = objFolder.ParseName(sProgram)
    Dim arrHeaders(300)
    For i = 0 To 300
        arrHeaders(i) = objFolder.GetDetailsOf(objFolder.Items, i)
        'WScript.Echo i &"- " & arrHeaders(i) & ": " & objFolder.GetDetailsOf(objFolderItem, i)
        If lcase(arrHeaders(i))= "product version" Then
            GetProductVersion= objFolder.GetDetailsOf(objFolderItem, i)
            Exit For
        End If
    Next
End If
End Function

I've found that the position of the attributes has occasionally changes (not sure why) in XP and Vista so I look for the "product version" attribute and exit the loop once it's found. The commented out line will show all the attributes and a value if available

hollopost
  • 569
  • 9
  • 28
Maputi
  • 121
  • 2
  • 2
    you did not create object of FSO to use it in your function you have to add " Set FSO=CreateObject("Scripting.FileSystemObject") " after line 2 in your function – hollopost Oct 02 '18 at 21:04
  • Why 300? Would it be better to use (2 ^ 15) - 1, which is the maximum integer value? – Frank Lesniak Jan 19 '21 at 04:56
  • Code could use a few obvious improvements. 1. There is no need for the array. Just replace it with a single variable. 2. It makes no sense to pass Items to GetDetailsOf. That parameter "must be a FolderItem object", although apparently if you pass any invalid value, it gives back the header names. Just pass "" in the first call. 3. There's no need for FSO. Namespace() or ParseName() will return Nothing if the directory or file doesn't exist, so you can check for that to guard against bad path/filename (as demonstrated in the current documentation for GetDetailsOf). – Lexikos May 15 '22 at 06:54
3

You can use the Shell.Namespace to get the extended properties on a file, one of which is the Product Version. The GetDetailsOf function should work. You can test with the following code to get an idea:

Dim fillAttributes(300)

Set shell = CreateObject("Shell.Application")
Set folder = shell.Namespace("C:\Windows")

Set file = folder.ParseName("notepad.exe")

For i = 0 to 299
    Wscript.Echo i & vbtab & fillAttributes(i) _
        & ": " & folder.GetDetailsOf(file, i) 
Next

One thing to be aware of:

The extended properties of a file differs between versions of Windows. Hence, the product version index numbers changes based on the version of Windows you are using. You can use the code above to determine what they are. From my testing, I believe they are as follows:

  • Window XP - 39
  • Windows Vista - 252
  • Windows 7 - 268
  • Windows 2008 R2 SP1 - 271
  • Windows 2012 R2 - 285

You may also find the following post helpful.

Pik Master
  • 103
  • 1
  • 6
Garett
  • 16,632
  • 5
  • 55
  • 63
  • 4
    the first line of your code" Dim fillAttributes(300) " didn't add anything in your script . You have to replace " fillAttributes(i) " with " folder.GetDetailsOf(folder.Items,i) " – hollopost Oct 02 '18 at 21:09
2

The product version can be retrieved directly with the ExtendedProperty method.

function GetProductVersion(Path)
    dim shell, file
    set shell = CreateObject("Shell.Application")
    const ssfDesktop = 0
    set file = shell.Namespace(ssfDesktop).ParseName(Path)
    if not (file is nothing) then
        GetProductVersion = _
            file.ExtendedProperty("System.Software.ProductVersion")
    end if
end function

By contrast with a couple of older answers,

  • This does not require looping over an unknown or arbitrary number of columns with GetDetailsOf.
  • This uses the canonical name of the property, not the display name. One can also use the FMTID and PID: "{0CEF7D53-FA64-11D1-A203-0000F81FEDEE} 8".
  • This avoids the need to split the path into directory and name, by starting at the root (desktop) namespace.
Lexikos
  • 987
  • 6
  • 16
0
' must explicitly declare all variables
Option Explicit
' declare global variables
Dim aFileFullPath, aDetail
' set global variables
aFileFullPath = "C:\Windows\Notepad.exe"
aDetail = "Product Version"
' display a message with file location and file detail
WScript.Echo ("File location: " & vbTab & aFileFullPath & vbNewLine & _
aDetail & ": " & vbTab & fGetFileDetail(aFileFullPath, aDetail))
' make global variable happy. set them free
Set aFileFullPath = Nothing
Set aDetail = Nothing
' get file detail function. created by Stefan Arhip on 20111026 1000
Function fGetFileDetail(aFileFullPath, aDetail)
' declare local variables
Dim pvShell, pvFileSystemObject, pvFolderName, pvFileName, pvFolder, pvFile, i
' set object to work with files
Set pvFileSystemObject = CreateObject("Scripting.FileSystemObject")
' check if aFileFullPath provided exists
If pvFileSystemObject.FileExists(aFileFullPath) Then
' extract only folder & file from aFileFullPath
pvFolderName = pvFileSystemObject.GetFile(aFileFullPath).ParentFolder
pvFileName = pvFileSystemObject.GetFile(aFileFullPath).Name
' set object to work with file details
Set pvShell = CreateObject("Shell.Application")
Set pvFolder = pvShell.Namespace(pvFolderName)
Set pvFile = pvFolder.ParseName(pvFileName)
' in case detail is not detected...
fGetFileDetail = "Detail not detected"
' parse 400 details for given file
For i = 0 To 399
' if desired detail name is found, set function result to detail value
If uCase(pvFolder.GetDetailsOf(pvFolder.Items, i)) = uCase(aDetail) Then
fGetFileDetail = pvFolder.GetDetailsOf(pvFile, i)
End If
Next
' if aFileFullPath provided do not exists
Else
fGetFileDetail = "File not found"
End If
' make local variable happy. set them free
Set pvShell = Nothing
Set pvFileSystemObject = Nothing
Set pvFolderName = Nothing
Set pvFileName = Nothing
Set pvFolder = Nothing
Set pvFile = Nothing
Set i = Nothing
End Function
-1
Wscript.Echo CreateObject("Scripting.FileSystemObject").GetFileVersion("C:\Windows\notepad.exe")
JMax
  • 26,109
  • 12
  • 69
  • 88
  • 1
    The OP said *Product Version*, not *File Version*. They are not the same thing. – Helen Sep 08 '11 at 07:07
  • This isn't technically correct but it serves my purposes fine and is much more concise than all other answers. – sirdank Feb 10 '20 at 13:18