【问题标题】:How can I suppress part of an external program's prompt when called from powershell?从 powershell 调用时,如何抑制部分外部程序的提示?
【发布时间】:2022-09-23 02:19:20
【问题描述】:

我有一个 powershell 脚本,除其他外,有时需要调用第三方应用程序 (TPA) 来触发登录提示。我的问题是 TPA 的密码prompt 包括额外的警告行,我不需要弄乱我的 UX。我可以(并且正在)通过用户名通过$TpaParams 到应用程序就好了,但我更愿意将处理用户密码的工作留给TPA 本身。

密码警告通过 STDOUT(而不是 STDERR)通过,这与必要的提示文本通过的地方相同。如果我重定向整个事情(Out-Null 等),则登录失败,因为它无法要求输入密码。

我希望能够(仅)显示提示并删除警告。如果做不到这一点,我很乐意将警告文本(使用Write-Host)重新着色为深灰色,使其不那么引人注目(我的脚本中已经设置了多种颜色仅出于此目的)。

其他(可能有帮助?)数据:

  • TpaCmd 是一个 CMD 文件,其中包含大量错误检查以及一行实际代码:\"%JAVACMD%\" -jar \"%JARFILE%\" %*
  • 我无法从 Java 或 TPA 的作者 (IBM) 那里找到任何帮助,要么
  • 我无法更改 JAR 文件;它必须保持完整。

谁能想到在powershell端做到这一点的方法?

我尝试过但没有成功的事情:

无重定向

$TpaCmd login $TpaParams

Password not passed [...]  
Password :  

分别重定向 Out/Err
$TpaCmd login $TpaParams 1> $TmpOut 2> $TmpErr

(null output)  

$TmpOut 包含

Password not passed [...]  

$TmpErr 包含

tpapp.cmd : java.lang.NullPointerException  
At D:\\path\\to\\powershell\\DoStuff.ps1:288 char:3  
+         &  ${TpaCmd} login --verbose ${TpaParams} 1> $TmpOut  
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
    + CategoryInfo          : NotSpecified: (java.lang.NullPointerException:String) [], RemoteException  
    + FullyQualifiedErrorId : NativeCommandError  
  
    at com.tpappname.ds.client.DeployCLI.main(DeployCLI.java:246)  
java.lang.NullPointerException  

Redirect Out,离开 Err
$TpaCmd login $TpaParams 1> $TmpOut
$TmpOut 包含

Password not passed as command line property password or set in environment, DS_PASSWORD  

NullPointerException 错误(上)显示到屏幕上

重定向错误,省略
$TpaCmd login $TpaParams 2> $TmpErr

Password not passed [...]  
Password :  

$TmpErr 为空

重定向一切
$TpaCmd login $TpaParams *> $TmpAll

(null output)  

$TmpAll 包含密码警告和 NPE

Password not passed [...]
Retry with --verbose flag for more info.
tpapp.cmd : java.lang.NullPointerException  
    At D:\\path\\to\\powershell\\DoStuff.ps1:288 char:3  
    +         &  ${TpaCmd} login --verbose ${TpaParams} 1> $TmpOut  
    +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
        + CategoryInfo          : NotSpecified: (java.lang.NullPointerException:String) [], RemoteException  
        + FullyQualifiedErrorId : NativeCommandError  
      
        at com.tpappname.ds.client.DeployCLI.main(DeployCLI.java:246)  
    java.lang.NullPointerException  
  • 如果将输出通过管道传输到Select-Object -Skip 1 会怎样?
  • @DougMaurer 虽然这将是一个简单的解决方案,但它会导致另一个 NullPointerException 错误:java.lang.NullPointerException Retry with --verbose flag for more info.

标签: powershell io-redirection


【解决方案1】:

根据I'd prefer to leave the handling the user's password to the TPA itself 的含义,可能会有更多解决方案。

临时密码变量:以下可能是传递密码的简单方法

$Password = Read-Host "Enter Password"
$TpaParms += " -password $Password"
$TpaCmd login $TpaParams

如果您不希望变量中的密码,您可以尝试使用没有密码变量:

$TpaCmd login "$TpaParms -password $(Read-Host "Enter Password")"

由于我没有您的程序和您的$TpaParms 来测试我的脚本,因此我尝试通过错误消息和错误代码查找文档,并在该页面上找到了https://www.ibm.com/docs/en/urbancode-deploy/7.0.3?topic=reference-command-format 用于密码的语法。 -username [username] 必须在 $TpaParms 中才能完成这项工作。

【讨论】:

  • 您的第一个解决方案正是我不想做的;我不希望我的脚本负责保护用户密码的安全。话虽如此,我喜欢您的第二个选项,但这会在输入密码时在屏幕上显示密码条目。我会使用 -MaskInput 标志,但显然我们的 PS 版本已经过时了,而且该标志不可用! :(
【解决方案2】:

在做了更多的研究并使用上面的答案作为灵感之后,我决定这样做:

$UserEncryptedPassword = Read-Host "Enter login password" -AsSecureString
& $TpaCmd login $TpaParams -password ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR(${UserEncryptedPassword})))

谢谢大家的鼓励和帮助!

【讨论】:

  • 很好,不过为了简单起见,我建议[pscredential]::new('unused', $UserEncryptedPassword).GetNetworkCredential().Password。顺便说一句:严格来说,应该是PtrToStringBSTR,而不是PtrToStringAuto(详见this answer)。
【解决方案3】:

你需要使用一个技巧来让它工作,这取决于你知道要忽略的行的内容批处理文件用于提示输入密码的提示字符串:

& $TpaCmd login $TpaParams |
  ForEach-Object { 
    if ($_ -match '\bPassword not passed\b') { # Line to ignore
      # Simulate the prompt that the batch file will show next, but
      # initially invisibly.
      Write-Host -NoNewLine 'Password : '
    } elseif ($_ -match '^Password : (.*)') { # The line with the prompt
      # Print the part of the line *after* the prompt string, which is
      # the *next* statement's output.
      $Matches.1 
    } else { # All other lines: pass through
      $_
    }
}

【讨论】:

  • 随着软件的更新,这将承担更改提示不再被屏蔽的风险。谢谢你,无论如何!
  • @Sas,如果提示字符串发生更改,用户键入的内容仍将被屏蔽,但提示字符串本身将不再从输出中删除。但是,我同意这是一个脆弱的解决方案,听起来您找到了一个更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 2011-11-10
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多