【问题标题】:How to run interactive commands in another application window from powershell如何从 powershell 在另一个应用程序窗口中运行交互式命令
【发布时间】:2013-06-20 04:07:19
【问题描述】:

我有另一个命令行程序,我从我的 powershell 脚本调用它,并希望在从 power shell 打开它后在该窗口中运行一些交互式命令。

换句话说-我做了一个Invoke-Item $link_to_app,它为该应用程序打开了交互式命令行,现在我想在powershell脚本中使用特定于应用程序的命令。

例如app.exe -help 调用app.exe 的帮助命令。

任何指针都会有所帮助。谢谢!

【问题讨论】:

    标签: powershell powershell-2.0 powershell-remoting


    【解决方案1】:

    试试这个:

    $app = 'app.exe -help'
    Invoke-Expression $app
    

    经过测试,它按预期工作:

    $pingTest = 'ping -n 8 127.0.0.1'
    Invoke-Expression $pingTest
    

    根据您的扩​​展说明,您似乎想在同一命令提示符下运行 2 个命令。这是可能的,但是,我不确定它是否适用于您的场景。例如:

    test1.bat: echo "hello!"

    test2.bat:echo "goodbye!"

    $batchTest = "test1.bat && test2.bat"
    cmd /c $batchTest 
    

    输出:

    D:\Test>echo "hello!"
    "hello!"
    
    D:\Test>echo "goodbye!"
    "goodbye!"
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢凯尔。让我详细说明这个问题。如果我从 powershell 打开一个 commnad 窗口,然后将 shell 特定命令作为两个步骤提供,则上述命令不起作用。我正在尝试这样的事情来从应用程序窗口发出命令: $help = "app help" $cmdline = "app.lnk" (使用所有 envt 设置打开 shell 的快捷方式) Invoke-Expression $cmdline $help 我期待要调用的 $cmdline 以及要从该 shell 调用的其余命令。这可能吗?
    • 有什么理由不能在 powershell 而不是 cmd 中设置环境设置,然后简单地从 powershell 中调用 $help?
    • 感谢您的回复。脚本使用上述方法无限期挂起。我不确定如何设置所有环境变量 - 通常我只是使用快捷方式启动应用程序
    • 本文介绍如何在 PS 中使用 Set\Use 环境变量:technet.microsoft.com/en-us/library/ff730964.aspx
    【解决方案2】:

    我不确定,但我认为您想要的是能够让脚本向另一个程序发送输入并从另一个程序接收输出,其中另一个程序具有您的脚本需要能够与之交互的“状态” .下面是一个驱动 CMD.EXE 的脚本示例。 CMD 有状态,例如当前工作目录和环境变量。

    请注意,您可以按照其他回答者的建议进行操作,然后启动程序,在命令行上提供所有输入,然后对输出执行您需要的操作。但是对于 CMD,如果您需要根据输出做出决定,然后根据先前的输出为 CMD 提供更多输入,则必须在每次执行 CMD 之间保存和恢复环境和当前工作目录。下面的方法不需要。

    但是,下面的方法确实有几个注意事项。首先它依赖于PS“主机”。它在命令行 PS 上(对我来说)有效,但在 ISE 中无效。这种依赖性是由于使用原始主机接口来确定密钥是否可用。其次,它取决于时间,基于 CMD 的行为(或您使用的任何东西)。您将在脚本中看到一些睡眠命令。我必须尝试全部 来让这个脚本在输入该命令时显示特定子命令的 CMD 输出,而 CMD 在输入另一个命令后给出先前命令的输出。注释掉 sleeps 看看我的意思。三是容易挂Powershell。在任务管理器中杀死 CMD 可以让你摆脱挂起状态,我不得不这样做很多次。

    您会看到我添加了几个脚本专门处理的命令。这是为了证明命令的输入可以来自 PS 脚本(而不是键盘输入)。

    $global:ver++
    if ($ExecutionContext.Host.name -match "ISE Host$") {
        write-warning "This script relies on RawUI functionality not implemented in ISE"
        return
    }
    $in = $null
    $flExiting = $false
    
    $doDebug = $false
    function dot-debug {param($color) 
      if ($doDebug) {
        write-host "." -NoNewline -ForegroundColor $color
      }
    }
    #function dot-debug {param($color) }
    
    $procInfo = new diagnostics.processstartinfo
    $procInfo.RedirectStandardOutput=1
    $procInfo.RedirectStandardInput=1
    $procInfo.RedirectStandardError=1
    $procInfo.FileName="cmd.exe"
    $procInfo.UseShellExecute=0
    $p=[diagnostics.process]::start($procInfo)
    $outBuf = new char[] 4096
    write-host "Version $ver"
    sleep -Milliseconds 300
    do {
       dot-debug red
    
      # This while loop determines whether input is available from either
      #  CMD's standard output or from the user typing. You don't want to
      #  get stuck waiting for input from either one if it doesn't really have input.
    
      :WaitIO  while ($true) {
        if (-1 -ne $p.StandardOutput.peek()) {
          dot-debug yellow
          $cnt = $p.StandardOutput.read( $outBuf, 0, 4096)
        } else {
          dot-debug Gray
          if ($host.ui.rawui.KeyAvailable -or $flExiting) {break}
        }
        $str = $outBuf[0..($cnt-1)] -join ""
        write-host "$str" -NoNewline
    
        while (-1 -eq ($rc =$p.StandardOutput.peek())) {
          if ($host.ui.rawui.KeyAvailable -or $flExiting) {
            break WaitIO
          }
          dot-debug DarkGray
          sleep -milli 200
        }
        dot-debug cyan
      }
      dot-debug green
    
      # read-host echoes input, so commands get echoed twice (cmd also echoes)
      #
      # $host.ui.rawui.ReadKey("NoEcho, IncludeKeyDown") doesn't work on ISE,
      # but does work in the PS cli shell
      if ($in -ne "exit") {$in = read-host}
      if ($in -eq "td") { # toggle debug
        $doDebug = -not $doDebug
        $p.StandardInput.WriteLine( "echo debug toggled")
        sleep -milli 300
        continue
      }
      if ($in -eq "xxx") {
        # Example of script driven output being sent to CMD
        $p.StandardInput.WriteLine( "echo This is a very long command that I do not want to have to type in everytime I want to use it")
        # You have to give CMD enough time to process command before you read stdout,
        # otherwise stdout gets "stuck" until the next time you write to stdin
        sleep -milli 1
        continue
      }
      if ($in -eq "exit") {
        $flExiting = $true
        $p.StandardInput.WriteLine($in)
        continue
      }
    
      foreach ($char in [char[]]$in) {
        $p.StandardInput.Write($char)
      }
      $p.StandardInput.Write("`n")
      sleep -milli 1
    
    } until ($p.StandardOutput.EndOfStream)
    

    【讨论】:

    • 感谢您的回复。 ISE 听到的意思是什么?我正在尝试运行和理解脚本命令以满足我的要求。将发布进度。
    • Powershell 集成脚本环境。它有点像 Visual Studio for Powershell(但更简单)。如果您从开始菜单中查看附件、Powershell,您将看到一个启动“Windows Powershell ISE”的图标。
    猜你喜欢
    • 1970-01-01
    • 2010-11-04
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 2011-11-22
    相关资源
    最近更新 更多