powershell - Hvordan kan jeg få det aktuelle aktive vindue på det tidspunkt, hvor et batch script køres?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har et batch script, jeg vil køre med genvejstaster, og dette script skal foretage nogle handlinger i det aktive vindue (for eksempel at oprette et bestemt sæt mapper eller små bogstaver alle navne på filerne inde i mappen). Så scriptet skal henvise til det aktive vindue, når det kaldes.


Jeg har forsøgt at forlade feltet 'Start i' i aliaset, men echoing\% cd\% udskriver altid 'C: \ Windows \ System32' i stedet for det aktuelle aktive vindue.

Bedste reference


Du kan se hvilke processer der fik vinduet i forgrunden ved hjælp af pinvoke of user32.dll.
Jeg har brugt dette trick til system.window.forms.sendkeys metode i et script:


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

Andre referencer 1


For alle, der leder efter en ikke-Powershell-løsning, her 'et batch script, der bruger cscript for at påberåbe sig en blok af JScript. JScript opretter en ny børneproces, får sin PID og går derefter op på ParentProcessID forfædres linje, indtil den kommer til explorer.exe, så returneres PID for det direkte barn. Det burde returnere den korrekte PID for det konsolvindue, som scriptet kører, selvom der er flere forekomster af cmd.exe]] eller cscript.exe kører.


Hvad kan jeg sige? Jeg følte mig kreativ i dag.


@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);