2

NSTaskを使用して、ターミナルをシミュレートしてコマンドを実行したいと思います。コードは次のとおりです。ループで入力を取得し、プロセス出力を返すことができます。

int main(int argc, const char * argv[])
{
  @autoreleasepool {      
    while (1) {
        char str[80] = {0};
        scanf("%s", str);
        NSString *cmdstr = [NSString stringWithUTF8String:str];

        NSTask *task = [NSTask new];
        [task setLaunchPath:@"/bin/sh"];
        [task setArguments:[NSArray arrayWithObjects:@"-c", cmdstr, nil]];

        NSPipe *pipe = [NSPipe pipe];
        [task setStandardOutput:pipe];

        [task launch];

        NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];

        [task waitUntilExit];

        NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@", string);

    }
}

私の質問は、ループが終了すると、実行環境が初期化状態に復元することです。たとえば、デフォルトの実行パスはであり、パスをに変更するため/Users/appleに実行してから実行すると、ではなくが返されます。cd //pwd/Users/apple/

NSTaskでは、どうすればターミナルを完全にシミュレート できますか?

4

1 に答える 1

6

cdpwdはシェル組み込みコマンドです。タスクを実行すると

/bin/sh -c "cd /"

変更された作業ディレクトリを呼び出しプロセスに戻す方法はありません。変数を設定する場合も同じ問題が存在しますMYVAR=myvalue

これらの行を個別に解析して、環境を更新してみてください。しかし、次のような複数行のコマンドはどうですか

for file in *.txt
do
    echo $file
done

各行を別々のNSTaskプロセスに送信することによってそれをエミュレートすることはできません。

あなたができる唯一のことは、単一の /bin/shプロセスをNSTaskで開始し、すべての入力行をそのプロセスの標準入力にフィードすることです。readDataToEndOfFileただし、 を使用して出力を読み取ることはできませんが、非同期で読み取る必要があります ( を使用[[pipe fileHandleForReading] waitForDataInBackgroundAndNotify])。

要するに、(単一の)シェルを実行するだけでターミナルをシミュレートできます。

追加:おそらく、アプリの出発点として以下を使用できます。(エラーチェックはすべて省略しています。)

int main(int argc, const char * argv[])
{
    @autoreleasepool {

        // Commands are read from standard input:
        NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];

        NSPipe *inPipe = [NSPipe new]; // pipe for shell input
        NSPipe *outPipe = [NSPipe new]; // pipe for shell output

        NSTask *task = [NSTask new];
        [task setLaunchPath:@"/bin/sh"];
        [task setStandardInput:inPipe];
        [task setStandardOutput:outPipe];
        [task launch];

        // Wait for standard input ...
        [input waitForDataInBackgroundAndNotify];
        // ... and wait for shell output.
        [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];

        // Wait asynchronously for standard input.
        // The block is executed as soon as some data is available on standard input.
        [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
                                                          object:input queue:nil
                                                      usingBlock:^(NSNotification *note)
         {
             NSData *inData = [input availableData];
             if ([inData length] == 0) {
                 // EOF on standard input.
                 [[inPipe fileHandleForWriting] closeFile];
             } else {
                 // Read from standard input and write to shell input pipe.
                 [[inPipe fileHandleForWriting] writeData:inData];

                 // Continue waiting for standard input.
                 [input waitForDataInBackgroundAndNotify];
             }
         }];

        // Wait asynchronously for shell output.
        // The block is executed as soon as some data is available on the shell output pipe. 
        [[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
                                                          object:[outPipe fileHandleForReading] queue:nil
                                                      usingBlock:^(NSNotification *note)
         {
             // Read from shell output
             NSData *outData = [[outPipe fileHandleForReading] availableData];
             NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
             NSLog(@"output: %@", outStr);

             // Continue waiting for shell output.
             [[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
         }];

        [task waitUntilExit];

    }
    return 0;
}
于 2012-11-04T11:44:42.923 に答える