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.
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
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.