我有一个应用程序,旨在在沙盒和非沙盒的MacOS上运行。 如果用户从MacOS 10.6升级到更高版本的操作系统,则需要用户重新选择文件夹,以便我可以使用安全书签来标记它们。
如何检测我的应用程序是否在支持沙盒的操作系统上运行?
我知道的唯一方法是查找APP_SANDBOX_CONTAINER_ID
环境变量。只有当应用程序在沙盒容器内运行时,它才存在。
NSDictionary* environ = [[NSProcessInfo processInfo] environment];
BOOL inSandbox = (nil != [environ objectForKey:@"APP_SANDBOX_CONTAINER_ID"]);
BOOL isSandboxed = NO;
SecStaticCodeRef staticCode = NULL;
NSURL *bundleURL = [[NSBundle mainBundle] bundleURL];
if (SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleURL, kSecCSDefaultFlags, &staticCode) == errSecSuccess) {
if (SecStaticCodeCheckValidityWithErrors(staticCode, kSecCSBasicValidateOnly, NULL, NULL) == errSecSuccess) {
SecRequirementRef sandboxRequirement;
if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"), kSecCSDefaultFlags,
&sandboxRequirement) == errSecSuccess)
{
OSStatus codeCheckResult = SecStaticCodeCheckValidityWithErrors(staticCode, kSecCSBasicValidateOnly, sandboxRequirement, NULL);
if (codeCheckResult == errSecSuccess) {
isSandboxed = YES;
}
}
}
CFRelease(staticCode);
}
测试Swift3
func isSandboxed() -> Bool {
let bundleURL = Bundle.main.bundleURL
var staticCode:SecStaticCode?
var isSandboxed:Bool = false
let kSecCSDefaultFlags:SecCSFlags = SecCSFlags(rawValue: SecCSFlags.RawValue(0))
if SecStaticCodeCreateWithPath(bundleURL as CFURL, kSecCSDefaultFlags, &staticCode) == errSecSuccess {
if SecStaticCodeCheckValidityWithErrors(staticCode!, SecCSFlags(rawValue: kSecCSBasicValidateOnly), nil, nil) == errSecSuccess {
let appSandbox = "entitlement[\"com.apple.security.app-sandbox\"] exists"
var sandboxRequirement:SecRequirement?
if SecRequirementCreateWithString(appSandbox as CFString, kSecCSDefaultFlags, &sandboxRequirement) == errSecSuccess {
let codeCheckResult:OSStatus = SecStaticCodeCheckValidityWithErrors(staticCode!, SecCSFlags(rawValue: kSecCSBasicValidateOnly), sandboxRequirement, nil)
if (codeCheckResult == errSecSuccess) {
isSandboxed = true
}
}
}
}
return isSandboxed
}
以下是 Swift 4.2 中 @hamstergene 的答案:
func isSandboxEnvironment() -> Bool {
let environ = ProcessInfo.processInfo.environment
return (nil != environ["APP_SANDBOX_CONTAINER_ID"])
}
import Security
extension Bundle {
var isSandboxed: Bool {
let defaultFlags: SecCSFlags = .init(rawValue: 0)
var staticCode: SecStaticCode? = nil
if SecStaticCodeCreateWithPath(self.bundleURL as CFURL, defaultFlags, &staticCode) == errSecSuccess {
if SecStaticCodeCheckValidityWithErrors(staticCode!, SecCSFlags(rawValue: kSecCSBasicValidateOnly), nil, nil) == errSecSuccess {
let requirementText = "entitlement[\"com.apple.security.app-sandbox\"] exists" as CFString
var sandboxRequirement: SecRequirement?
if SecRequirementCreateWithString(requirementText, defaultFlags, &sandboxRequirement) == errSecSuccess {
if SecStaticCodeCheckValidityWithErrors(staticCode!, defaultFlags, sandboxRequirement, nil) == errSecSuccess {
return true
}
}
}
}
return false
}
}
使用方法:
isSandboxed = Bundle.main.isSandboxed