Using below code, I am getting this error:
NSTask: Task create for path '/Users/media/Library/Developer/Xcode/DerivedData/Manager-gnixeptcszdoubbnfcncumzypwge/Build/Products/Debug/lib' failed: 22, "Invalid argument". Terminating temporary process.
I am not getting whats the issue behind this.
- (void)startProcessingVideo {
NSLog(#"Processing Video Low Resolution");
NSTimeInterval timeStamp = [[NSDate date] timeIntervalSince1970];
// NSTimeInterval is defined as double
NSNumber *timeStampObj = [NSNumber numberWithInt:timeStamp];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterNoStyle];
NSString *convertNumber = [formatter stringForObjectValue:timeStampObj];
NSLog(#"timeStampObj:: %#", convertNumber);
NSString *fileNameNumber = [convertNumber stringByAppendingString:[self genRandStringLength:8]];
NSLog(#"fileNameNumber:::: %#", fileNameNumber);
NSString *aString = [[NSString stringWithFormat:#"%#%#%#", thumbnailDirPath,#"/Mobile" ,fileNameNumber] retain];
//NSString *string = [aString stringByAppendingString:#"_H"];
fileNameMP4Mobile = [aString stringByAppendingString:#".mp4"];
NSLog(#"string:::: %#", aString);
[lblMessage setStringValue:#"Started!"];
NSTask *task= [NSTask new];
[task setLaunchPath:ffmpegPresetLaunchPath];
[task setArguments:[NSArray arrayWithObjects:
#"-y",
#"-i",
inputFilePath,// #"1.wmv",
#"-vcodec",
#"libx264",
#"-fpre",
#"libx264-fast.ffpreset",
#"-b",
#"500k",
#"-s",
#"640*480",
#"-r",
#"30",
#"-aspect",
#"16:9",
#"-ab",
#"128k",
#"-ac",
#"2",
#"-ar",
#"44100",
fileNameMP4Mobile,nil]];
[task setCurrentDirectoryPath:thumbnailDirPath];
NSPipe *outputPipe = [NSPipe pipe];
[task setStandardInput:[NSPipe pipe]];
[task setStandardOutput:outputPipe];
[task launch];
[task waitUntilExit];
[task release];
NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile];
NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease];
[lblMessage setStringValue:#"Video Generated!"];
[self startProcessingVideoHighResolution];
}
value for ffmpegPresetLaunchPath is:
ffmpegPresetLaunchPath = [[NSString stringWithFormat:#"%#%#", currentDir, #"/lib/"] retain];
Value in NSLOG:
ffmpegPresetLaunchPath::: /Users/media/Library/Developer/Xcode/DerivedData/FileManager-gnixeptcszdoubbnfcncumzypwge/Build/Products/Debug/lib/
Please help resolving this issue.
You are not providing the correct file to execute; you are passing its path (presumably).
You probably need something like:
ffmpegPresetLaunchPath = [[NSString stringWithFormat:#"%#%#", currentDir, #"/lib/ffmpeg"] retain];
Note: It's clear than error 22 is the errno value EINVAL, however there is no reference to it on the exec() manpage or execve() manpage., so I don't know how you're expected to determine the cause from just the error code.
Related
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).
I am new developing with Objective-C and Cocoa.
I need to run/stop/restart Apache and Mysql from a Xcode/Cocoa App and I don't know which is the best practise: Using NSTask, using NSAppleScript or what should be used?
Anyway I think that I need admin privileges for that.
Maybe somebody can help me how or where to get starting with this using best practices.
Below it's little of what I already tried:
I also saw this tutorial: http://www.michaelvobrien.com/blog/2009/07/authorizationexecutewithprivileges-a-simple-example/ but the AuthorizationExecuteWithPrivileges method is deprecated from OS 10.6.
I tried several methods that I find on stackoverflow.com but without any result.
One of the ways I tried is with the following method that I have in a TasksController class:
- (BOOL) runProcessAsAdministrator:(NSString*)scriptPath
withArguments:(NSArray *)arguments
output:(NSString **)output
errorDescription:(NSString **)errorDescription {
NSLog(#"runProcessAsAdministrator called!");
NSString * allArgs = [arguments componentsJoinedByString:#" "];
NSString * fullScript = [NSString stringWithFormat:#"%# %#", scriptPath, allArgs];
NSDictionary *errorInfo = [NSDictionary new];
NSString *script = [NSString stringWithFormat:#"do shell script \"sudo %#\" with administrator privileges", fullScript];
NSLog(#"shell script path: %#",script);
NSAppleScript *appleScript = [[NSAppleScript new] initWithSource:script];
NSAppleEventDescriptor * eventResult = [appleScript executeAndReturnError:&errorInfo];
// Check errorInfo
if (! eventResult)
{
// Describe common errors
*errorDescription = nil;
if ([errorInfo valueForKey:NSAppleScriptErrorNumber])
{
NSNumber * errorNumber = (NSNumber *)[errorInfo valueForKey:NSAppleScriptErrorNumber];
if ([errorNumber intValue] == -128)
*errorDescription = #"The administrator password is required to do this.";
}
// Set error message from provided message
if (*errorDescription == nil)
{
if ([errorInfo valueForKey:NSAppleScriptErrorMessage])
*errorDescription = (NSString *)[errorInfo valueForKey:NSAppleScriptErrorMessage];
}
return NO;
}
else
{
// Set output to the AppleScript's output
*output = [eventResult stringValue];
return YES;
}
}
Called as following:
TasksController *tasks = [[TasksController alloc] init];
NSString * output = nil;
NSString * processErrorDescription = nil;
BOOL success = [tasks runProcessAsAdministrator:#"/Applications/MyAPP/Library/bin/httpd"
withArguments:[NSArray arrayWithObjects:#"-f /Applications/MyAPP/conf/apache/MyAPP-httpd.conf", #"-k start", nil]
output:&output
errorDescription:&processErrorDescription
];
if (!success) // Process failed to run
{
// ...look at errorDescription
[_lblStatus setStringValue:#" Apache could not be started!"];
[_txtLogs setStringValue:processErrorDescription];
NSLog(#"%#",output);
NSLog(#"%#",processErrorDescription);
}
else
{
// ...process output
[_lblStatus setStringValue:#" Hurray Apache running!!"];
[_txtLogs setStringValue:output];
}
When I tried the above method the app is popup a small window asking for admin password but after introducing pass it's try to run and I get the following message in console:
dyld: DYLD_ environment variables being ignored because main executable (/usr/libexec/security_authtrampoline) is setuid or setgid
I also tried using the following methods but without success:
-(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;
}
-(void) runScript:(NSString*)scriptName
{
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
NSArray *arguments;
NSString* newpath = [NSString stringWithFormat:#"'%#'/%#",[[NSBundle mainBundle] resourcePath], scriptName];
NSLog(#"shell script path: %#",newpath);
arguments = [NSArray arrayWithObjects:newpath, 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 (#"script returned:\n%#", string);
}
For this last method I have ShellScript folder in my Supporting Files folder that contain scripts like startMysql.sh, startApache.sh ...
startMysql.sh example:
# /bin/sh
/Applications/MyAPP/Library/bin/mysqld_safe --port=8889 --socket=/Applications/MyAPP/tmp/mysql/mysql.sock --lower_case_table_names=0 --pid-file=/Applications/MyAPP/tmp/mysql/mysql.pid --log-error=/Applications/MyAPP/logs/mysql_error_log &
Thanks in advance!
In my program I currently use NSTask 5 times, and it all works very well, but I'm tired of having to repeat so much code when it's all so similar, so I tried putting it in a function. Unfortunately it results in a crash on the line: [task launch]. Other than that I can't figure out what's causing the crash as if I use this code outside the function it works perfectly.
The method I am using is as follows:
- (NSString *)performTask: (NSString *)launchPath: (NSString *)argument1: (NSString *)argument2: (NSString *)argument3: (NSString *)argument4: (NSString *)argument5
{
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: [NSString stringWithFormat: launchPath, resPath]];
NSArray *arguments = [NSArray arrayWithObjects: argument1, argument2, argument3, argument4, argument5, nil];
[task setArguments: arguments];
NSPipe *pipe = [NSPipe pipe];
[task setStandardInput:[NSPipe pipe]];
[task setStandardOutput: pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task launch];
NSData *data = [file readDataToEndOfFile];
NSString *status = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return status;
}
I really hope this can be fixed, I really cannot see why this crashes.
Thanks in advance everyone.
Check this out it's pretty cool I use it:
https://gist.github.com/1875386
It's also much easier than using arrayWithObjects: for NSTask...
rc
I am trying to run a simple shell command that runs and returns text rather quickly inside of a loop of indeterminate size at compile time that is generated by an NSArray. In scripting languages like perl, I would be able to do something like this:
for(i=0;i<=$myinputarraysize;i++){
$output[i]=`/my/task $inputarray[i]`;
}
This would build a new array for me from the expected output of my task. In Obj-C this seems to be much more difficult and a bit confusing to me. Right now my loop looks like this:
for(int i=0; i<[inputarray count]; i++){
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath:nsdchat];
NSArray *args;
args = [NSArray arrayWithObjects:#"/my/task", [inputarray objectAtIndex:i], nil];
[task setArguments:args];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *desc;
desc = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
desc = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
[descriptions insertObject:desc atIndex:i];
[task release];
[args release];
[pipe release];
[file release];
[data release];
}
My goal is to fill descriptions (an NSMutableArray) with the output from my task (which I know is always a string and always ends in a newline that I want to strip out). It seems I'm missing something about memory releasing as when I run this and NSLog the output, I get the same result for the entire count of the loop.
Is there any easier or more way to loop through simple tasks like this? Am I overcomplicating it for myself?
First of all, there's no need to do most of that work inside the loop. task, pipe and file all look like they could be handled outside the loop. You should also consider using Objective-C 2.0 dot syntax and fast enumeration to cut things down a little.
More significantly:
NSArray *args;
args = [NSArray arrayWithObjects:#"/my/task", [inputarray objectAtIndex:i], nil];
[task setArguments:args];
This says that the first argument passed to the executable at path ndschat is /my/task. Which doesn't seem to match your PERL usage. Probably you want just:
NSArray *args;
args = [NSArray arrayWithObject:[inputarray objectAtIndex:i]];
[task setArguments:args];
Or, with the style comments taken into account:
for(NSString *argument in inputarray)
{
...
task.arguments = [NSArray arrayWithObject:argument];
...
}
EDIT: you're also releasing a lot of objects you don't own, which as well as adding heft to your code is a memory management error possibly leading to a crash. So, to cut the whole thing down and correct that fault:
for(NSString *argument in inputarray)
{
NSTask *task = [[NSTask alloc] init]; // you now own this
task.launchPath = nsdchat;
NSPipe *pipe = [NSPipe pipe]; // you don't own this
task.standardOutput = pipe;
NSFileHandle *file = [pipe fileHandleForReading]; // you also don't own this
task.arguments = [NSArray arrayWithObject:argument];
[task launch];
[task waitUntilExit]; // you should wait until the task is done
NSData *data = [file readDataToEndOfFile]; // this is another thing
// you don't own. Note also that
// readDataToEndOfFile advances
// the current read pointer, so
// it should be fine to do this
// successively
NSString *desc;
desc = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]
autorelease];
// you don't own this because
// of the autorelease; you
// don't want to own it since
// the next line will throw
// it away
desc = [string stringByReplacingOccurrencesOfString:#"\n" withString:#""];
// you don't own this
[descriptions addObject:desc];
[task release];
}
I'm a beginner developer. I'and stopped with this error about:
Clang LLVM 1.0 Error
Expected ':'
line: [pipe fileHandleForReading availableData]
Can anyone help me? Thanks in advance.
- (NSInteger)sizeOfItemAtPath:(NSString*)path {
BOOL isdir;
[[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isdir];
if (isdir) {
NSPipe *pipe = [NSPipe pipe];
NSTask *t = [[[NSTask alloc] init] autorelease];
[t setLaunchPath:#"/usr/bin/du"];
[t setArguments:[NSArray arrayWithObjects:#"-k", #"-d", #"0", path, nil]];
[t setStandardOutput:pipe];
[t setStandardError:[NSPipe pipe]];
[t launch];
[t waitUntilExit];
NSString *sizeString = [[[NSString alloc] initWithData:[[pipe fileHandleForReading availableData] encoding:NSASCIIStringEncoding] autorelease];
sizeString = [[sizeString componentsSeparatedByString:#" "] objectAtIndex:0];
BOOL bytes;
bytes = [sizeString longLongValue]*1024;
}
else {
BOOL bytes;
bytes = [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize];
}
BOOL bytes;
return bytes;
}
You are missing a ]: it must be
[[pipe fileHandleForReading] availableData]
The whole line needs to look like this:
NSString *sizeString = [[[NSString alloc] initWithData:[[pipe fileHandleForReading] availableData] encoding:NSASCIIStringEncoding] autorelease];
Also, your method will return garbage. That is because you've defined bytes three times: once in the if branch, once in the else branch and once in the enclosing method body. The return value will be taken from the last one, but this one is initialized. Not only that, but you're using the wrong type: it must be a NSInteger bytes;, not BOOL bytes;. You need to put the definition at the start of the method and remove all other definitions, the variable may exist only once.
Try this:
[[pipe fileHandleForReading] availableData]