有没有一种在PowerShell中显示弹出消息框的方法,可以兼容Windows系统和MacOS?

9

我知道你可以在PowerShell版本5上做类似这样的事情(如下所示),但是否有办法在Windows和Mac OS平台上重现弹出消息框?

$ButtonType = [System.Windows.Forms.MessageBoxButtons]::OK

$MessageIcon = [System.Windows.Forms.MessageBoxIcon]::Information

$MessageBody = "Message Body goes here"

$MessageTitle = "Title"

$Result = [System.Windows.Forms.MessageBox]::Show($MessageBody,$MessageTitle,$ButtonType,$MessageIcon)

上面代码的输出

enter image description here


目前,唯一真正跨平台的消息显示方式是使用控制台。 - Lee_Dailey
在网络浏览器中显示? - js2010
1个回答

8

下面定义的Show-MessageBox函数提供了在Windows和macOS上的消息框功能,其模仿了WinForms的MessageBox类。

示例:

# Message box with custom message, OK button only, and default title and icon
$null = Show-MessageBox 'some message'

# Message box with custom message and title, buttons OK and cancel, and 
# the Stop icon (critical error)
# Return value is the name of the button chosen.
$buttonChosen = Show-MessageBox 'some message' 'a title' -Buttons OKCancel -Icon Stop

语法(为了易读性跨多行):
Show-MessageBox [-Message] <string> [[-Title] <string>] 
                [[-Buttons] {OK | OKCancel | AbortRetryIgnore | YesNoCancel | YesNo | RetryCancel}] 
                [-Icon {Information | Warning | Stop}] 
                [-DefaultButtonIndex {0 | 1 | 2}]

注意:
在macOS上,使用AppleScript的display alert命令创建消息框。
尽管此命令分别区分了信息、警告和关键性,但前两个显示相同的图标——一个文件夹,而后者则仅用感叹号覆盖文件夹图标。
为了跨平台一致性,输出值是一个字符串,即用户按下的按钮名称。
- DefaultButtonIndex是按钮的0基索引,当用户只按Enter时将按下该按钮。 - Windows:如果存在“取消”按钮,则按Esc键。 - macOs:如果存在“否”、“中止”或“取消”按钮,并且它不是默认按钮,则按Esc键。
Show-MessageBox源代码:
function Show-MessageBox {
  [CmdletBinding(PositionalBinding=$false)]
  param(
    [Parameter(Mandatory, Position=0)]
    [string] $Message,
    [Parameter(Position=1)]
    [string] $Title,
    [Parameter(Position=2)]
    [ValidateSet('OK', 'OKCancel', 'AbortRetryIgnore', 'YesNoCancel', 'YesNo', 'RetryCancel')]
    [string] $Buttons = 'OK',
    [ValidateSet('Information', 'Warning', 'Stop')]
    [string] $Icon = 'Information',
    [ValidateSet(0, 1, 2)]
    [int] $DefaultButtonIndex
  )

  # So that the $IsLinux and $IsMacOS PS Core-only
  # variables can safely be accessed in WinPS.
  Set-StrictMode -Off

  $buttonMap = @{ 
    'OK'               = @{ buttonList = 'OK'; defaultButtonIndex = 0 }
    'OKCancel'         = @{ buttonList = 'OK', 'Cancel'; defaultButtonIndex = 0; cancelButtonIndex = 1 }
    'AbortRetryIgnore' = @{ buttonList = 'Abort', 'Retry', 'Ignore'; defaultButtonIndex = 2; ; cancelButtonIndex = 0 }; 
    'YesNoCancel'      = @{ buttonList = 'Yes', 'No', 'Cancel'; defaultButtonIndex = 2; cancelButtonIndex = 2 };
    'YesNo'            = @{ buttonList = 'Yes', 'No'; defaultButtonIndex = 0; cancelButtonIndex = 1 }
    'RetryCancel'      = @{ buttonList = 'Retry', 'Cancel'; defaultButtonIndex = 0; cancelButtonIndex = 1 }
  }

  $numButtons = $buttonMap[$Buttons].buttonList.Count
  $defaultIndex = [math]::Min($numButtons - 1, ($buttonMap[$Buttons].defaultButtonIndex, $DefaultButtonIndex)[$PSBoundParameters.ContainsKey('DefaultButtonIndex')])
  $cancelIndex = $buttonMap[$Buttons].cancelButtonIndex

  if ($IsLinux) { 
    Throw "Not supported on Linux." 
  }
  elseif ($IsMacOS) {

    $iconClause = if ($Icon -ne 'Information') { 'as ' + $Icon -replace 'Stop', 'critical' }
    $buttonClause = "buttons { $($buttonMap[$Buttons].buttonList -replace '^', '"' -replace '$', '"' -join ',') }"

    $defaultButtonClause = 'default button ' + (1 + $defaultIndex)
    if ($null -ne $cancelIndex -and $cancelIndex -ne $defaultIndex) {
      $cancelButtonClause = 'cancel button ' + (1 + $cancelIndex)
    }

    $appleScript = "display alert `"$Title`" message `"$Message`" $iconClause $buttonClause $defaultButtonClause $cancelButtonClause"            #"

    Write-Verbose "AppleScript command: $appleScript"

    # Show the dialog.
    # Note that if a cancel button is assigned, pressing Esc results in an
    # error message indicating that the user canceled.
    $result = $appleScript | osascript 2>$null

    # Output the name of the button chosen (string):
    # The name of the cancel button, if the dialog was canceled with ESC, or the
    # name of the clicked button, which is reported as "button:<name>"
    if (-not $result) { $buttonMap[$Buttons].buttonList[$buttonMap[$Buttons].cancelButtonIndex] } else { $result -replace '.+:' }
  }
  else { # Windows
    Add-Type -Assembly System.Windows.Forms        
    # Show the dialog.
    # Output the chosen button as a stringified [System.Windows.Forms.DialogResult] enum value,
    # for consistency with the macOS behavior.
    [System.Windows.Forms.MessageBox]::Show($Message, $Title, $Buttons, $Icon, $defaultIndex * 256).ToString()
  }

}

$IsLinux和$IsMacOS是PowerShell核心自带的自动变量吗? - rshelat
@rshelat:是的,它们是(连同$IsWindows)-请注意,我刚刚进行了更新,以确保代码在Windows PowerShell中也能正常工作(Set-StrictMode -Version 1-> Set-StrictMode -Off),因为这些变量未定义。 - mklement0
@Sied,你有一个打字错误(在.Form.MessageBox之间缺少s)。 - mklement0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接