gpt4 book ai didi

objective-c - 当前目录路径和 NSTask

转载 作者:搜寻专家 更新时间:2023-10-30 20:08:56 35 4
gpt4 key购买 nike

好吧,假设我正在创建一个 (Bash) 终端模拟器 - 我实际上不是,但它在描述方面非常接近。

我已经设法让(几乎)一切正常,但是我面临一个简单的问题:维护当前目录。

我的意思是...假设用户运行 pwd,我们通过 NSTask/usr/bin/env bash 执行它。这将输出当前应用程序的目录。没关系。

现在,假设用户输入 cd ..。路径正在改变,对吗? (好吧,即使是那个特定的 session ,但它正在改变,不是吗?)

因此,我想在任务终止时存储任务的 currentDirectoryPath,然后在启动另一个与 Bash 相关的任务时重新设置它。

但是,它始终获得完全相同的路径(应用程序包所在的路径)。

我错过了什么?

关于如何让它工作的任何想法?


代码

- (NSString*)exec:(NSArray *)args environment:(NSDictionary*)env action:(void (^)(NSString*))action completed:(void (^)(NSString*))completed
{
_task = [NSTask new];
_output = [NSPipe new];
_error = [NSPipe new];
_input = [NSPipe new];
NSFileHandle* outputF = [_output fileHandleForReading];
NSFileHandle* errorF = [_error fileHandleForReading];

__block NSString* fullOutput = @"";

NSMutableDictionary* envs = [NSMutableDictionary dictionary];

envs[@"PATH"] = [[APP environment] envPath];

[_task setLaunchPath:@"/usr/bin/env"];
if (env)
{
for (NSString* key in env)
{
envs[key] = env[key];
}
}
[_task setEnvironment:envs];

[_task setArguments:args];
[_task setStandardOutput:_output];
[_task setStandardError:_error];
[_task setStandardInput:_input];

void (^outputter)(NSFileHandle*) = ^(NSFileHandle *file){
NSData *data = [file availableData];
NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

action(str);

fullOutput = [fullOutput stringByAppendingString:str];
};

[outputF setReadabilityHandler:outputter];
[errorF setReadabilityHandler:outputter];

[_task setTerminationHandler:^(NSTask* task){
completed(fullOutput);

dispatch_async(dispatch_get_main_queue(), ^{
[[APP environment] setPwd:[task currentDirectoryPath]];
});

[task.standardOutput fileHandleForReading].readabilityHandler = nil;
[task.standardError fileHandleForReading].readabilityHandler = nil;
[task.standardInput fileHandleForWriting].writeabilityHandler = nil;
[task terminate];
task = nil;
}];

if (![[[APP environment] pwd] isEqualToString:@""])
[_task setCurrentDirectoryPath:[[APP environment] pwd]];

[_task launch];

return @"";
}

最佳答案

一般来说,很难甚至不可能从外部修改另一个进程的环境和其他属性。同样,通常不可能从外部查询那些。调试器和 ps 可以使用特殊权限来完成。

创建相关进程的父进程有机会在它生成子进程时设置初始环境和属性。

cd 命令必然是一个 shell 内置命令,因为它必须修改 shell 进程的状态。该更改不会直接影响任何其他现有进程的状态。它将被随后创建的子流程继承。

NSTaskcurrentDirectoryPath 属性仅在任务启动时才有意义。它是新进程将继承的当前目录。它不会跟踪子进程的当前目录,因为它不能。查询它仅返回 NSTask 对象配置使用的值(或默认值,即创建 NSTask 对象的进程的当前目录)。

如果您尝试编写类似终端仿真器的东西,您将需要创建一个长期运行的交互式 shell 子进程,并在父进程和 shell 之间建立通信管道。不要在单独的进程中运行单独的命令。相反,通过管道将命令写入交互式 shell 并读取后续输出。尝试解释该输出可能没有意义,因为它在形式上可能是通用的并且不容易解析。直接向用户显示即可。

或者,您必须在父进程中本地解释一些命令。这将类似于 shell 内置函数。所以,你必须识别一个 cd 命令,而不是启动一个 NSTask 来执行它,你只需修改父进程的状态,这样新的当前目录将用于后续任务。也就是说,您可以在变量中跟踪新的当前目录,并在启动所有后续 NSTask 对象之前设置 currentDirectoryPath,或者您可以使用 修改父进程的当前目录>-[NSFileManager changeCurrentDirectoryPath:] 它将被 future 的子进程自动继承。

关于objective-c - 当前目录路径和 NSTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27057837/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com