我有一个我想用热键运行的批处理脚本,这个脚本应该在活动窗口中进行一些操作(例如,创建一组特定的文件夹,或者小写文件夹中文件的所有名称) 。因此,脚本需要在调用时引用活动窗口。
我试图将别名的“Start in”字段留空,但回显%cd%始终打印“C:\ Windows \ System32”而不是当前活动窗口。
答案 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.exe
或cscript.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);