如何在运行批处理脚本时获取当前活动窗口?

时间:2012-03-15 14:51:37

标签: windows powershell batch-file

我有一个我想用热键运行的批处理脚本,这个脚本应该在活动窗口中进行一些操作(例如,创建一组特定的文件夹,或者小写文件夹中文件的所有名称) 。因此,脚本需要在调用时引用活动窗口。

我试图将别名的“Start in”字段留空,但回显%cd%始终打印“C:\ Windows \ System32”而不是当前活动窗口。

2 个答案:

答案 0 :(得分:13)

您可以使用user32.dll的pinvoke查找哪个进程将窗口置于前台。 我在脚本中使用了这个技巧来处理system.window.forms.sendkeys方法:

Add-Type @"
  using System;
  using System.Runtime.InteropServices;
  public class Tricks {
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}
"@

$a = [tricks]::GetForegroundWindow()

get-process | ? { $_.mainwindowhandle -eq $a } # in my case:

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------

    161       7    13984      15820    91     9,75   7720 Console

答案 1 :(得分:2)

对于任何寻找非Powershell解决方案的人来说,这是一个使用cscript来调用JScript块的批处理脚本。 JScript创建一个新的子进程,获取其PID,然后向上走ParentProcessID行的祖先,直到它到达explorer.exe,然后返回直接子进程的PID。它应该为脚本运行的控制台窗口返回正确的PID,即使有多个cmd.execscript.exe实例正在运行。

我能说什么?我今天感觉很有创意。

@if (@a==@b) @end   /* JScript multiline comment

:: begin batch portion

@echo off
setlocal

for /f "delims=" %%I in ('cscript /nologo /e:Jscript "%~f0"') do (
    echo PID of this console window is %%I
)

goto :EOF

:: end batch portion / begin JScript */

var oShell = WSH.CreateObject('wscript.shell'),
    johnConnor = oShell.Exec('%comspec% /k @echo;');

// returns PID of the direct child of explorer.exe
function getTopPID(PID, child) {
    var proc = GetObject("winmgmts:Win32_Process=" + PID);

    // uncomment the following line to watch the script walk up the ancestor tree
    // WSH.Echo(proc.name + ' has a PID of ' + PID);

    return (proc.name == 'explorer.exe') ? child : getTopPID(proc.ParentProcessID, PID);
}

var PID = getTopPID(johnConnor.ProcessID);
johnConnor.Terminate();

// send the console window to the back for a second, then refocus, just to show off
oShell.SendKeys('%{ESC}');
WSH.Sleep(1000);
oShell.AppActivate(PID);

// output PID of console window
WSH.Echo(PID);