How to read macOS desktop file in cocoa app - objective-c

I want to make cocoa app execute .sh file or other Operation,
this my code:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"%#",[self cmd:#"cd Desktop;ls;"]);
}
- (NSString *)cmd:(NSString *)cmd
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/bash"];
NSArray *arguments = [NSArray arrayWithObjects: #"-c", cmd, nil];
[task setArguments: arguments];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task launch];
NSData *data = [file readDataToEndOfFile];
return [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
}
but log error:
ls: .: Operation not permitted
how to do that?I search about macOS permit,Do I need use SMJobBless ?

Sandbox applications aren't allowed to read outside the application folder. So in order for your script to work you need to turn off Sandbox.
Also you need to change the path like Sangram S. mentioned or set the current directory to the home folder:
[task setCurrentDirectoryPath:NSHomeDirectory()];

change
NSLog(#"%#",[self cmd:#"cd Desktop;ls;"]);
with
NSLog(#"%#",[self cmd:#"cd ~/Desktop; ls;"]);

Related

Cocoa application - NSTask

How can I programmatically run terminal command?
Now I'm doing like this:
-(IBAction)proceedTapped:(id)sender
{
NSLog(#"%#",[self runCommand:#"cd ~"]);
NSLog(#"%#",[self runCommand:#"ls"]);
}
-(NSString *)runCommand:(NSString *)commandToRun
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:
#"-c" ,
[NSString stringWithFormat:#"%#", commandToRun],
nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output;
output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return output;
}
For single commands this code works well, but in my case, when I want to change directory
to ~(home) and then do 'ls' this doesn't work well (it looks like to run two commands in two different terminal windows).
So how to run multiple commands like in one terminal window ?
Thank you.
In one of my applications I have:-
- (IBAction)openDirInTerminal:(id)sender { // context only
DirectoryItem *item = (DirectoryItem *)[self.dirTree focusedItem];
NSString *s = [NSString stringWithFormat:
#"tell application \"Terminal\" to do script \"cd \'%#\'\"", item.fullPath];
NSAppleScript *as = [[NSAppleScript alloc] initWithSource: s];
[as executeAndReturnError:nil];
}
DirectoryItem *item = (DirectoryItem *)[self.dirTree focusedItem]; is my method, but replace item.fullPath with a Path.
You could add the 2nd command to the script string (followed by a newline).

How to run sudo command programmatically on OS X

I am trying to run sudo command programmatically in my OS X app,
but i got these message
sudo: no tty present and no askpass program specified
Here is my code:
NSString *runCommand(NSString *commandToRun)
{
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:#"-c" ,[NSString stringWithFormat:#"%#", commandToRun], nil];
NSLog(#"run command: %#",commandToRun);
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output;
output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return output;
}
And i call this method like this :
runCommand(#"sudo purge");
Thanks for any help or sugession.

Executing a command from Objective C

I want to execute a command from objective C (Cocoa framework). The command I am trying is as below. I tried with NSTask but it says "launch path not accessible" when I execute it.
sudo ifconfig en0 down
My code is:
- (void)testme {
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"sudo ifconfig en0 down"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"foo", #"bar.txt", nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"command returned:\n%#", string);
[string release];
[task release];
}
sudo ifconfig en0 down is not a sensible launch path. The correct launch path for this command would be /usr/sbin/sudo.
Once that is done, you still need to pass the correct arguments to setArguments:. foo and bar.txt look like example code that you copied without reading.
MORE IMPORTANTLY, THOUGH, running sudo from NSTask will not work. You will need to use Authorization Services to launch a privileged command.
You need to specify the full executable path and you should specify the arguments as the arguments, not along with the launch path. NSTask ain't a shell, it internally uses syscalls (execv(), I guess) to invoke the command.
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/sudo"];
NSArray *arguments = #[#"ifconfig", #"en0", #"down"];
[task setArguments:arguments];

NSTask and FFMpeg losing output

I'm trying to call ffmpeg from NSTask in objective-c. I execute the ffmpeg command in terminal and it works flawlessly every time. I make the same command using NSTask, and it never gives me the whole output. It cuts it off half way through the output, at a seemingly random spot every time. Here is my code.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSString* ffmpegPath = [[NSBundle mainBundle] pathForResource:#"ffmpeg" ofType:#""];
NSString* path = #"test.mov";
NSTask *task = [[NSTask alloc] init];
NSArray *arguments = [NSArray arrayWithObjects: #"-i", path, nil];
NSPipe *pipe = [NSPipe pipe];
NSFileHandle * read = [pipe fileHandleForReading];
[task setLaunchPath: ffmpegPath];
[task setArguments: arguments];
[task setStandardOutput: pipe];
[task launch];
[task waitUntilExit];
NSData* data = [read readDataToEndOfFile];
NSString* stringOutput = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", stringOutput);
NSLog(#"%i", [task terminationStatus]);
NSLog(#"DONE");
}
And just like that I figured it out. Apparently the output had non UTF8Characters in it. Switched it over to NSASCIIStringEncoding and voila. Magic.

Launching an Mac App with Objective-C/Cocoa

When launching Path Finder app with command line, I use open -a Path Finder.app /Users/.
Based on this idea, I use the following code to launch Path Finder.
Can I have launch app without using open command line?
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/usr/bin/open"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"-a", #"Path Finder.app", #"/Users/", nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
if(![[NSWorkspace sharedWorkspace] launchApplication:#"Path Finder"])
NSLog(#"Path Finder failed to launch");
With Parameters:
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:#"Path Finder"]];
//Handle url==nil
NSError *error = nil;
NSArray *arguments = [NSArray arrayWithObjects:#"Argument1", #"Argument2", nil];
[workspace launchApplicationAtURL:url options:0 configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error:&error];
//Handle error
You could also use NSTask to pass arguments:
NSTask *task = [[NSTask alloc] init];
NSBundle *bundle = [NSBundle bundleWithPath:[[NSWorkspace sharedWorkspace] fullPathForApplication:#"Path Finder"]]];
[task setLaunchPath:[bundle executablePath]];
NSArray *arguments = [NSArray arrayWithObjects:#"Argument1", #"Argument2", nil];
[task setArguments:arguments];
[task launch];
Based on yuji's answer in different posting, NSWorkspace is the tool to use, and I could get the same result with only two lines of code.
The openFile can be used for passing the parameter to Path Finder, which is normally the directory, not a file. However, it works fine.
[[NSWorkspace sharedWorkspace] openFile:string2 withApplication:#"Path Finder"];
[[NSApplication sharedApplication] terminate:nil];