【问题标题】:How to retrieve an application's version string?如何检索应用程序的版本字符串?
【发布时间】:2014-11-09 14:13:23
【问题描述】:

使用 Mac OSX SDK,我编写了这个简单的测试应用程序来从正在运行的应用程序中提取版本字符串。

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 ] );
    }
}

但这不起作用,它会打印如下行:

pid 34 的版本:“(null)”

第二次尝试 如果我尝试通过将最后两行更改为来检索CFBundleVersion,我会更接近:

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

但现在版本是一个整数,比如 257633863,我想要像 1.23.0 这样的数字

【问题讨论】:

  • 从阅读您的最后一行开始,版本不应该保存为字符串吗?另外,你不能在常量头文件中定义一个版本字符串吗?并在每次更新时手动更改。 #define kVersion @"1.23.0" 并在您想要的任何地方调用“kversion”,只要您导入了文件。
  • 你检查过这篇文章吗?它适用于 iOS,但可能会提示您在 OS X 上做同样的事情。stackoverflow.com/questions/7608632/…
  • 关于您的代码的几点说明:您忘记了CFRelease(dictionary);(CoreFoundation 函数ProcessInformationCopyDictionary 的名称中有Copy,因此您拥有返回的引用)。你为什么要做那些const XY * 演员?我以前从未见过这个,所以我只是好奇原因。
  • @DarkDust 感谢您的评论!我来自 C/C++,所以const-ness 只是一种反射。
  • @Zil:我首先开始将它作为字符串检索,但我有一个运行时警告说“找不到 NSNumber 的选择器 UTF8String”(或类似的东西),所以我认为 CFDictionaryGetValue 正在返回一个 NSNumber

标签: objective-c macos osx-snow-leopard


【解决方案1】:

阅读捆绑包的Info.plist 字典可能更容易:

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);
}

【讨论】:

    【解决方案2】:

    您可以使用这样的方法来检查特定的应用版本。

    +(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;
    }
    

    请务必在用于商业软件之前对此进行测试。

    【讨论】:

      猜你喜欢
      • 2013-02-04
      • 1970-01-01
      • 2011-03-11
      • 2015-04-22
      • 2020-02-21
      • 2019-07-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多