Impossible d'instaurer un dialogue interactif avec une NSTask

HollowManHollowMan Membre
21:05 modifié dans API AppKit #1
Bonjour à  tous,
Je souhaite pouvoir dialoguer de manière interactive avec une NSTask afin de passer un mot de passe quand celui-ci est demandé par l'executable que je pilote. Cela fonctionne exactement comme pour SSH, mais ce n'est pas SSH, donc pas possibilité de tricher avec les clés AES. J'ai un fileHandle et une NSPipe pour lire/écrire, et la lecture fonctionne parfaitement pour afficher la progression, ou toutes les autres infos "conventionnelles".
Seulement voilà , lorsqu'il s'agit de lui donner le mot de passe, la demande se fait dans la console (Xcode en mode debug, on la console système autrement), et il attend une réponse clavier depuis la-dite console (en mode debug uniquement). Je n'arrive pas à  récupérer la demande afin de pouvoir savoir quand il faut un mot de passe, et donc je ne peux pas non plus le-lui envoyer.

Voici mon code actuel:
myTask = [[NSTask alloc] init];<br />	NSPipe *readPipe = [[NSPipe pipe] retain];<br />	NSMutableString *tmpResults = [[NSMutableString alloc] init];<br />	readHandle = [[readPipe fileHandleForReading] retain];<br />	NSPipe *writePipe = [[NSPipe pipe] retain];<br />	writeHandle = [[writePipe fileHandleForWriting] retain];<br />	[myTask setStandardInput:writePipe];<br />	<br />	[myTask setLaunchPath:[args objectAtIndex:0]];<br />	[myTask setArguments:[args objectAtIndex:1]];<br />	[myTask setStandardOutput:readPipe];<br />	[readHandle readInBackgroundAndNotify];<br />	[myTask launch];


Est-il possible de solutionner ce problème?
Merci par avance !

