PowerShell и Java KeyTool - подавление всего вывода KeyTool

Я создаю довольно сложную ситуацию сценария Post-Build для своей компании, которая будет обрабатывать множество движущихся частей. Использование сценариев Powershell обеспечивает большую гибкость, поэтому я начал его изучать.
Однако при установке сертификата Java возникает проблема перенаправления вывода.

Теперь все работает как положено. Проверка сертификата, сертификата удаления, даже сертификата установки работает нормально - за исключением одной небольшой проблемы:

(Это результат успешного запуска скрипта)

[Command:   C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
[Arguments: -list -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt"]
[Command:   C:\Program Files\Java\jre1.8.0_261\bin\keytool.exe]
[Arguments: -import -storepass "storepass" -keystore "C:\Program Files\Java\jre1.8.0_261\lib\security\cacerts" -alias "ourcert.crt" -file "\\unc\drive\share\path\ourcert.crt" -noprompt]
Certificate was added to keystore   <-- This line here
  Java Cert Installed in Store.

Я использую метод & $ Command $ args для вызова всех внешних команд, а ниже - сценарий, который я выполняю.

# This function is used all over the place to streamline the external command execution of
# KeyTool, Sonar Scanner, and MSBuild
function Invoke([String] $command, [String[]] $arguments)
{  
    Write-Host "    [Commnad:   $command]"
    Write-Host "    [Arguments: $arguments]"

    &$command $arguments
}

function ValidateKeyTool() 
{ # Our developers may or maynot have the same version of java so this is to find the most recent version on their system
    $path = [System.IO.Directory]::GetFiles("C:\Program Files (x86)\Java", "keytool.exe", [System.IO.SearchOption]::AllDirectories);
    $path = $path + [System.IO.Directory]::GetFiles("C:\Program Files\Java", "keytool.exe", [System.IO.SearchOption]::AllDirectories);
    $path = $path | Sort-Object -Descending;
    $script:KeyTool = $path | Select -First 1;
    $script:KeyStore = (Join-Path -Path (Split-Path (Split-Path $path)) -ChildPath "lib\security\cacerts");
    return ([System.IO.File]::Exists($KeyTool) -and [System.IO.File]::Exists($KeyStore));
}


function CheckCertExists() 
{
    if (ValidateKeyTool) 
    {
        $args = @("-list", "-storepass", """storepass""", "-keystore", """$KeyStore""", "-alias", """ourcert.crt""");
        Invoke $KeyTool $args | Out-Null;
        return ($LastExitCode -eq 0)
    }
    else 
    {
        throw "Unable to determine Java KeyTool or KeyStore";
    }
}

function InstallCert()
{
    if (!(CheckCertExists))
    {
        $args = @("-import", "-storepass", """storepass""", "-keystore", """$KeyStore""", "-alias", """ourcert.crt""", "-file", $CertFile, "-noprompt");
        Invoke $KeyTool $args | Out-Null;  #this DOESN'T Work, the Out-Null doesn't trap the output
        if ($LastExitCode -eq 0) 
        {
            Write-Host "  Java Cert Installed in Store."
        }
        else 
        {
            throw "Error occured attempting to Install the Java Cert into the Store."
        }
    }
    else 
    {
        Write-Host "  Java Cert already installed."
    }    
}

Все исполнения KeyTool с | Out-Null перехватывает вывод, как ожидалось, для -list, для -delete, но НЕ для -import. Независимо от того, что я пробовал, keytool с -import всегда выдает, что сертификат был добавлен в сообщение вывода хранилища ключей. Я хочу подавить его и уйти из $ LastExitCode только для успеха / неудачи.


person JaedenRuiner    schedule 20.10.2020    source источник


Ответы (1)


Вероятно, причина в том, что сообщение отправляется другому выходной поток. Например, вместо вывода сообщения в стандартный поток успеха (1) он может выводить сообщение в поток ошибок (2) или поток предупреждений (3) или в другой поток. Конвейерная обработка в | Out-Null будет обрабатывать только поток успеха, например:

PS C:\> Write-Output "hi" | Out-Null
PS C:\>
PS C:\> Write-Warning "hi" | Out-Null
WARNING: hi

Подход тупого молотка для подавления всех сообщений из всех потоков заключается в следующем: перенаправить все потоки вот так:

Invoke $KeyTool $args *> $null

Более приятный подход заключается в том, что если вы знаете, в какой поток отправляется сообщение (например, поток ошибок (2)), вы можете перенаправить отдельные потоки. Для этого нужно перенаправить поток ошибок (2) в поток успеха (1), а затем поток успеха (1) на $null:

Invoke $KeyTool $args 2>&1 > $null
person HAL9256    schedule 20.10.2020