NSTask launchPath not working - macos

I have a NSOpenPanel where the user choses a directory and I'm trying to run an NSTask but the launchPath isn't working.
Here's my code:
#IBAction func choseFile(sender: AnyObject) {
var panel = NSOpenPanel()
panel.canChooseFiles = false
panel.canChooseDirectories = true
panel.allowsMultipleSelection = false
panel.beginWithCompletionHandler { (result) -> Void in
if result == NSFileHandlingPanelOKButton {
var path : String = panel.URL!.absoluteString as String!
var filePath = path.stringByReplacingOccurrencesOfString("file://", withString: "", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
let task = NSTask()
task.launchPath = filePath
task.arguments = ["ls"]
task.launch()
task.waitUntilExit()
}
}
}
Thanks :)

The launchPath of an NSTask is the path to the program to run, not the working directory.
I assume, since you set the arguments to be ls, that you want to run the ls command in a particular directory. In that case, you want to set the launchPath to "/bin/ls" and the arguments to [panel.URL!.path].

Related

How to get top output with swift 3 on osx (NOT iOS)

// Playground
import Foundation
let task = Process()
task.launchPath = "/usr/bin/top"
task.arguments = ["-s","2"]
let pipe = Pipe()
task.standardOutput = pipe
task.launch()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
task.waitUntilExit()
print(String(data: data, encoding: String.Encoding.utf8)!)
This code work with "/bin/ls" instead of "/usr/bin/top" and when i put others argument but like it is actualy i get nothing on playground and it crach in my xcode8 project with an "An uncaught exception was raised" and it lunch a debuger with asm.So how to get TOP output in a variable ?
Found
// Playground
import Foundation
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
let task = Process()
task.launchPath = "/usr/bin/top"
task.arguments = ["-s","9"]
let pipe = Pipe()
task.standardOutput = pipe
let outHandle = pipe.fileHandleForReading
outHandle.readabilityHandler = { pipe in
if let line = String(data: pipe.availableData, encoding: String.Encoding.utf8) {
// Update your view with the new text here
print("New ouput: \(line)")
} else {
print("Error decoding data: \(pipe.availableData)")
}
}
task.launch()

Root Privilegs for NSTask in Swift

I searched a lot on the web to find a simple way to get root privileges in my NSTask but I only found old articles which are written in Objective-C. But my Xcode Project is written in Swift :x is there a way to solve this problem to run a NSTask with Root Privilegs? :) I know I have to use something like AppleScript, STPrivilegedTask or the BetterAuthorizationSample from Apple but all I've found is written in Objective-C...
My Idea is to create a application that makes a storage media bootable with the command createinstallmedia :p all works perfectly the only problem is that the command wants root privileges, for testing I simply open my Terminal and login as Root but this is not the greatest solution for this Problem :D so please help me! :o
My Code the only thing that miss is the code to get root access:
import Cocoa
class ViewController: NSViewController {
var Task = NSTask()
var openPanel = NSOpenPanel()
var workingpath_createinstallmedia : String!
var workingpath_medium : String!
var workingpath_application : String!
var volume_flag = "--volume"
var applicationpath_flag = "--applicationpath"
var nointeraction_flag = "--nointeraction"
var commandpath : String!
var postcommand : [String]!
var DirectoryOS : NSURL!
var DirectoryMedium : NSURL!
#IBOutlet weak var PathControlOS: NSPathControl!
#IBOutlet weak var PathControlMedium: NSPathControl!
#IBOutlet weak var Outputlabel: NSTextField!
#IBAction func OSauswählen(sender: AnyObject) {
openPanel.canChooseDirectories = false
openPanel.canChooseFiles = true
openPanel.canCreateDirectories = false
openPanel.allowsMultipleSelection = false
if openPanel.runModal() == NSModalResponseOK {
DirectoryOS = openPanel.URLs[0] as NSURL
PathControlOS.objectValue = DirectoryOS
}
}
#IBAction func Mediumauswählen(sender: AnyObject) {
openPanel.canChooseDirectories = true
openPanel.canChooseFiles = false
openPanel.canCreateDirectories = false
openPanel.allowsMultipleSelection = false
if openPanel.runModal() == NSModalResponseOK {
DirectoryMedium = openPanel.URLs[0] as NSURL
PathControlMedium.objectValue = DirectoryMedium
}
}
#IBAction func starttask(sender: AnyObject) {
// edit Strings
// Createinstallmedia
workingpath_createinstallmedia = String(DirectoryOS)
workingpath_createinstallmedia = workingpath_createinstallmedia.stringByReplacingOccurrencesOfString("file://", withString: "")
workingpath_application = workingpath_createinstallmedia.stringByReplacingOccurrencesOfString("%20", withString: " ")
workingpath_createinstallmedia = workingpath_application + "/Contents/Resources/createinstallmedia"
// Medium
workingpath_medium = String(DirectoryMedium)
workingpath_medium = workingpath_medium.stringByReplacingOccurrencesOfString("file://", withString: "")
workingpath_medium = workingpath_medium.stringByReplacingOccurrencesOfString("%20", withString: " ")
// config Task Parameters
commandpath = workingpath_createinstallmedia
postcommand = [volume_flag,workingpath_medium,applicationpath_flag,workingpath_application,nointeraction_flag]
// commit the Parameters to the Task
Task.launchPath = commandpath
Task.arguments = postcommand
// start Task
Task.launch()
Task.waitUntilExit()
}
}
Thanks for your help!!!
I solved using sudo into the command and asking to the user for the password to give directly to the sudo, in the following way:
echo "passwordhere" | sudo -S command --arguments
and doing this using the sh shell executable to run the process, using this method i successfully created an app to create bootable mac os install media called TINU, but you need to be careful while dealing with user password, i chose to make my app open source to let others know what it does with this kinds of tasks that needs user password, but on mac os you should create specialized programs that does this kind of privileged tasks and then start them using system apis that will manage authentication for you and let the specialized program to do his job.

