IPB

Bienvenue invité ( Connexion | Inscription )

 
Reply to this topicStart new topic
> Plantage d'appli NSTask, Sierra - Obj-C NSTask
Options
Nono95400
posté 20 Aug 2017, 11:03
Message #1


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 673
Inscrit : 16 Oct 2004
Membre no 25 318



Bonjour,

Voilà maintenant quelques années que je n'ai pas touché à Xcode ou bien pour de minimes retouches sur des projets perso.

Et venant d'installer Sierra sur mon ordi, j'ai pu constaté que l'appel à un exécutable unix depuis une application via NSTask, faisait planter immédiatement l'app.
J'ai donc réécrit une classe dans mon application pour me passer de cet exécutable.

Mais j'en ai un autre pour lequel je n'ai pas la moindre idée de la façon dont il procède et je ne peux donc pas m'en passer.

Comment faire pour intégrer un exécutable unix dans un projet Xcode sous Mac OS 10.12 pour pouvoir l'appeler depuis l'application avec NSTask ?

Y-aurait-il un système de signature ou bien de niveau d'autorisation nécessaire pour l'application pour exécuter d'autres programmes ?

Merci

PS : l'exécutable appelé depuis le Terminal avec exactement les mêmes arguments... fonctionne très bien.

Ce message a été modifié par Nono95400 - 20 Aug 2017, 11:04.


--------------------
Mac Pro early '09 Quad-Core Intel Xeon 2,93 GHz - 8Go de RAM - ATI HD5870 1Go - SSD Vortex 2 128Go - HD 1To, 2To, 3To.
MacBook Air 13" i7 1,8Ghz - 4Go de RAM - SSD 256Go
Go to the top of the page
 
+Quote Post
teddy7545
posté 24 Aug 2017, 22:24
Message #2


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 619
Inscrit : 4 Apr 2004
Lieu : Lorraine - 54
Membre no 17 184



Bonsoir Nono

Tu ne précises pas grand chose sur ton code et un extrait pourrait être utile pour t'aider davantage.
Ou as tu placé ton script ? comment l'appelles tu ? es tu certain des droits d'exécution de ton script (la version qui est exécutée) ?

Je viens de faire un essai avec Xcode sous Sierra et l'appel à NSTask fonctionne parfaitement (sous réserve d'avoir bien donné les droits d'execution à ton script).

Par ailleurs, en utilisant un bloc try comme ci-dessous, ton application ne devrait pas planter et pourra te donner la raison du blocage.
Code
    @try
    {
        NSTask *t = [[NSTask alloc] init];
        ...
    }
    @catch (NSException *e)
    {
        NSLog(@"Expection occurred %@", [e reason]);        
    }

De grandes chances que si le chemin n'est pas correct ou si les droits d'exécution ne sont pas attribués tu trouves le défaut : launch path not accessible.

Ce message a été modifié par teddy7545 - 24 Aug 2017, 23:51.


--------------------
Mac Pro Intel Dual Xéon 3 GHz - MacOSX 10.10.3 - ATI Radeon HD 5770 - ATTO UL5D - Apple Cinema HD Display 23 pouces
MacBookPro 13' mid 2009 - iMac 24' 8,1 2,8GHz 4Go- Mac G4 MDD Bi 1,25 GHz - Mac G4 Quicksylver 933MHz
Go to the top of the page
 
+Quote Post
Jaypee
posté 25 Aug 2017, 06:22
Message #3


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 323
Inscrit : 29 Aug 2002
Membre no 3 340



Est-ce l'occasion de jeter un œil à Swift

un "gist" donne un exemple: https://gist.github.com/Seasons7/836d3676884a40c8c98a

Code
    import Foundation
    
    
    let filePath = "/usr/local"

    // Création de la tâche en Swift 3.x
    let task = Process()
    
    // Configuration de la tâche
    task.launchPath = "/bin/ls"
    task.arguments = ["-laF@" , filePath]
    
    // Tuyau de sortie
        let pipe = Pipe()
    task.standardOutput = pipe
    
    // Exécution de la tâche
    task.launch()
    
    // Récupération du résultat
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)
    
    print(output!)


Et on peut l' essayer sans compiler dans un playground.

J-P

Ce message a été modifié par Jaypee - 25 Aug 2017, 06:28.
Go to the top of the page
 
+Quote Post
teddy7545
posté 26 Aug 2017, 16:32
Message #4


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 619
Inscrit : 4 Apr 2004
Lieu : Lorraine - 54
Membre no 17 184



