How to get the version number of an App?

hello,
How to retrieve the version number of an (external) application (or a bundle) that appears in the Cmd+I window of the Finder? Do I need App.Version and App.ExecutableFile commands?
Thanks

You can get the version from the plist:

Private Function getVersionOfFileMaker(theFileMakerFolderitem as FolderItem) As Integer
  
  'check version of FileMaker
  
  if theFileMakerFolderitem = nil then Return 0
  dim theCFUrl as CFURLMBS = NewCFURLMBSFile(theFileMakerFolderitem)
  if theCFUrl = nil then Return 0
  dim theCFBundle as CFBundleMBS = CreateBundleMBS(theCFUrl)
  if theCFBundle = Nil then Return 0
  
  dim theVersion as String = st(theCFBundle.GetValueForInfoDictionaryKey(theCFBundle.kCFBundleVersionKey))
  Return val(theVersion.NthField(".", 1))
  
End Function

You can do this also with a Shell command.

Examples in Terminal follow.

This lists all installed versions for a bundle id, along with their paths:

mdfind "kMDItemCFBundleIdentifier == com.irradiatedsoftware.iClip" | while IFS= read -r path ; do echo "$path"; mdls -name kMDItemVersion "$path"; done

This gets the version of a particular app:

mdls -name kMDItemVersion /Applications/iClip.app

Beware: Both only works if Spotlight indexing is enabled on the app, though. So, it’s useful to get optional infos, e.g. for debugging and support, but an app should not rely on this, because some users turn off Spotlight.

1 Like

Thanks but these are single files that do not have a Version.plist or Info.plist.

it works with applications but not with other files (.bundle, etc.)

I should have called my post: How to get the version number of a file? (and not from an app). Sorry.

What kind of files do you mean? cmdline executables with embedded info_plist segments? Can you provide an example file?

Can the Finder display the version? Then the NSWorkspace functions should be the right way. Do you use the MBS plugins?

Thanks.
Sample File: “/Library/Apple/Library/Bundles/TCC_Compatibility.bundle” (but it could be any other file) - No info.plist on these files -
and yes, the Finder still shows the version.
I have MBS plugins (but without it’s even better)

That’s definitely a bundle that has an Info.plist


I tweaked @Beatrix_Willius ’ code a little bit and it’s working with TCC_Compatibility.bundle. Remember that you need permission to access some files.

Public Function BundleVersion(fTarget as FolderItem) As String
  // This function does not error trap nil objects because that's some failure you need to debug.
  var oCFURL as CFURLMBS = NewCFURLMBSFile(fTarget)
  
  if not oCFURL.IsPackage.Value then
    var ex as new UnsupportedFormatException
    ex.Message = fTarget.Name + " is not a bundle."
    raise ex
    
  end
  
  var oCFBundle as CFBundleMBS = CreateBundleMBS(oCFURL)
  
  var oValue as CFObjectMBS = oCFBundle.GetValueForInfoDictionaryKey(CFBundleMBS.kCFBundleVersionKey)
  if oValue isa CFStringMBS then
    var sVersion as String = CFStringMBS(oValue).DisplayString
    return sVersion
    
  end
End Function
1 Like

For completeness of this question, i.e. for getting the version of true single-file executables, I’ve posted the question and one answer on SO.

However, the otool -P /path/to/file command will only print the XML text of the plist. You’d still have to load that into a XMLDocument and then find the child with the “CFBundleShortVersionString” inside.

Oh - someone just pointed out the perfect answer in a comment of my question, see https://stackoverflow.com/a/13381340/43615

With MBS or a declare that should be doable.

Oh, and then there’s also another option how version numbers could be stored (and shown by Finder): In the classic Resource Fork. MBS plugins do that, for instance.

To get those versions via code, you’ll need code that can read the classic resource fork resources. Since Xojo for 64 bit does not offer these functions any more, I’ve made some code that works in 64 bit, some of it from the old MacOSLib.

Take this “MacResourceBrowser” project and see how it parses the contents of a resource fork - you’ll want to extract the “vers” resource.

Thank you for all these often complex suggestions. For me, when there is a version.plist file (or Info.plist) I do the simplest thing, i.e. this:

sh = newshell
sh.Execute("defaults read /Library/Apple/Library/Bundles/TCC_Compatibility.bundle/Contents/version.plist CFBundleShortVersionString")
msgbox(sh.result)

and it works fine 100% of the time.

and key ‘CFBundleVersion’ too.

There are types of bundles where the Info.plist is in a different place inside, but your code relies on a specific location. That’s not good. OTOH, the code shown by Beatrix and Tim will handle all these special cases.

You posted in “General”. The solutions posted in response are for Mac. As far as I know, there is no equivalent for Windows.