使用 Qt、c、c++ 检索 OS X 版本

Retrieving OS X version using Qt, c, c++

提问人:fyngyrz 提问时间:1/17/2018 最后编辑:fyngyrz 更新时间:1/17/2018 访问量:1150

问:

Build Environment: 、
Run Environment: through 和更高版本
QT 4.7OS X 10.6OS X 10.6OS X 10.13Windows XP

我正在使用一个非常大的、高度图形密集型的 QT 应用程序。我需要找出我运行的 / 的版本 - 10.6...10.10... 10.12 等OS XMacOS

我正在 OS X 中寻找可以实时调用的 cc++ 函数;这是一个运行时问题。它需要从 10.6 开始工作。我是用 c++ 编写的,所以我可以像 c++ 一样方便地使用 c 解决方案。

我有这个:

#ifdef Q_OS_WIN
    QApplication::setGraphicsSystem("raster");
#else
    QApplication::setGraphicsSystem("native");
#endif

以上内容可以确定我正在构建的是 Windows 还是 OS X。在上面的片段中,我需要做一些进一步的检查;我不需要“原生”图形系统,除非 ,其中 QT“光栅”系统有问题。我更喜欢“光栅”系统,因为它要快得多,但后来的机器也更快,所以如果我只能在运行最新操作系统的现代机器上调用“本机”系统,那应该会奏效。elseOS X 10.12

我有大量用户在早期版本的 OS X 下运行,因此这里使用的任何内容都必须足够通用,以便在所有版本的 OS 10.6 及更高版本上运行。QT 4.7 本身似乎对它没有明确知道的操作系统版本一无所知;使用 ,它只报告“未知的操作系统版本”。QSysInfo::MacVersion

理想情况下,我想象以下形式:

int v = majorOSRevision();
int r = minorOSRevision();
int s = stepOSRevision();

OS X API 中是否有如此直接、简单的调用?

C++ C macOS、 Qt 、OSX-Snow-Leopard

评论

0赞 fyngyrz 1/17/2018
@Pablo......嗯。我无法判断你是在拖钓还是只是困惑。无论如何,答案是肯定的。我通常是用 C++ 编写的。当然,我可以随时回退到 c,所以我可以使用任何一种方法。这回答了你的问题吗?
0赞 Macmade 1/17/2018
没有时间写一个正确的答案。搜索格式塔...
0赞 fyngyrz 1/17/2018
格式塔已从 10.8 开始被弃用,所以我担心使用它
0赞 Eljay 1/17/2018
stackoverflow.com/questions/11072804/ 的傻瓜......如果您需要回到 10.6,则必须使用新旧组合。
0赞 JWWalker 1/17/2018
我不认为有一种方法可以不被弃用,但又可以回到OS 10.6。当然,弃用并不意味着它肯定会很快消失。格式塔仍在 10.13 SDK 中。

答:

3赞 p-a-o-l-o 1/17/2018 #1

您可以执行类似 sw_vers 的命令并读取其输出。

示例代码,使用:QProcess

osxversion.h

#ifndef OSXVERSION_H
#define OSXVERSION_H

#include <QProcess>

class OSXVersion : public QProcess
{
    Q_OBJECT

    int majr;
    int minr;
    int step;

    OSXVersion();

public:

    int majorOSRevision() const { return majr; }
    int minorOSRevision() const { return minr; }
    int stepOSRevision() const { return step; }

    static OSXVersion * getVersion();

private slots:
    void dataReady();
};

#endif // OSXVERSION_H

osxversion.cpp

#include "osxversion.h"

OSXVersion::OSXVersion() : QProcess(0)
{
    majr = 0;
    minr = 0;
    step = 0;
    connect(this, SIGNAL(readyRead()), this, SLOT(dataReady()));
}

OSXVersion * OSXVersion::getVersion()
{
    OSXVersion * v = new OSXVersion();
    v->start("sw_vers -productName");
    v->waitForFinished();
    return v;
}

void OSXVersion::dataReady()
{
    int * v[3] = {&majr, &minr, &step};

    QByteArray data = readAll();
    QList<QByteArray> tokens =  data.split(':');
    tokens = tokens[tokens.size() - 1].split('.');
    for(int i=0; i<tokens.size(); i++)
    {
        *(v[i]) = QString(tokens[i]).toInt();
    }
}

main.cpp

#include <QCoreApplication>
#include <QDebug>

#include "osxversion.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    OSXVersion * version = OSXVersion::getVersion();

    qDebug() << "OSX Version: "
             << version->majorOSRevision()
             << "."
             << version->minorOSRevision()
             << "."
             << version->stepOSRevision();

    delete version;

    return a.exec();
}

评论

0赞 fyngyrz 1/17/2018
感谢您指出sw_vers;它完全符合我的需要,它从 10.6.8 到 10.12.6 工作,完美。愚蠢的是,他们从第一天起就没有在系统 API 中拥有这种能力,但哦,好吧。对于未来的读者,我能够使用OS X的主要,次要和修订级别。我把它当作一个简单的用法,用 、 、 ,然后解析结果而不是上面的,但想法是一样的。sw_vers -productVersionQString params="-productVersion"QProcess pp.start("sw_vers", params)p.waitForFinished(-1)QString p_stdout = p.readAll()
1赞 TheDarkKnight 1/17/2018 #2

OS X / macOS 始终将其产品信息存储在一个明确的 plist 文件中,该文件位于 /System/Library/CoreServices/SystemVersion.plist

如果我们在High Sierra上查看此文件,我们可以看到以下内容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ProductBuildVersion</key>
    <string>17C205</string>
    <key>ProductCopyright</key>
    <string>1983-2018 Apple Inc.</string>
    <key>ProductName</key>
    <string>Mac OS X</string>
    <key>ProductUserVisibleVersion</key>
    <string>10.13.2</string>
    <key>ProductVersion</key>
    <string>10.13.2</string>
</dict>
</plist>

由于它是一个 plist,因此根据给定的键使用 Qt 读取任何值QSettings

#include <QSettings>
QString getSysVersion()
{
    QSettings settings("/System/Library/CoreServices/SystemVersion.plist", QSettings::NativeFormat);
    return settings.value("ProductUserVisibleVersion").toString();
}

现在我们有了版本,我们可以获取主要、次要和构建组件QString

QString version = getSysVersion();
QStringList components = version.split(".");
int maj = components[0].toInt();
int min = components[1].toInt();
int build = components[2].toInt();