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",[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","""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."
    }    
}

所有带有“ | Out-Null”的KeyTool执行都会按预期捕获输出,对于-list,对于-delete,但对于-import不是。不管我尝试了什么,带有“ -import”的keytool始终会产生“证书已添加到keystore”的输出消息。我想隐瞒它,只将$ LastExitCode设置为成功/失败。

解决方法

可能是因为该消息正在输出到另一个output stream。对于前。代替将消息输出到标准成功流(1),它可能是将消息输出到错误流(2)或警告流(3)或另一个。流水到| Out-Null只会处理成功流,例如:

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

抑制所有流中所有消息的钝器方法是redirect all the streams,如下所示:

Invoke $KeyTool $args *> $null

“更精细”的方法是,如果您知道将消息发送到哪个流(例如,错误流(2)),则可以重定向各个流。通过将错误流(2)重定向到成功流(1),然后将成功流(1)重定向到$null

Invoke $KeyTool $args 2>&1 > $null