如何用.bat脚本关闭窗口?

时间:2016-01-16 00:38:09

标签: windows batch-file cmd lua

使用鼠标配置一些键绑定时遇到了一些小问题。

我想要实现的是从背景(打开或关闭的窗口)打开程序并再次关闭它,但不要杀死任务(与x按钮等效,因此它会一直在后台运行)< / p>

我已经设置了鼠标来启动名为​​everything的应用程序(可以进行非常快速的文件系统搜索)

我已经想出了这个代码:

TASKKILL /F /IM Everything.exe

我可以用宏键运行我可以杀死应用程序。但是我不想仅仅在窗口中杀死应用程序本身,因为一旦我必须重新启动它就需要一段时间来索引所有重要文件。

因此,问题是有没有办法将窗口/任务调到屏幕前面或触发x按钮事件,而不必杀死整个过程?

鼠标(g600)也支持lua脚本,但这可能是更难的方法。

2 个答案:

答案 0 :(得分:1)

无法发表评论所以我会尽力回答。 'x'按钮可能会杀死你的应用程序,除非应用程序配置,否则我猜。 我想我明白你最好把它放到图标托盘或其他什么东西。如果你的应用程序没有自然地做到这一点,这是不可能的。 你可以尝试点击alt + space + n,这是一个最小化应用程序的快捷方式。

答案 1 :(得分:1)

通常可以通过激活窗口(将其置于前台)然后使用SendKeys()发送 Alt + Space 来完成最小化窗口,然后无论如何在您的语言环境中标有“#34;最小化&#34; (英语Windows中的 N )。 Here's one可能使用VBScript的几十个例子。

在我看来,这个序列被过度使用,不优雅和无聊 - 而且它对某些窗口(例如cmd控制台)不起作用。可以最小化窗口而不将其带到前台,并且无需模拟按键。一个人只需要从user32.dll导入一个函数。只要我们经历这个麻烦,我们也可以导入第二个函数来检测当前窗口状态,以便我们可以切换最小化/恢复。

我们可以像这样使用PowerShell导入函数。使用.bat扩展名保存此批处理/ PowerShell混合脚本并运行它。

<# : minimize.bat
:: toggles minimized state of a window by its filename
:: minimize.bat /? for usage
:: https://stackoverflow.com/a/34834953/1683264

@echo off & setlocal

if "%~1"=="" goto usage
set "prog=%~n1"
tasklist | findstr /i "\<%prog%\>" >NUL || goto usage

set /P "=Toggling the minimized state of %prog%... " <NUL
powershell -noprofile -noninteractive "iex ((gc \"%~f0\") -join \"`n\")"

goto :EOF

:usage
echo syntax: %~nx0 progname[.exe]
echo;
echo If the program is visible, minimize it.  If minimized, restore it.
goto :EOF

:: end Batch / begin PowerShell hybrid chimera #>

Add-Type user32_dll @'
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
'@ -namespace System

$hwnd = @(Get-Process $env:prog)[0].MainWindowHandle
$state = [user32_dll]::GetWindowLong($hwnd, -16)

# mask of 0x20000000 = minimized; 2 = minimize; 4 = restore
if ($state -band 0x20000000) { $action = 4 } else { $action = 2 }

if ([user32_dll]::ShowWindowAsync($hwnd, $action)) {
    write-host "Success" -f green
} else {
    write-host "Fail" -f red
}

现在,如果您的程序最小化到系统托盘,则前一个脚本可以最小化,但在最小化时无法找到窗口句柄。尝试恢复时会失败。在这种情况下找到HWND是棘手的。如果知道窗口标题,可以使用user32.dll FindWindow()FindWindowEx()函数找到HWND。

使用WMI或内置的PowerShell命令找到最小化到托盘的窗口标题,我没有多少运气。 get-processgwmi win32_process[diagnostics.process]::getProcessByName()都没有取得成功。但是,我确实发现tasklist /v /fo list的最后一行将显示窗口标题。这足以调用FindWindow()并获得HWND。

这可能比它需要的更复杂,但是它可能不会。我只知道我找到了1000种失败的方法,但却找到了成功的方法。 Thanks to JPBlanc帮助我弄清楚如何将空参数传递到FindWindow()FindWindowEx()

<# : minimize.bat
:: toggles minimized state of a window by its filename
:: minimize.bat /? for usage

@echo off & setlocal

if "%~1"=="" goto usage
set "prog=%~n1"
tasklist | findstr /i "\<%prog%\>" >NUL || goto usage

set /P "=Toggling the minimized state of %prog%... " <NUL
powershell -noprofile -noninteractive "iex ((gc \"%~f0\") -join \"`n\")"

goto :EOF

:usage
echo syntax: %~nx0 progname[.exe]
echo;
echo If the program is visible, minimize it.  If minimized, restore it.
goto :EOF

End batch / begin PowerShell hybrid chimera #>

Add-Type user32_dll @'
    [DllImport("user32.dll")]
    public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(IntPtr lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter,
        IntPtr lclassName, string windowTitle);
'@ -namespace System

$hwnd = (ps $env:prog)[0].MainWindowHandle

if ($hwnd -eq 0) {
    tasklist /v /fi "imagename eq $env:prog*" /fo list | %{
        $title = $_ -replace '^[^:]+:\s+'
    }
    $zero = [IntPtr]::Zero
    $hwnd = [user32_dll]::FindWindow($zero, $title)
    if ($hwnd -eq 0) {
        $hwnd = [user32_dll]::FindWindowEx($zero, $zero, $zero, $title)
    }
}

$state = [user32_dll]::GetWindowLong($hwnd, -16)

# mask of 0x20000000 = minimized; 2 = minimize; 4 = restore
if ($state -band 0x20000000) { $action = 4 } else { $action = 2 }

if ([user32_dll]::ShowWindowAsync($hwnd, $action)) {
    write-host "Success" -f green
} else {
    write-host "Fail" -f red
}