1

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

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

但是当我尝试关闭窗口时:

Popup-Message -close

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

我假设这与将函数保持在全局范围内有关,但我不知道如何使用表单执行此操作

4

3 回答 3

1

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

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"
}
}
于 2019-03-06T00:32:23.237 回答
1

kpogue 的有用答案很好地解释了您的问题,并提供了一个有效的解决方案,但由于依赖于全局变量而不是最佳的。

让我建议一种不同的方法,您使用一个函数来简单地定义表单并返回该定义,您可以根据需要在其上调用.Show().Close() 方法,但请注意,该.Show()方法被覆盖 viaAdd-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 会话退出,会话中创建的任何弹出窗口都会自动关闭。

注意事项

  • 请注意,由于使用了该.Show()方法(无需额外的努力),用户将无法与弹出窗口进行交互,尤其是甚至无法 移动窗口或手动关闭它。

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

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

    • 如果您使用这种方法,您应该[System.Windows.Forms.Cursor]::Hide()从函数中删除调用。
于 2019-03-06T02:27:21.003 回答
0

我们可以使用一行来创建带有 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)
于 2019-03-06T18:56:10.900 回答