qdii
qdii

Reputation: 12963

How to retrieve an application's version string?

Using the Mac OSX SDK, I wrote this simple test application to extract the version string from running applications.

int main()
{
    NSWorkspace * ws = [NSWorkspace sharedWorkspace];
    NSArray * apps = [ws runningApplications];
    NSUInteger max= [apps count];
    for (NSUInteger i = 0; i < max; i++)
    {
        NSRunningApplication *app = [apps objectAtIndex: i];
        pid_t pid = [ app processIdentifier ];
        ProcessSerialNumber psn = { kNoProcess, kNoProcess };

        if ( GetProcessForPID(pid, &psn) != noErr )
            continue;

        CFDictionaryRef dictionary 
            = ProcessInformationCopyDictionary(&psn, kProcessDictionaryIncludeAllInformationMask);

        const NSString * version 
            = reinterpret_cast<const NSString*>(CFDictionaryGetValue( dictionary, CFSTR("CFBundleShortVersionString") ));

        printf( "version for pid %d: \"%s\"\n", pid, [ version UTF8String ] );
    }
}

but this does not work, it prints lines like:

version for pid 34: "(null)"

SECOND TRY I get a bit closer if I try retrieving CFBundleVersion by changing the two last lines to:

 const NSNumber * version
     = reinterpret_cast<const NSNumber *>(CFDictionaryGetValue( dictionary, CFSTR("CFBundleVersion") ));
 printf( "version for pid %d: \"%s\"\n", pid, [ [ version stringValue ] UTF8String ] );

but now the version is an integer, like 257633863, and I would like something like 1.23.0

Upvotes: 1

Views: 1572

Answers (2)

Arius Kahn
Arius Kahn

Reputation: 221

You can use a method like this to check for a specific app version.

+(BOOL) isCorrectApp:(NSString*) appIdentifier forVersion: (NSString*) appVersion {
    NSWorkspace *ws = [NSWorkspace sharedWorkspace];
    NSArray *apps = [ws runningApplications];
    for (NSRunningApplication *app in apps)
    {
        NSBundle *bundle = [NSBundle bundleWithURL:[app bundleURL]];
        NSDictionary *info = [bundle infoDictionary];

        NSString *identifier = info[@"CFBundleIdentifier"];
        if ([identifier containsString:appIdentifier]) { // appIdentifier is com.apple.iTunesHelper or such

            NSString *name = info[@"CFBundleName"];
            NSString *version = info[@"CFBundleVersion"];
            NSString *shortVersion = info[@"CFBundleShortVersionString"];
            if ([version hasPrefix:appVersion]) {
                NSLog(@"Name: %@, Identifier: %@, Version: %@ (%@)", name, identifier, version, shortVersion);
            } else {
                // NSLog(@"Waiting for the right version.");
                return false;
            }
        }
    }
    return true;
}

Please be sure to test this before using in commercial software.

Upvotes: 1

DarkDust
DarkDust

Reputation: 92345

It's probably easier to just read the bundle's Info.plist dictionary:

NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSArray *apps = [ws runningApplications];
for (NSRunningApplication *app in apps)
{
    pid_t pid = [app processIdentifier ];
    NSBundle *bundle = [NSBundle bundleWithURL:[app bundleURL]];
    NSDictionary *info = [bundle infoDictionary];

    NSString *name = info[@"CFBundleName"];
    NSString *identifier = info[@"CFBundleIdentifier"];
    NSString *version = info[@"CFBundleVersion"];
    NSString *shortVersion = info[@"CFBundleShortVersionString"];
    NSLog(@"PID: %ld, Name: %@, Identifier: %@, Version: %@ (%@)", (long)pid, name, identifier, version, shortVersion);
}

Upvotes: 1

Related Questions