2009-08-08 4 views
1

Привет У меня есть следующий код:Использования NSTask: приложение замораживание после возвращения выхода

- (IBAction)runTask:(id)sender { 
    NSTask *proc; 
    NSPipe *output; 
    NSData *data; 
    NSString *buffer; 

    proc = [[NSTask alloc] init]; 
    output = [[NSPipe alloc] init]; 

    [proc setLaunchPath:@"/bin/sh"]; 
    [proc setArguments:[NSArray arrayWithObjects: @"-c", @"/usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit | /usr/bin/awk 'NR>1{print $1}' | /usr/bin/sed -e '/@executable_path/d' -e 's/(.*)$//' -e 's/\\/Versions.*$//'", nil]]; 
    [proc launch]; 

    data = [[output fileHandleForReading] readDataToEndOfFile]; 
    buffer = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; 
    NSLog(@"got: %@", buffer); 

    // Release 
    [proc release]; 
    [output release]; 
    [buffer release]; 
    [data release]; 
} 

кода цель является своим родом сложной, он использует otool, чтобы получить список разделяемых библиотек, используемых двоичные файлы, то он использует sed и awk, чтобы отфильтровать его в машиночитаемом формате. Просто для тестирования я использовал двоичный файл Mac OS X TextEdit.app.

Проблема в том, что код запускается и возвращает результат, но затем замораживает приложение. Я прошел через него по строкам и нашел эту проблему проблемой:

data = [[output fileHandleForReading] readDataToEndOfFile];

Эта строка сама регистрирует вывод на консоль и затем замораживает приложение. Я проверил это, удалив все остальные строки после этой строки и все еще записывает выходные данные и зависает. В отладчике нет ничего, и любые предложения о том, как решить эту проблему, будут очень благодарны.

+1

Я скопировал код в инструмент командной строки, добавил недостающую 'setStandardOutput:' сообщения, и побежал. Он отлично работает, за исключением того, что вы заканчиваете «данные» в конце. –

+0

«Я проверил это, удалив все остальные строки после этой строки ...» Вместо этого я предлагаю выборку вашего приложения. См. Образец человека 1. –

ответ

1

Решение этой проблемы было просто,

Его известная ошибка, что после NSTask выполняется все каротаж не работает. Он возвращает выход, его просто не регистрирует. Решение было добавить следующую строку:

[task setStandardInput:[NSPipe pipe]]; 

И все работает отлично :)

2

Похоже, вы пропустили в

[proc setStandardOutput:output]; 
+0

Я добавил эту строку, но теперь кажется, что я вообще ничего не получаю. – indragie

0

У вас есть дополнительный слэш в конце прошлого SED заявления. После его удаления скрипт работает нормально.

+0

Я не уверен, что я удалил правую косую черту, я вытащил одну из них в самом конце последнего оператора sed, теперь строка выглядит так: [proc setArguments: [NSArray arrayWithObjects: @ "- c", @ "/ usr/bin/otool -L /Applications/TextEdit.app/Contents/MacOS/TextEdit |/usr/bin/awk 'NR> 1 {print $ 1}' |/usr/bin/sed -e '/ @ executable_path/d '-e' s/(.*)$// '-e' s/\\/Версии. * $/'", nil]]; Но я получаю эту ошибку: sed: 1: "s/\/Versions. * $/\ N": unescaped newline внутри замещающего шаблона – indragie

+0

О, а также, я не думаю, что это проблема с самой командой , Я пробовал очень простой «ls/Volumes», и то же самое происходит, выход возвращается, но приложение зависает. Я добавил в строку setStandardOutput, как было предложено предыдущим плакатом, и, хотя это решает проблему замораживания, выхода больше нет. Thanks – indragie

+0

PCWiz: Я забыл отменить обратную косую черту перед тем, как попробовать команду, и на самом деле не прочитал ее, чтобы увидеть, где должен был закончить последний шаблон. Эта последняя косая черта здесь. Сожалею. –

0

выход должен быть создан с помощью [NSPipe трубы] (бесхозной), а затем выход должен быть установлен как стандартный вывод с [Proc setStandardOutput: выходной]

Но причина, вы сбой, потому что вы освобождаете данные, вы не выделяли, не добавляли или не копировали. См. memory management rules.

Также см. Quickies for NSTask за хорошую чистую реализацию этого кода.

Смежные вопросы