Я пишу генератор 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()
не работает.