-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProcessAdditions.swift
More file actions
94 lines (86 loc) · 3.05 KB
/
ProcessAdditions.swift
File metadata and controls
94 lines (86 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//
// ProcessAdditions.swift
// Caffeinator
//
// Created by aaplmath on 8/8/18.
// Copyright © 2018 aaplmath. All rights reserved.
//
import Cocoa
/// Attempts to get the name of a process using NSWorkspace and libproc
func getNameByPID(_ pid: pid_t) -> String? {
return getRunningAppName(for: pid) ?? getLibProcName(for: pid) ?? getLibProcPathEnd(for: pid)
}
/// Gets the name of a process by its PID using NSRunningApplication
func getRunningAppName(for pid: pid_t) -> String? {
return NSRunningApplication(processIdentifier: pid)?.localizedName
}
/// Gets the name of a process by its PID using libproc
func getLibProcName(for pid: pid_t) -> String? {
if pid == 0 {
return "kernel_task"
}
let nameBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(MAXPATHLEN))
defer {
nameBuffer.deallocate()
}
let nameLength = proc_name(pid, nameBuffer, UInt32(MAXPATHLEN))
if nameLength > 0 {
return String(cString: nameBuffer)
} else {
return nil
}
}
/// Gets the last component of the path of a process by its PID using libproc
func getLibProcPathEnd(for pid: pid_t) -> String? {
let pathBuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: Int(MAXPATHLEN))
defer {
pathBuffer.deallocate()
}
let pathLength = proc_pidpath(pid, pathBuffer, UInt32(MAXPATHLEN))
if pathLength > 0 {
let fullPath = String(cString: pathBuffer)
let sliceStart: String.Index
if let lastSeparatorLoc = fullPath.lastIndex(of: "/"), lastSeparatorLoc < fullPath.index(before: fullPath.endIndex) {
sliceStart = fullPath.index(after: lastSeparatorLoc)
} else {
sliceStart = fullPath.startIndex
}
let lastComponent = fullPath[sliceStart...]
return String(lastComponent)
} else {
return nil
}
}
extension Process {
convenience init(_ executablePath: String, _ arguments: String...) {
self.init()
self.launchPath = executablePath
self.arguments = arguments
self.standardOutput = FileHandle.nullDevice
self.standardError = FileHandle.nullDevice
}
convenience init(_ executablePath: String, withArguments arguments: [String]) {
self.init()
self.launchPath = executablePath
self.arguments = arguments
self.standardOutput = FileHandle.nullDevice
self.standardError = FileHandle.nullDevice
}
func run(synchronously: Bool, terminationHandler: ((Process) -> Void)?) {
if let handler = terminationHandler {
self.terminationHandler = handler
}
if #available(macOS 10.13, *) {
do {
try self.run()
} catch let err {
Notifier.showErrorMessage(withTitle: txt("PA.execution-error-title"), text: String(format: txt("PA.execution-error-msg"), launchPath ?? "PA.unknown-process-path", err.localizedDescription))
}
} else {
self.launch()
}
if synchronously {
self.waitUntilExit()
}
}
}