Bonjour

Merci Jaypee pour le petit test en Swift ... c'est en effet une bonne occasion de tester un peu plus Swift (surtout maintenant que je viens de passer à Sierra avec Xcode 8)
Evidemment ça fonctionne très bien ... mais même en Swift il faut que le script possède les droits d'exécution .... et à défaut ça fait évidemment planter de la même façon qu'en ObjectiveC....

Dans ton exemple, tu utilises un exécutable du système (qui est évidemment exécutable) mais je pense que Nono95400 souhaitais utiliser un script perso encaqué dans son bundle auquel il doit affecter les droits au bon fichier (celui qui est ajouté dans le répertoire source)

De fait, pour avoir un message d'erreur en clair plutôt qu'un plantage il faudrait également utiliser en Swift un équivalent du bloc try que j'avais moi même mis en place avec ObjectiveC pour comprendre le problème que rencontrait Nono95400.

J'ai trouvé quelques exemples de code Swift qui mettent en oeuvre ce mécanisme et je vais essayer de l'implémenter dans cet exemple avec NSTask.

Ce message a été modifié par teddy7545 - 26 Aug 2017, 16:37.


--------------------
Mac Pro Intel Dual Xéon 3 GHz - MacOSX 10.10.3 - ATI Radeon HD 5770 - ATTO UL5D - Apple Cinema HD Display 23 pouces
MacBookPro 13' mid 2009 - iMac 24' 8,1 2,8GHz 4Go- Mac G4 MDD Bi 1,25 GHz - Mac G4 Quicksylver 933MHz
Go to the top of the page
 
+Quote Post
Jaypee
posté 27 Aug 2017, 08:40
Message #5


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 323
Inscrit : 29 Aug 2002
Membre no 3 340



Dans le cas où la commande shell se conforme au standard avec la convention:
status == 0 => success
status != 0 => erreur

on peut récupérer la valeur dans task.terminationStatus un Int32

!!! Attention: ne pas essayer le code suivant avec des privilèges: il tente de supprimer le log du système !!!!
Code
    // import Cocoa // pas certain que ce soit utile
    import Foundation
    
    
    let filePath = "/var/log/system.log"
    ""
    // Création de la tâche en Swift 3.x
    let task = Process()
    
    // Configuration de la tâche
    task.launchPath = "/bin/rm"
    task.arguments = ["-f" , filePath]
    
    // Tuyau de sortie
    let pipe = Pipe()
    task.standardOutput = pipe
    
    // Exécution de la tâche
    task.launch()
    
    task.waitUntilExit()
    
    // Récupération du résultat
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output = String(data: data, encoding: String.Encoding.utf8)
    
    print ("Termination status:  \(task.terminationStatus)")
    print("Output: \(output!)")


On voit que le statut est 1 donc en erreur. Le shell ne lève pas d'exception donc pas de try catch possible.
On voit aussi que output est vide.

J-P

Ce message a été modifié par Jaypee - 27 Aug 2017, 10:20.
Go to the top of the page
 
+Quote Post
Nono95400
posté 1 Sep 2017, 18:54
Message #6


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 673
Inscrit : 16 Oct 2004
Membre no 25 318



Bonjour,

Merci pour votre aide.

Je suis un peu perdu avec Swift, en ce moment pour le boulot j'apprend C#, VBA et ST. Donc pas trop le temps pour apprendre un langage supplémentaire à titre perso.

Je suis tout aussi perdu avec les nouvelles règles de sécurité de Mac OS Sierra, si je comprend bien un exécutable peut ne pas être autorisé à être appelé par une application et en même temps, il peut être lancé sans soucis depuis le Terminal ?

L'exécutable est situé dans le dossier "Resources" de l'application, il y est copié par Xcode lors de la compilation de l'application.

Comment puis-je l'autorisé à être exécuté par mon application ?


--------------------
Mac Pro early '09 Quad-Core Intel Xeon 2,93 GHz - 8Go de RAM - ATI HD5870 1Go - SSD Vortex 2 128Go - HD 1To, 2To, 3To.
MacBook Air 13" i7 1,8Ghz - 4Go de RAM - SSD 256Go
Go to the top of the page
 
+Quote Post
Jaypee
posté 2 Sep 2017, 18:58
Message #7


Macbidouilleur d'Or !
*****

Groupe : Membres
Messages : 2 323
Inscrit : 29 Aug 2002
Membre no 3 340



Salut Nono95400,

