将批处理脚本CMD窗口保留在新打开的CMD窗口之上

可能是一个简单的答案,但不能在网上find它。

我有一个.bat脚本来打开一些程序,也希望用户input(Y [N])这一切工作正常。

我的问题。

我怎样才能让脚本窗口保持在新打开的窗口的顶部,以便用户可以看到脚本正在寻找一些input。

@ECHO OFF REM 2016-06-17 GMAN REM Start Zookeeper cd zookeeper-3.4.8 CALL StartZookeeper.bat REM Give Zookeeper a chance to start sleep 4 REM Start Kafka cd ..\kafka_2.11-0.10.0.0 CALL StartKafka.bat REM Give Kafka a chance to start sleep 2 setlocal :PROMPT SET /p prodCons="Open a CMD for Producer and Consumer: (Y/[N]"?) echo You entered: %prodCons% sleep 1 IF /I "%prodCons%" NEQ "Y" GOTO END REM Producer Terminal start cmd.exe /k "TITLE Producer && cd .\kafka_2.11-0.10.0.0\bin\windows" REM Consumer Terminal start cmd.exe /k "TITLE Consumer && cd .\kafka_2.11-0.10.0.0\bin\windows" :END endlocal 

我的脚本窗口隐藏在新的CMD之后,所以用户可以看到inputY或N.

Solutions Collecting From Web of "将批处理脚本CMD窗口保留在新打开的CMD窗口之上"

设置Always On Top标志的一种方法是从user32.dll导入SetWindowPos()函数,并使用以下参数调用它:

  • 将窗口父项设置为HWND_TOPMOST(-1)
  • 使用SWP_NOMOVE(0x01)和SWP_NOSIZE(0x02)标志跳过调整大小/移动窗口

在纯批处理中没有办法做到这一点,但是您可以让PowerShell完成繁重的工作。 下面是一个bat + PowerShell混合脚本模板,您可以在其中粘贴批处理代码,使控制台始终处于顶层:

 <# : AlwaysOnTop.bat -- http://stackoverflow.com/a/37912693/1683264 @echo off & setlocal rem // Relaunch self in PowerShell to run this window Always On Top powershell -noprofile "iex (${%~f0} | out-string)" rem /* ############################### rem Your main batch code goes here. rem ############################### */ goto :EOF rem // end batch / begin PowerShell hybrid code #> # // Solution based on http://stackoverflow.com/a/34703664/1683264 add-type user32_dll @' [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); '@ -namespace System # // Walk up the process tree until we find a window handle $id = $PID do { $id = (gwmi win32_process -filter "ProcessID='$id'").ParentProcessID $hwnd = (ps -id $id).MainWindowHandle } while (-not $hwnd) $rootWin = [IntPtr](-1) $topmostFlags = 0x0003 [void][user32_dll]::SetWindowPos($hwnd, $rootWin, 0, 0, 0, 0, $topmostFlags) 

也可以使用GetWindowLong()来查询扩展窗口样式,以确定窗口是否已经设置在最上面 – 然后切换它。

 <# : AlwaysOnTop2.bat -- http://stackoverflow.com/a/37912693/1683264 @echo off & setlocal call :toggleAlwaysOnTop rem /* ############################### rem Your main batch code goes here. rem ############################### */ goto :EOF :toggleAlwaysOnTop powershell -noprofile "iex (${%~f0} | out-string)" goto :EOF rem // end batch / begin PowerShell hybrid code #> add-type user32_dll @' [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] public static extern int GetWindowLong(IntPtr hWnd, int nIndex); '@ -namespace System $id = $PID do { $id = (gwmi win32_process -filter "ProcessID='$id'").ParentProcessID $hwnd = (ps -id $id).MainWindowHandle } while (-not $hwnd) $style = [user32_dll]::GetWindowLong($hwnd, -20) # // If flag 0x08 is set, make parent HWND -2 to unset it. Otherwise, HWND -1 to set it. [IntPtr]$rootWin = ($style -band 0x08) / -8 - 1 [void][user32_dll]::SetWindowPos($hwnd, $rootWin, 0, 0, 0, 0, 0x03)