无法恢复使用显示窗口隐藏的窗口



我在脚本中有以下类型定义:

Add-Type -TypeDefinition @'
namespace Win32
{
    //https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
    public static class Functions
    {
        [System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint="ShowWindow")]
        public static extern bool SW(System.IntPtr hWnd, Win32.SW nCmdShow);
    }
    public enum SW
    {
        HIDE               = 0,
        SHOW_NORMAL        = 1,
        SHOW_MINIMIZED     = 2,
        MAXIMIZE           = 3,
        SHOW_MAXIMIZED     = 3,
        SHOW_NO_ACTIVE     = 4,
        SHOW               = 5,
        MINIMIZE           = 6,
        SHOW_MIN_NO_ACTIVE = 7,
        SHOW_NA            = 8,
        RESTORE            = 9,
        SHOW_DEFAULT       = 10,
        FORCE_MINIMIZE     = 11
    }
}
'@

其中的所有内容都有效,例如:

[Win32.Functions]::SW((Get-Process -Name powershell).MainWindowHandle, [Win32.SW]::SHOW_DEFAULT)

但是,当我使用[Win32.SW]::HIDE时,我完全无法恢复该窗口。 每个选项都失败了,我得到了false回报。 文档中是否缺少某些内容或SW_HIDE的功能使其无法恢复?

我的最终目标是在自扩展.cmd> .ps1脚本中创建一些 WPF GUI,创建一个伪可执行文件并隐藏留下的 powershell 窗口(可能会根据脚本操作进行还原(。

问题是.MainWindowHandle在窗口隐藏时不再有效[1],因此尝试"取消隐藏"窗口失败。

只需缓存 HWND 并在"取消隐藏"调用中使用缓存的值:

# Also consider Get-Process -ID $PID, as in Stanislav's answer, to avoid ambiguity 
# if multiple PowerShell processes exist.
$hWnd = (Get-Process -Name PowerShell).MainWindowHandle
# ... hide window and do stuff
# Unhide, using the *cached* HWND:
[Win32.Functions]::SW($hWnd, [Win32.SW]::SHOW_DEFAULT)

顺便说一句:ShowWindow() Windows API函数(此处别名为SW( 返回一个布尔值,该值不反映成功,但反映窗口以前是否隐藏 ( $False ( 或 ( $True (。


[1] 属性类型为 [System.IntPtr] ,其值在窗口隐藏时0

我可以看到的是,您通过检查其名称来引用进程。这可能有点棘手,因为可以运行多个具有相同名称的进程。因此,如果您要隐藏当前的PowerShell窗口,并且希望稍后还原它,请使用其PID而不是名称来引用它。可以用作示例的代码可以在下面找到。

Add-Type -TypeDefinition @'
namespace Win32
{
    //https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548(v=vs.85).aspx
    public static class Functions
    {
        [System.Runtime.InteropServices.DllImport("User32.dll", EntryPoint="ShowWindow")]
        public static extern bool SW(System.IntPtr hWnd, Win32.SW nCmdShow);
    }
    public enum SW
    {
        HIDE               = 0,
        SHOW_NORMAL        = 1,
        SHOW_MINIMIZED     = 2,
        MAXIMIZE           = 3,
        SHOW_MAXIMIZED     = 3,
        SHOW_NO_ACTIVE     = 4,
        SHOW               = 5,
        MINIMIZE           = 6,
        SHOW_MIN_NO_ACTIVE = 7,
        SHOW_NA            = 8,
        RESTORE            = 9,
        SHOW_DEFAULT       = 10,
        FORCE_MINIMIZE     = 11
    }
}
'@
. ([ScriptBlock]::Create('using namespace Win32'))
$mainWindowHandle = (Get-Process -ID $PID).MainWindowHandle
[Functions]::SW($mainWindowHandle, [SW]::HIDE)
# Sleep for 5 seconds to prove it working
Start-Sleep -Seconds 5
[Functions]::SW($mainWindowHandle, [SW]::SHOW_DEFAULT)

请确保在运行它之前,在最后一个命令之后至少有一个空换行符,否则它不会被执行,并且您的窗口将永远不会弹出;)

希望对您有所帮助!

最新更新