在 Powershell 中创建弹出消息

Create a popup message in Powershell

我正在尝试制作一个允许我弹出请稍候消息的功能运行更多脚本然后关闭弹出窗口

Function Popup-Message {

    param ([switch]$show,[switch]$close)

    Add-Type -AssemblyName System.Windows.Forms  

    # Build Form
    $objForm = New-Object System.Windows.Forms.Form
    $objForm.Text = "Test"
    $objForm.Size = New-Object System.Drawing.Size(220,100)

    # Add Label
    $objLabel = New-Object System.Windows.Forms.Label
    $objLabel.Location = New-Object System.Drawing.Size(80,20) 
    $objLabel.Size = New-Object System.Drawing.Size(100,20)
    $objLabel.Text = "Hi there!"
    $objForm.Controls.Add($objLabel)



    If ($show)
    {
        $objForm.Show() | Out-Null
        $global:test = "Show"
    }


    If ($close)
    {
        # destroy form
        $objForm.Close() | Out-Null
        $global:test = "Close"
    }
}

然后我可以通过以下方式显示弹出窗口:

Popup-Message -show

此时我可以看到 $test 变量为 Show

但是当我尝试关闭 window 时:

Popup-Message -close

但是弹窗window不会关闭 如果我再次查看 $test 它将显示为 Close

我假设这与将函数保留在全局范围内有关,但我不知道如何使用表单来做到这一点

您将在每次调用 Popup-Message 时创建一个新的表单实例。因此,表单没有关闭,因为您试图关闭一个从未打开过的新表单。与此同时,旧表格不再有任何人引用它,它只是坐在 space 中。您可以创建一个全局引用,如下所示,可能有更巧妙的方法可以做到这一点。

Function Popup-Message {

param ([switch]$show,[switch]$close)

Add-Type -AssemblyName System.Windows.Forms  

# Build Form
if ($Global:objForm -eq $null){
$Global:objForm = New-Object System.Windows.Forms.Form
$Global:objForm.Text = "Test"
$Global:objForm.Size = New-Object System.Drawing.Size(220,100)

# Add Label
$Global:objLabel = New-Object System.Windows.Forms.Label
$Global:objLabel.Location = New-Object System.Drawing.Size(80,20) 
$Global:objLabel.Size = New-Object System.Drawing.Size(100,20)
$Global:objLabel.Text = "Hi there!"
$Global:objForm.Controls.Add($objLabel)
}



If ($show)
{
    $Global:objForm.Show() | Out-Null
    $global:test = "Show"
}


If ($close)
{
    # destroy form
    $Global:objForm.Close() | Out-Null
    $global:test = "Close"
}
}

很好地解释了您的问题并提供了一个有效但由于依赖 全局变量.

而不是最佳的解决方案

让我建议一种不同的方法,您 使用一个函数来简单地 定义 表单和 return 该定义,可以根据需要调用.Show().Close()方法,但注意.Show() 方法通过 Add-Member 覆盖以包含对 [System.Windows.Forms.Application]::DoEvents() 的调用,以确保正确绘制表单。

function New-PopUpForm {

  Add-Type -AssemblyName System.Windows.Forms  

  # Create the form.
  $objForm = New-Object System.Windows.Forms.Form -Property @{
    Text            = "Test"
    Size            = New-Object System.Drawing.Size 220, 100
    StartPosition   = 'CenterScreen' # Center on screen.
    FormBorderStyle = 'FixedSingle'  # fixed-size form
    # Remove interaction elements (close button, system menu).
    ControlBox      = $false
  }

  # Create a label...
  $objLabel = New-Object System.Windows.Forms.Label -Property @{
    Location = New-Object System.Drawing.Size 80, 20
    Size     = New-Object System.Drawing.Size 100, 20
    Text     = "Hi there!"
  }

  # ... and add it to the form.
  $objForm.Controls.Add($objLabel)

  # Override the `.Show()` method to include
  # a [System.Windows.Forms.Application]::DoEvents(), so as 
  # to ensure that the form is properly drawn.
  $objForm | Add-Member -Force -Name Show -MemberType ScriptMethod -Value {
    $this.psbase.Show() # Call the original .Show() method.
    # Activate the form (focus it).
    $this.Activate()
    [System.Windows.Forms.Application]::DoEvents() # Ensure proper drawing.
  }

  # Since this form is meant to be called with .Show() but without 
  # a [System.Windows.Forms.Application]::DoEvents() *loop*, it
  # it is best to simply *hide* the cursor (mouse pointer), so as not
  # to falsely suggest that interaction with the form is possible
  # and so as not to end up with a stuck "wait" cursor (mouse pointer) on 
  # the first instantiation in a session.
  [System.Windows.Forms.Cursor]::Hide()

  # Return the form.
  return $objForm
}

然后您可以按如下方式使用函数:

$form = New-PopupForm

$form.Show() 

# ...

$form.Close()

:

  • 调用.Close()后,存储在$form中的表单实例将被处理掉,无法重复使用——只需再次调用New-PopupForm来创建一个新实例.

  • 如果 PowerShell 会话 运行 您的脚本 退出 ,会话中创建的任何弹出窗口 windows 会自动关闭。

注意事项

  • 请注意,由于使用了 .Show() 方法(无需额外努力),用户将无法互动 与弹出 window,特别是为了 移动 window 或关闭它 手动.

    • 如果,例如在您的情况下,window 不打算与之交互,但这不是问题。
    • 上面的设置 ControlBox = $false 删除了 window 的关闭按钮和系统菜单,以明确表示无法进行交互。
    • [System.Windows.Forms.Cursor]::Hide()隐藏光标(鼠标指针)有同样的目的。
      • 注意: 隐藏光标会导致显示“等待”光标(表示表单正忙于处理某些事情)无限期地将鼠标悬停在表单上,​​但奇怪的是仅针对会话中创建的第一个实例。据我所知,避免这种情况的唯一方法是在调用 .Show() 后进入事件循环,如上一个要点所述。
  • 相比之下,.ShowDialog()允许交互,但阻止进一步执行 直到 window 被用户关闭。

  • 如果您需要结合这两种方法 - 允许用户在继续做的同时与window交互在您的 PowerShell 脚本中进行处理 - 您需要 循环调用 [System.Windows.Forms.Application]::DoEvents() ,如 [=29] 所示=].

    • 如果您使用这种方法,您应该从函数中删除 [System.Windows.Forms.Cursor]::Hide() 调用。

我们可以使用 One line 创建带有 Wscript.Shell COM 对象的 powershell 弹出窗口

语法:intButton = objShell.Popup(strText,[nSecondsToWait],[strTitle],[nType])

#creating object os WScript
$wshell = New-Object -ComObject Wscript.Shell -ErrorAction Stop
#invoking the POP method using object
$wshell.Popup("please wait message?",5,"Wait Until Scrip execution",48+4)