首页 > 解决方案 > 将 Powershell-Console 从 WinForms 带到前面

问题描述

我试图将我的 powershell 控制台放在前面,即使它已最小化。我发现以下代码:

function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '

  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd) 
}
Show-Process -Process (Get-Process -Id $pid) 

它工作正常,但是当我从按钮单击事件调用函数时,控制台不会显示。问题是什么?使用 WinForms GUI 时,有没有办法将 powershell 控制台放在前面?

这是示例 GUI 代码:

function Show-Process($Process, [Switch]$Maximize)
{
  $sig = '
    [DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
    [DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);
  '

  if ($Maximize) { $Mode = 3 } else { $Mode = 4 }
  $type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
  $hwnd = $process.MainWindowHandle
  $null = $type::ShowWindowAsync($hwnd, $Mode)
  $null = $type::SetForegroundWindow($hwnd) 
}

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '446,266'
$Form.text                       = "Form"
$Form.TopMost                    = $false

$Button1                         = New-Object system.Windows.Forms.Button
$Button1.text                    = "button"
$Button1.width                   = 60
$Button1.height                  = 30
$Button1.location                = New-Object System.Drawing.Point(75,29)
$Button1.Font                    = 'Microsoft Sans Serif,10'

$Button1.Add_Click({
    Show-Process -Process (Get-Process -Id $pid) 
})

$Form.controls.AddRange(@($Button1))

[void]$Form.ShowDialog()

标签: windowsformspowershelluser-interfaceconsole

解决方案


感谢@iRon的回答,我能够弄清楚我想要它。对于任何好奇的人,问题是,只要不调用 ShowDialog,您就只能获得控制台 MainwindowHandle。所以我将控制台句柄保存在一个变量中,并使用 Form_Shown 事件来获取表单窗口句柄,因为 Form_Load 仍然返回控制台句柄。

$sig = '
[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")] public static extern int SetForegroundWindow(IntPtr hwnd);'
$type = Add-Type -MemberDefinition $sig -Name WindowAPI -PassThru
[IntPtr]$handleConsole = (Get-Process -Id $pid).MainWindowHandle
[void]$type::ShowWindowAsync($handleConsole, 4);[void]$type::SetForegroundWindow($handleConsole)

Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()

$Form                            = New-Object system.Windows.Forms.Form
$Form.ClientSize                 = '446,266'
$Form.text                       = "Form"
$Form.TopMost                    = $false

$Form.Add_Shown({
 $global:handleForm = (Get-Process -Id $pid).MainWindowHandle
})

$Button1                         = New-Object system.Windows.Forms.Button
$Button1.text                    = "Clone ad-USer"
$Button1.width                   = 60
$Button1.height                  = 30
$Button1.location                = New-Object System.Drawing.Point(75,29)
$Button1.Font                    = 'Microsoft Sans Serif,10'

$Button1.Add_Click({
    [void]$type::ShowWindowAsync($handleConsole, 4);[void]$type::SetForegroundWindow($handleConsole)
    Read-Host -Prompt "Please Enter a Value"
    [void]$type::ShowWindowAsync($global:handleForm, 4);[void]$type::SetForegroundWindow($global:handleForm)
})

$Form.controls.AddRange(@($Button1))

[void]$Form.ShowDialog()

现在,如果我按下按钮,控制台会在前面弹出。用户在控制台中输入内容后,表单再次出现。


推荐阅读