2010-08-09 27 views
10

İşte benim kodudur.NSTask NSPipe nesnel c komut satırı yardım

Bazı nedenlerden ötürü, bu kodu çalıştırdığımda stringRead, hiçbir şey döndürmez. .sh dosyasını başlattığımda hangi terminalin döndüğünü döndürmeli. Doğru?

Herhangi bir fikrin var mı?

İlyas standart çıktıyı kullanarak yeni bir görev başlatıldığında bir sonraki herhangi bir çıktı baskı durdurur Xcode bir hata var

+0

Sunucu.sh komut dosyasının standart çıktıda çıktığından emin misiniz? Belki de stderr'i bağlaman ve bir şey içerip içermediğini görmelisin. Ayrıca, okunmakta olan borudan fazla veri yazdırmaya çalışırsa ve arabellek dolduğunda, görev, çalışmakta olan borudan veri okumayı düşünebilirsiniz. Bir şey çıkarmaya çalışır. –

+0

Emin değilim. Bana bir örnek gösterebilir misin? Evet, [task release] ve [task waitUntilExit] 'i kaldırdım. Aynı sorun. – objectiveccoder001

+0

String'in içeriğini programlı olarak mı kontrol ediyorsunuz (veya gdb'de), yoksa NSLog'u kullanarak bir şeyler mi yazdırmaya çalışıyorsunuz? NSLog kullanıyorsanız ve hiç çıktı göremiyorsanız, çıkışınız için Uygulamalar> Yardımcı Programlar'da Konsol günlüğünü kontrol edin. Kabuk betikleri, NSTask'ın Xcode konsolu çıkışının çalışmasını durdurabileceği şekilde çalışır.Bunun dışında, Kevin'ın standart hata üzerinde bir şey olup olmadığını (sadece ikinci bir boru ekleyip görevinizin standart hatası olarak belirlediğini) kontrol etmenin ve boruların tümünün Görevinizin çıktı. – puzzle

cevap

19

Xcode Bug
(hepsi çıktı toplar, ancak artık hiçbir şey yazdırır). Çıktının tekrar gösterilmesini sağlamak için [task setStandardInput:[NSPipe pipe]] numaralı telefonu aramanız gerekecek (ya da alternatif olarak, görevlerin stdout yerine stderr'e sahip olmasını sağlayın). Nihai kodu için


Öneri: Bu senkron çünkü çözüm donma noktasının üzerindeyse

NSTask *server = [NSTask new]; 
[server setLaunchPath:@"/bin/sh"]; 
[server setArguments:[NSArray arrayWithObject:@"/path/to/server.sh"]]; 
[server setCurrentDirectoryPath:@"/path/to/current/directory/"]; 

NSPipe *outputPipe = [NSPipe pipe]; 
[server setStandardInput:[NSPipe pipe]]; 
[server setStandardOutput:outputPipe]; 

[server launch]; 
[server waitUntilExit]; // Alternatively, make it asynchronous. 
[server release]; 

NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile]; 
NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; // Autorelease optional, depending on usage. 
+0

donuyor Bu benim kodumu donuyor gibi görünüyor ... huh ... başka bir fikir? – objectiveccoder001

+0

Ve "Merhaba dünya" echo koymak için boş döndü .... ve tarih boş bırakıldı. – objectiveccoder001

+0

'[server setStandardInput: [NSPipe pipe]]' ile bile mi? Bu biraz garip. Kodumun aynısını kopyaladın mı? Deneyin ve sadece "echo" Merhaba Dünya "içeren bir dosyayla çalışıp çalışmayacağını görün; pwd | ls'. Eğer hala çalışmıyorsa, lütfen bize hangi Xcode sürümünü kullandığınızı söyleyin ve dize dosyaya yazılırsa herhangi bir çıktı üretip üretmediğine bakın (sadece Xcode terminali daha fazla çıktı almıyor olabilir). –

9

. [server waitUntilExit] numaralı çağrı, görevler bitene kadar çalışma döngüsünü engeller.

Görev çıktısını almak için gereken async çözümü.

task.standardOutput = [NSPipe pipe]; 
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) { 
    NSData *data = [file availableData]; // this will read to EOF, so call only once 
    NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 

    // if you're collecting the whole output of a task, you may store it on a property 
    [self.taskOutput appendData:data]; 
}]; 

Muhtemelen task.standardError için aynı yukarıda tekrarlamak istiyorum.

ÖNEMLİ:

senin görevin sona zaman, nil readabilityHandler bloğu ayarlamak zorunda; Aksi takdirde, okuma asla durmayacağından yüksek CPU kullanımıyla karşılaşırsınız.

[task setTerminationHandler:^(NSTask *task) { 

    // do your stuff on completion 

    [task.standardOutput fileHandleForReading].readabilityHandler = nil; 
    [task.standardError fileHandleForReading].readabilityHandler = nil; 
}]; 

Bu

tüm asenkron (ve bunu zaman uyumsuz yapmalısınız), bu nedenle yöntem^tamamlama bloğu olmalıdır.

+0

Mükemmel. Blok API'sine bir örnek arıyordum. – uchuugaka