Réponses

  • AliGatorAliGator Membre, Modérateur
    21:05 modifié #2
    sais-tu si ton exécutable te demande systématiquement le mot de passe, et ce toujours au même moment dans les étapes ? Par exemple il te demande toujours le mot de passe comme première "question" ?

    Si c'est le cas, normalement tu peux écrire dans le writePipe (dans stdin, en fait), même sans attendre. Car l'entrée standard est buffurisée, autrement dit tout ce que tu lui envoies est stocké en attente d'être lu, et sera donc "dépilé" et lu quand le programme cherchera à  lire l'entrée clavier.

    Enfin ça c'est le principe générique. Après si ton utilitaire que tu lances par NSTask ne demande pas toujours le mot de passe, ou pas toujours au même moment (et que tu ne peux donc pas prévoir s'il faut l'envoyer et à  quel moment, ou pas), ou si ton utilitaire gère l'entrée du mot de passe d'une manière non conventionnelle (sans lire stdin, ou en basculant stdin en mode non-bufferisé dans le code du programme même si c'est vraiment pas courant, ou en vidant le contenu de stdin avant de demander le mot de passe, etc...) ça marchera pas, mais bon, ça reste quand même jouable en général.
  • Philippe49Philippe49 Membre
    septembre 2009 modifié #3
    Bonjour,
    j'avais fait la petite appli ci-dessous pour expliquer le dialogue d'un programme C avec l'utilisateur, sans rencontrer de problème de communication avec le task ...
    (on répond au fur et à  mesure au programme les valeurs de tab ... )
  • HollowManHollowMan Membre
    21:05 modifié #4
    dans 1253813916:

    sais-tu si ton exécutable te demande systématiquement le mot de passe, et ce toujours au même moment dans les étapes ? Par exemple il te demande toujours le mot de passe comme première "question" ?

    Si c'est le cas, normalement tu peux écrire dans le writePipe (dans stdin, en fait), même sans attendre. Car l'entrée standard est buffurisée, autrement dit tout ce que tu lui envoies est stocké en attente d'être lu, et sera donc "dépilé" et lu quand le programme cherchera à  lire l'entrée clavier.

    Enfin ça c'est le principe générique. Après si ton utilitaire que tu lances par NSTask ne demande pas toujours le mot de passe, ou pas toujours au même moment (et que tu ne peux donc pas prévoir s'il faut l'envoyer et à  quel moment, ou pas), ou si ton utilitaire gère l'entrée du mot de passe d'une manière non conventionnelle (sans lire stdin, ou en basculant stdin en mode non-bufferisé dans le code du programme même si c'est vraiment pas courant, ou en vidant le contenu de stdin avant de demander le mot de passe, etc...) ça marchera pas, mais bon, ça reste quand même jouable en général.


    Justement non, c'est le problème, le programme ne demande pas le mot de passe à  chaque fois, et ce sera à  l'utilisateur de rentrer le-dit mot de passe. Malgré tout, j'ai essayé sur un cas ou je sais qu'il a besoin du mot de passe, et ou je le connais, et en envoyant la chaine sur le writeHandle tout de suite après le lancement de la task, ça ne marche pas, il me le demande quand même...

    dans 1253818819:

    Bonjour,
    j'avais fait la petite appli ci-dessous pour expliquer le dialogue d'un programme C avec l'utilisateur, sans rencontrer de problème de communication avec le task ...
    (on répond au fur et à  mesure au programme les valeurs de tab ... )


    Je n'ai pas trouvé ton petit programme sur ton site web, ne serait-il pas possible je jeter un oeil à  ses sources?

    Si jamais je ne m'en sort pas avec la NSTask, je ferais passer la chose dans un script Exp qui permet de gérer cette interactivité (ça marche plutôt bien avec SSH notamment), mais je préférerais éviter, parce que c'est plus propre, et parce que je trouverais dommage qu'on ne puisse pas le faire directement ^^
  • Philippe49Philippe49 Membre
    septembre 2009 modifié #5
    dans 1253824569:

    Je n'ai pas trouvé ton petit programme sur ton site web

    Ce programme n'avait d'intérêt que pour le cours du lendemain ...

    dans 1253824569:

    ne serait-il pas possible je jeter un oeil à  ses sources?


    Rien de bien original sur les Tasks , je crois que tout est dans le Hillegass

    -(void) launchTask {<br />	// setting task<br />	....<br />		<br />	NSPipe* inputPipe=[NSPipe pipe] ; [task setStandardInput:inputPipe]; inputFileHandle=[[inputPipe fileHandleForWriting] retain];<br />	NSPipe* outputPipe=[NSPipe pipe] ; [task setStandardOutput:outputPipe]; outputFileHandle=[[outputPipe fileHandleForReading] retain];	<br />	NSPipe* errorPipe=[NSPipe pipe] ; [task setStandardError:errorPipe]; errorFileHandle=[[errorPipe fileHandleForReading] retain];	<br />	<br />	[task launch];<br />	[outputFileHandle readInBackgroundAndNotify];<br />	[errorFileHandle readInBackgroundAndNotify];<br />}
    


    S'enregistrer pour les notifications
    <br />-(void) awakeFromNib {<br />	// Registering with Notifications<br />	NSNotificationCenter * defaultCenter=[NSNotificationCenter defaultCenter];<br />	[defaultCenter addObserver:self selector:@selector(taskDidStop:) name:NSTaskDidTerminateNotification object:task];<br />	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(writeTaskInfo:) name:NSFileHandleReadCompletionNotification object:nil];<br />}<br />-(void) dealloc {<br />	if([task isRunning]) [task interrupt];<br />	[[NSNotificationCenter defaultCenter] removeObserver:self];<br />	[super dealloc];<br />}<br />
    


    Recevoir le stdout du task
    <br />-(void) writeTaskInfo:(NSNotification*) notification {<br />	// The object of the notification is outputFilehandleNotification, so it is not necessary to retain it in runTask.<br />	NSData * data=[[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];<br />	NSString * str=[[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]; <br />	NSFileHandle * fileHandle=[notification object];<br />	if(fileHandle==outputFileHandle) {<br />		// append to outputTextView	<br />		NSTextStorage * textStorage=[outputTextView textStorage];<br />		[textStorage replaceCharactersInRange:NSMakeRange([textStorage length],0) withString:str];<br />		if(task) {<br />			[outputFileHandle readInBackgroundAndNotify];<br />		}<br />	} else {<br />	....<br />	}		<br />}<br />
    


    Répondre
    <br />- (void)textDidChange:(NSNotification *) notification {<br />	// configure the data to send<br />	....<br />	// send it<br />	NSData * data=[str dataUsingEncoding:NSUTF8StringEncoding];<br />	[inputFileHandle writeData:data];<br /><br />	// updates<br />}
    

Connectez-vous ou Inscrivez-vous pour répondre.