swift - 如何获取 NSRunningApplication 的参数?

标签 swift macos cocoa

如何获取 NSRunningApplication 启动期间使用的参数列表,类似于我运行 ps aux 时看到的参数列表:

let workspace = NSWorkspace.shared
let applications = workspace.runningApplications

for application in applications {
    // how do I get arguments that were used during application launch?
}

最佳答案

“ps”工具使用 sysctl()KERN_PROCARGS2 来获取正在运行的进程的参数。以下是尝试翻译 adv_cmds-153/ps/print.c 中的代码到 swift 。该文件还包含原始参数空间的内存布局的文档,并解释了如何在该内存中定位字符串参数。

func processArguments(pid: pid_t) -> [String]? {
    
    // Determine space for arguments:
    var name : [CInt] = [ CTL_KERN, KERN_PROCARGS2, pid ]
    var length: size_t = 0
    if sysctl(&name, CUnsignedInt(name.count), nil, &length, nil, 0) == -1 {
        return nil
    }
    
    // Get raw arguments:
    var buffer = [CChar](repeating: 0, count: length)
    if sysctl(&name, CUnsignedInt(name.count), &buffer, &length, nil, 0) == -1 {
        return nil
    }
    
    // There should be at least the space for the argument count:
    var argc : CInt = 0
    if length < MemoryLayout.size(ofValue: argc) {
        return nil
    }
    
    var argv: [String] = []
    
    buffer.withUnsafeBufferPointer { bp in
        
        // Get argc:
        memcpy(&argc, bp.baseAddress, MemoryLayout.size(ofValue: argc))
        var pos = MemoryLayout.size(ofValue: argc)
        
        // Skip the saved exec_path.
        while pos < bp.count && bp[pos] != 0 {
            pos += 1
        }
        if pos == bp.count {
            return
        }
        
        // Skip trailing '\0' characters.
        while pos < bp.count && bp[pos] == 0 {
            pos += 1
        }
        if pos == bp.count {
            return
        }
        
        // Iterate through the '\0'-terminated strings.
        for _ in 0..<argc {
            let start = bp.baseAddress! + pos
            while pos < bp.count && bp[pos] != 0 {
                pos += 1
            }
            if pos == bp.count {
                return
            }
            argv.append(String(cString: start))
            pos += 1
        }
    }
    
    return argv.count == argc ? argv : nil
}

只有一个简单的错误处理:如果出现任何问题,函数将返回nil

对于 NSRunningApplication 的实例,您可以调用

processArguments(pid: application.processIdentifier)

关于swift - 如何获取 NSRunningApplication 的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72443976/

相关文章:

macos - 更改系统代理并一劳永逸地授权

ios - URLSession 最佳实践 - 多个请求

objective-c - 错误 : ‘NSString’ undeclared (first use in this function)

macos - 如何在同一个 Mac 窗口中显示一个新的 View Controller ?

iphone - 以编程方式设置(系统范围)代理设置?

Swift 如何监听 AWS DynamoDB 中的更改

ios - 如何在 iOS swift 4 中进行名字验证?

ios - 使用滚动(手势)重新加载 CollectionView

arrays - 二维数组中的单个元素的数学运算 - Swift

xcode - 如何折叠 Xcode 问题导航器中的所有问题