如何获取 NSRunningApplication 的参数?
How to get arguments of NSRunningApplication?
如何获取 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。该文件还包含原始参数的内存布局文档 space 并解释了如何在该内存中定位字符串参数。
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 '[=10=]' characters.
while pos < bp.count && bp[pos] == 0 {
pos += 1
}
if pos == bp.count {
return
}
// Iterate through the '[=10=]'-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
}
只有一个简单的错误处理:如果出现任何错误,函数 returns nil
.
对于 NSRunningApplication
的实例,您可以调用
processArguments(pid: application.processIdentifier)
如何获取 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。该文件还包含原始参数的内存布局文档 space 并解释了如何在该内存中定位字符串参数。
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 '[=10=]' characters.
while pos < bp.count && bp[pos] == 0 {
pos += 1
}
if pos == bp.count {
return
}
// Iterate through the '[=10=]'-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
}
只有一个简单的错误处理:如果出现任何错误,函数 returns nil
.
对于 NSRunningApplication
的实例,您可以调用
processArguments(pid: application.processIdentifier)