从 System.Diagnostics.Process 调用`pod install`

问题描述 投票:0回答:1

当我们为 iOS 构建 Unity 项目时,它会生成一个使用 Cocoapods 的 Xcode 项目。我正在尝试制作一个构建后处理脚本(C#,在 Unity 编辑器中运行)来编辑 Podfile,然后在构建目录中运行

pod install

我尝试了几种不同的方法来运行

pod install
,但都以以下两种方式之一失败:

private static void ExecuteProcess(string directory, string argument) {
    try {
        System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo() {
            FileName = "/bin/bash",
            UseShellExecute = false,
            RedirectStandardError = true,
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
            CreateNoWindow = true,
            WorkingDirectory = directory,
            Arguments = " -c \"" + argument + " \""
        };

        System.Diagnostics.Process myProcess = new System.Diagnostics.Process {
            StartInfo = startInfo
        };
        myProcess.Start();
        while (!myProcess.StandardOutput.EndOfStream) {
        var line = myProcess.StandardOutput.ReadLine();
            UnityEngine.Debug.Log(line);
        }

    } catch (System.Exception e) {
        UnityEngine.Debug.Log(e);
    }
}

private static void TryInstallPods() {
    const string BUILDS_PATH = "./Builds";
    string shellScriptPath = Path.Join(BUILDS_PATH, "podinstall.sh");

    // Outputs nothing
    File.WriteAllText(shellScriptPath, "pod install --verbose");
    ExecuteProcess(BUILDS_PATH, "sh podinstall.sh");

    // Outputs "CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only performed in repo update"
    File.WriteAllText(shellScriptPath, "/usr/local/bin/pod install --verbose");
    ExecuteProcess(BUILDS_PATH, "sh podinstall.sh");

    // Outputs nothing
    ExecuteProcess(BUILDS_PATH, "pod install --verbose");
    
    // Outputs "CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only performed in repo update"
    ExecuteProcess(BUILDS_PATH, "/usr/local/bin/pod install --verbose");

    // For reference, this works as expected for the build directory:
    ExecuteProcess(BUILDS_PATH, "ls");
    // This also works as expected:
    ExecuteProcess(BUILDS_PATH, "/usr/local/bin/pod --help");
    // This produces no output:
    ExecuteProcess(BUILDS_PATH, "pod --help");
}

注意这个shell脚本是由代码生成的:

podinstall.sh

/usr/local/bin/pod install --verbose

  1. 从我的 C# 代码中,
    pod install --verbose
    不会产生任何输出,无论是直接调用还是从 shell 脚本内部调用。
  2. 从我的 C# 代码中,
    "/usr/local/bin/pod install --verbose"
    生成输出“CDN:主干相对路径:CocoaPods-version.yml 存在!返回本地,因为仅在存储库更新中执行检查”,无论是直接调用还是从 shell 脚本内部调用。没有发生任何其他事情,并且 pod 配置也没有更新。

如果尝试此处描述的方法,我会得到相同的结果:https://forum.unity.com/threads/ adjustment-pods-pods-xcproject-after-pod-install.1406500/

但是,如果我在构建文件夹中打开终端窗口并在其中键入命令,则任何变体都可以工作:

% pod install --verbose

% /usr/local/bin/pod install --verbose

% sh podinstall.sh

过程不死锁;删除标准输入和输出的方向不会使

pod install
命令起作用(通过检查
Podfile.lock
并看到它没有改变来验证)。

为什么当我在终端窗口中输入这些命令时它们会起作用,但当我尝试从 C#/Unity 中的进程中运行它们时却不起作用?

注意:我已经重新格式化了这个问题的代码;这个问题可能包含原始代码中不存在的拼写错误。

c# macos mono cocoapods
1个回答
0
投票

user246821 帮助我指明了正确的方向。将错误输出重定向到控制台后,我发现了一条错误消息,

pod install
要求将shell设置为UTF-8。向进程添加环境变量可以解决此问题:

private static void TryInstallPods() {
    RunCmd("/bin/bash", BUILDS_PATH, "/usr/local/bin/pod install");
}

private static void RunCmd(string exePath, string directory, string arguments = null) {
    ProcessStartInfo startInfo = new ProcessStartInfo(exePath, arguments);
    startInfo.Arguments = " -c \"" + arguments + " \"";
    startInfo.WorkingDirectory = directory;
    startInfo.CreateNoWindow = true;
    startInfo.RedirectStandardError = true;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardInput = false;
    startInfo.UseShellExecute = false;
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.ErrorDialog = false;
    startInfo.Environment["LANG"] = "en_US.UTF-8"; //REQUIRED FOR POD INSTALL

    using (Process p = new Process { StartInfo = startInfo, EnableRaisingEvents = true }) {
        p.ErrorDataReceived += (sender, e) => {
            if (!System.String.IsNullOrEmpty(e.Data)) {
                UnityEngine.Debug.Log("Error: " + e.Data);
            }
        };

        p.OutputDataReceived += (sender, e) => {
            if (!System.String.IsNullOrEmpty(e.Data)) {
                UnityEngine.Debug.Log("Output: " + e.Data);
            }
        };

        p.Start();
        p.BeginErrorReadLine();
        p.BeginOutputReadLine();
        p.WaitForExit();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.