Скрипт PowerShell не возвращает - PullRequest
0 голосов
/ 25 апреля 2020

Я пишу генератор PDF, который реализован в Java и использует сценарии PowerShell для компиляции файлов TEX с latexmk. Примером сгенерированной команды является powershell.exe -NoProfile -NoLogo "&'C:\path\to\scripts\compileTex.ps1' 'C:\path\to\workingDir' 'filename.tex'". Если я эту команду вручную в cmd, команда компилирует файл TEX и возвращает правильно. Когда я вызываю этот скрипт через Java, он не возвращается. Я прочитал много других вопросов, которые предлагают добавить < NUL в конце команды. Я делаю это, явно закрывая входной поток процесса. В результате все сценарии PowerShell возвращаются правильно, кроме сценария с командой latexmk.

Я использую следующий сценарий PowerShell для компиляции:

param(
    [Parameter(Mandatory = $true)][string] $workingDir,
    [Parameter(Mandatory = $true)][string] $texFileName
)

if (Test-Path -LiteralPath "$workingDir") {
    cd "$workingDir"
    if (Test-Path -LiteralPath "$texFileName") {
        $texFileBaseName = $texFileName.Trim(".tex")
        latexmk -nobibtex -norc -pdf -jobname="$texFileBaseName" "$texFileName" # FIXME This call leads to a timeout
    } else {
        Write-Error "Could not find \"$texFileName\""
    }
} else {
    Write-Error "The working directory \"$workingDir\" does not exist"
}

Я использую следующее Java фрагмент для вызова этого сценария:

        StringJoiner innerCommand = new StringJoiner(" ", "\"&", "\"")
                .add(String.format("'%s'", script.normalize().toString()));
        for (String param : params) {
            if (param.startsWith("-")) { // Its an option or switch
                innerCommand.add(param);
            } else {
                innerCommand.add(String.format("'%s'", param));
            }
        }
        StringJoiner command = new StringJoiner(" ")
                .add("powershell.exe")
                .add("-NoProfile")
                .add("-NoLogo")
                .add(innerCommand.toString());

        try {
            Process process = Runtime.getRuntime()
                    .exec(command);
            process.getOutputStream().close(); // Make sure CMD does not wait for further commands
            boolean exited = process.waitFor(COMMAND_TIMEOUT_VALUE, COMMAND_TIMEOUT_UNIT);
            String stdOutResult = new String(process.getInputStream().readAllBytes());
            T commandResult;
            if (exited) {
                if (process.exitValue() == 0) {
                    commandResult = onSuccess.apply(stdOutResult);
                } else {
                    String stdErrResult = new String(process.getErrorStream().readAllBytes());
                    commandResult = onFailure.apply(stdOutResult, stdErrResult);
                }
            } else {
                commandResult = onTimeout.get();
            }
            return commandResult;
        } catch (IOException | InterruptedException ex) {
            throw new SystemCommandFailedException(String.format("Processing %d errored", commandID), ex);
        }
    }

РЕДАКТИРОВАТЬ: Добавление [Console]::Out.Flush() не работает.

...