Swift error: launch path not accessible

I'm doing a simple OSX App to show/hide hidden files in the Finder from a StatuBar menu.
This is the IBAction to show/hide files:
#IBAction func menuClicked(sender: NSMenuItem) {
let task = NSTask()
task.currentDirectoryPath = "/var/tmp/"
task.launchPath = "usr/bin/defaults"
if(sender.state == NSOnState){
sender.state = NSOffState
task.arguments = ["write", "com.apple.finder", "AppleShowAllFiles", "NO"]
}else{
sender.state = NSOnState
task.arguments = ["write", "com.apple.finder", "AppleShowAllFiles", "YES"]
}
task.launch()
task.waitUntilExit()
let killTask = NSTask()
killTask.launchPath = "usr/bin/killall"
killTask.arguments = ["Finder"]
killTask.launch()
}
This gives me this error:
2015-05-10 23:54:22.237 ShowHideFiles[1234:303] An uncaught exception was raised
2015-05-10 23:54:22.238 ShowHideFiles[1234:303] launch path not accessible
I tried to find out why but cannot find an answer.
I tried also to see which of the two launchPath was wrong by disabling one or the other and they both give the same error.
Can somebody help me?
Both var and usr are at the same level, so you need to prefix usr with / like you did for var:
task.currentDirectoryPath = "/var/tmp/"
task.launchPath = "/usr/bin/defaults"
killTask.launchPath = "/usr/bin/killall"

Cocoa/Swift: Loop through names of folder in path

I'm currently programming an os x application with swift, but I can't figure how to loop through or even get the names of all folders at a certain path. Maybe something with fm.enumeratorAtPath?
I use enumeratorAtURL. Here's some code that shows an example of how to print the directories in the user's home directory.
if let dirURL = NSURL(fileURLWithPath: NSHomeDirectory()) {
let keys = [NSURLIsDirectoryKey, NSURLLocalizedNameKey]
let fileManager = NSFileManager.defaultManager()
let enumerator = fileManager.enumeratorAtURL(
dirURL,
includingPropertiesForKeys: keys,
options: (NSDirectoryEnumerationOptions.SkipsPackageDescendants |
NSDirectoryEnumerationOptions.SkipsSubdirectoryDescendants |
NSDirectoryEnumerationOptions.SkipsHiddenFiles),
errorHandler: {(url, error) -> Bool in
return true
}
)
while let element = enumerator?.nextObject() as? NSURL {
var getter: AnyObject?
element.getResourceValue(&getter, forKey: NSURLIsDirectoryKey, error: nil)
let isDirectory = getter! as Bool
element.getResourceValue(&getter, forKey: NSURLLocalizedNameKey, error: nil)
let itemName = getter! as String
if isDirectory {
println("\(itemName) is a directory in \(dirURL.absoluteString)")
//do something with element here.
}
}
}

AVRecorder and AVPlayer in swift

All ,
I need to create a sample audio player and recorder, its not erroring but its not playing and perhaps not recording.. any ideas ?
#IBAction func Play(AnyObject)
{
println ("Play")
let path = NSBundle.mainBundle().pathForResource("171010", ofType:"m4a")
let fileURL = NSURL(fileURLWithPath: path)
player = AVAudioPlayer(contentsOfURL: outputFileURL, error: nil)
player.prepareToPlay()
player.delegate = self
player.play()
}
#IBAction func Record(AnyObject)
{
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
settings.setValue(kAudioFormatMPEG4AAC, forKey: AVFormatIDKey)
settings.setValue(44100.0, forKey: AVSampleRateKey)
settings.setValue(2, forKey: AVNumberOfChannelsKey)
recorder = AVAudioRecorder(URL: outputFileURL, settings: settings, error: &error)
recorder.delegate = self;
recorder.prepareToRecord()
recorder.record()
}
#IBAction func Stop(AnyObject)
{
recorder.stop()
println("Stop")
}
and the globals at the top are :
class MainMenu: UIViewController , AVAudioRecorderDelegate , AVAudioPlayerDelegate {
var filename: String!
var outputFileURL: NSURL!
var recorder: AVAudioRecorder!
var error: NSError?
var settings: NSMutableDictionary = NSMutableDictionary()
var player : AVAudioPlayer! = nil
Any ideas ? I don't know if its recording and creating the file. As I am getting URL is nill on the playing function. This is wired up to a storyboard with buttons. Any help within this simple stuff in swift would be brilliant.
I have changed it to this and this should work ? Can anyone advise ?
#IBAction func Play(AnyObject)
{
println ("Play")
var audioPlayer = AVAudioPlayer()
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
audioPlayer = AVAudioPlayer(contentsOfURL: outputFileURL, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.delegate = self
audioPlayer.play()
}
#IBAction func Record(AnyObject)
{
filename = "171010.m4a"
let paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var pathComponents = [paths.lastObject as String, filename as String]
outputFileURL = NSURL.fileURLWithPathComponents(pathComponents)
settings.setValue(kAudioFormatMPEG4AAC, forKey: AVFormatIDKey)
settings.setValue(44100.0, forKey: AVSampleRateKey)
settings.setValue(2, forKey: AVNumberOfChannelsKey)
recorder = AVAudioRecorder(URL: outputFileURL, settings: settings, error: &error)
recorder.delegate = self;
recorder.prepareToRecord()
recorder.record()
}
The player needs to be an ivar so it isn't popped off the stack before playing.
Here is a github project with a functioning recorder if you need more info.
Also, the convention is to start function names with a lowercase character.

Resources