.psm1模块中Cmdlet函数为何吞掉&dotnet的输出?
问题描述
原本直接在.ps1文件中执行& dotnet命令能正常显示输出,但将这段逻辑封装到.psm1模块的Build-Android Cmdlet函数后,函数功能正常,但& dotnet的输出不再显示。经排查该问题与终端环境相关:在PowerShell Core 7环境下,终端不会显示&表达式的输出,但PowerShell本身可以,且无法将代码移回.ps1文件。
尝试过的无效方法
& dotnet *>&1& dotnet | Out-Host& dotnet | Write-Host
相关代码
functions.psm1
function Build-Android { [CmdletBinding()] param( [Parameter(Mandatory,ValueFromPipeline)] [string] $KeyStorePath, [Parameter(Mandatory,ValueFromPipeline)] [string] $SignPassword, [Parameter(Mandatory,ValueFromPipeline)] [string] $ProjectPath, [Parameter(Mandatory,ValueFromPipeline)] [string] $PublishDirectory ) [Environment]::SetEnvironmentVariable('PCR3PW', $SignPassword, 'Process') $keyAlias = "PCR3" $keyPass = "env:PCR3PW" $storePass = "env:PCR3PW" $publishCode = "dotnet publish $ProjectPath -f net7.0-android -c Release -o `"$PublishDirectory`" -p:AndroidKeyStore=true -p:AndroidSigningKeyStore=$KeyStorePath -p:AndroidSigningKeyAlias=$keyAlias -p:AndroidSigningKeyPass=$keyPass -p:AndroidSigningStorePass=$storePass" Write-Host "$publishCode" -ForegroundColor DarkGreen &dotnet publish $ProjectPath -f net7.0-android -c Release -o `"$PublishDirectory`" -p:AndroidKeyStore=true -p:AndroidSigningKeyStore=$KeyStorePath -p:AndroidSigningKeyAlias=$keyAlias -p:AndroidSigningKeyPass=$keyPass -p:AndroidSigningStorePass=$storePass if($LASTEXITCODE -ne 0) throw "There was an issue running the specified dotnet command." $apk = Get-ChildItem "$PublishDst" -Filter "*.apk" | %{$_.FullName} return $apk }
MyScript.ps1
param ( [Parameter(Mandatory=$true, HelpMessage="发布过程的签名密码")] [string]$SignPassword, [Parameter(Mandatory=$true, HelpMessage="APK发布的目标文件夹")] [string]$PublishDst ) Import-Module ".\functions.psm1" $keyStore = [System.Uri]::new([System.Uri]::new("$PSScriptRoot\.", [System.UriKind]::Absolute), [System.Uri]::new("PCR3.keystore", [System.UriKind]::Relative)).LocalPath $apkProject = [System.Uri]::new([System.Uri]::new("$PSScriptRoot\.", [System.UriKind]::Absolute), [System.Uri]::new("..\src\MyProject\MyProject.csproj", [System.UriKind]::Relative)).LocalPath $apkPath = Build-Android -KeyStorePath $keyStore -SignPassword $SignPassword -ProjectPath $apkProject -PublishDirectory $PublishDst
解决方案
在模块函数中,需要将dotnet命令的标准输出和错误流同时重定向,再通过Out-Host强制输出到控制台。修改执行dotnet的代码行如下:
# 重定向所有流到标准输出,再输出到主机 & dotnet publish $ProjectPath -f net7.0-android -c Release -o `"$PublishDirectory`" -p:AndroidKeyStore=true -p:AndroidSigningKeyStore=$KeyStorePath -p:AndroidSigningKeyAlias=$keyAlias -p:AndroidSigningKeyPass=$keyPass -p:AndroidSigningStorePass=$storePass 2>&1 | Out-Host
若需要同时捕获输出内容并显示,可先捕获再输出:
# 捕获所有输出,再输出到主机 $dotnetOutput = & dotnet publish $ProjectPath -f net7.0-android -c Release -o `"$PublishDirectory`" -p:AndroidKeyStore=true -p:AndroidSigningKeyStore=$KeyStorePath -p:AndroidSigningKeyAlias=$keyAlias -p:AndroidSigningKeyPass=$keyPass -p:AndroidSigningStorePass=$storePass 2>&1 $dotnetOutput | Out-Host
原理:模块函数默认会将命令输出作为返回值的一部分捕获,Out-Host可强制将内容直接输出到终端,绕过PowerShell的输出捕获机制;2>&1将错误流合并到标准输出,确保错误信息也能正常显示。
内容的提问来源于stack exchange,提问作者Dbl
相关产品推荐
相关产品推荐