Si on vérifie les basiques, les permissions elles sont correctes?

il doit y avoir r et x au minimum partout, 755 ou rwxr-xr-x sur la commande que tu embarques dans l'appli

J-P

Ce message a été modifié par Jaypee - 2 Sep 2017, 19:10.
Go to the top of the page
 
+Quote Post
Nono95400
posté 5 Sep 2017, 19:20
Message #8


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 673
Inscrit : 16 Oct 2004
Membre no 25 318



Bonjour,

Voici les droits de l'exécutable qui est copié dans l'appli lors de la compilation par Xcode : -rwxr-xr-x


--------------------
Mac Pro early '09 Quad-Core Intel Xeon 2,93 GHz - 8Go de RAM - ATI HD5870 1Go - SSD Vortex 2 128Go - HD 1To, 2To, 3To.
MacBook Air 13" i7 1,8Ghz - 4Go de RAM - SSD 256Go
Go to the top of the page
 
+Quote Post
teddy7545
posté 8 Sep 2017, 20:44
Message #9


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 619
Inscrit : 4 Apr 2004
Lieu : Lorraine - 54
Membre no 17 184



Bonsoir,

Ton problème est curieux car les droits que tu mentionne sont bien adaptés.
J'ai fais les tests avec Xcode en ObjectiveC comme en Swift (avec la proposition de Jaypee) et tout fonctionne sans problème.

Citation
PS : l'exécutable appelé depuis le Terminal avec exactement les mêmes arguments... fonctionne très bien.
Es tu certain que c'est le même exécutable que tu lances avec Xcode ou avec le terminal (je veux dire pas sa copie située à un autre endroit)

Citation
Voici les droits de l'exécutable qui est copié dans l'appli lors de la compilation par Xcode : -rwxr-xr-x
Es tu certain que Xcode utilise bien cet exécutable ? comment l'appelles tu dans ton code ?

Peux tu montrer le code que tu utilises pour appeler ton exécutable (ou au moins un extrait) ?
Peux tu montrer le défaut que tu obtient ?



--------------------
Mac Pro Intel Dual Xéon 3 GHz - MacOSX 10.10.3 - ATI Radeon HD 5770 - ATTO UL5D - Apple Cinema HD Display 23 pouces
MacBookPro 13' mid 2009 - iMac 24' 8,1 2,8GHz 4Go- Mac G4 MDD Bi 1,25 GHz - Mac G4 Quicksylver 933MHz
Go to the top of the page
 
+Quote Post
Nono95400
posté 9 Sep 2017, 09:23
Message #10


Macbidouilleur d'argent !
***

Groupe : Membres
Messages : 673
Inscrit : 16 Oct 2004
Membre no 25 318



Bonjour,

Sans rien avoir changé à mon projet ou au code, voilà que l'appli ne plante plus lors de l'appel à l'exécutable huh.gif

Pour info, le bout de code réalisant l'appel :

Code
+ (NSString *)executeGetMonitor:(NSArray*)arguments {
    NSString * strResult=nil;
    NSPipe * thePipe=[[NSPipe alloc] init];
    NSTask * theTask=[[NSTask alloc] init];
    
    NSString * path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"highmonitor"];
    
    [theTask setLaunchPath: path];
    
    [theTask setArguments: arguments];
    [theTask setStandardOutput: thePipe];
    [theTask launch];
    [theTask waitUntilExit];
    if ([theTask terminationStatus] == 0) {
        strResult = [[NSString alloc] initWithData:[[thePipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding];
    } else {
        strResult = [[NSString alloc] initWithFormat:@"Erreur (%d)", [theTask terminationStatus]];
    }
    [theTask release];
    [thePipe release];
    return strResult;
}


Lors de l'exécution, je me rend compte que contrairement à avant (mon passage à Sierra), cela prend plusieurs longues secondes.

Je vais peut-être faire un "delegate" pour récupérer le résultat, une fois qu'il est disponible et éviter de bloquer l'appli.


--------------------
Mac Pro early '09 Quad-Core Intel Xeon 2,93 GHz - 8Go de RAM - ATI HD5870 1Go - SSD Vortex 2 128Go - HD 1To, 2To, 3To.
MacBook Air 13" i7 1,8Ghz - 4Go de RAM - SSD 256Go
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 utilisateur(s) sur ce sujet (1 invité(s) et 0 utilisateur(s) anonyme(s))
0 membre(s) :

 



Nous sommes le : 26th September 2017 - 06:49