UDF: Windows Explorer fernsteuern

  • Versuch das mal:

    [autoit]

    Func _GetHwndByPID($PID)
    $aWinList = WinList()
    For $i = 1 To $aWinList[0][0]
    If WinGetProcess($aWinList[$i][1]) = $PID Then Return $aWinList[$i][1]
    Next
    Return SetError(1, 0, 0)
    EndFunc

    [/autoit]

    Das Handle ändert sich nicht bei Titelwechsel, es bleibt immer gleich.

  • Hmm komische Sache. Also erstmal zu den Fehlern im Script:

    In Zeile 12 gibst du die pid und das handle vom linken fenster aus, das muss natürlich aufs rechte fenster geändert werden
    In Zeile 57 wird glaube ich die falsche Array Spalte verwendet (handle statt title), müsste denke ich so lauten
    If WinGetProcess($aWinList[$i][0]) = $PID Then Return $aWinList[$i][1]

    Ich bekomme allerdings nur fürs linke Fenster ein Handle zurück. Beim rechten wird die if Bedingung nicht erfüllt, obwol das Fenster im array von winlist vorhanden ist. Um das zu prüfen hatte ich noch ein arraydislay eingebaut bevor die For Schleife startet.

    EDIT: Beim ersten Fenster kommt im übrigen auch nur dann ein Handle zurück, wenn explorer.exe mit einem Parameter gestartet wird also z.B. explorer.exe "C:\".

    3 Mal editiert, zuletzt von misterspeed (2. Dezember 2010 um 14:10)

    • Offizieller Beitrag

    Es geht eigentlich viel einfacher, mußt nur schauen, ob evtl bei Win7 eine andere CLASS verwendet wird:

    Edit: Hatte noch zu kompliziert gedacht, noch kürzer:

    [autoit]

    $old = Opt("WinTitleMatchMode", 4)
    ShellExecute("explorer.exe")
    ShellExecute("explorer.exe")

    [/autoit][autoit][/autoit][autoit]

    $WinList = WinList("CLASSNAME=ExploreWClass")
    $hWnd_left = $WinList[1][1]
    $hWnd_right = $WinList[2][1]

    [/autoit][autoit][/autoit][autoit]

    Opt("WinTitleMatchMode", $old) ; wichtig, sonst können die Window Funcs nicht mit dem Handle arbeiten!

    [/autoit][autoit][/autoit][autoit]

    WinMove($hWnd_left,"",0,0,@DesktopWidth/2,@DesktopHeight-480-60)
    WinMove($hWnd_right,"",@DesktopWidth/2,0,@DesktopWidth/2,@DesktopHeight-480-60)

    [/autoit]


    Dann kannst du mit

    [autoit]

    WinActivate($hWnd)

    [/autoit]

    das jeweilige Fenster aktivieren und deine Aktionen ausführen. Du kannst dann als Titel "[ACTIVE]" verwenden und greifst somit auf das eben aktivierte Fenster zu.

  • Krass! Jetzt kommen die Profis :thumbup:

    Vielen Dank. Das Skript funktioniert auch bei mir - allerdings musste ich noch nach dem Aufruf der 2 Explorer ein Sleep(1000) einsetzen müssen, weil es sonst nicht zuverlässig funktioniert hat (zumindest auf meinem langsamen Laptop).

    Mir geht es natürlich darum, mein Skript zum laufen zu bekommen - allerdings möchte ich das ganze auch verstanden wissen - schon alleine um euch beim nächsten mal nicht wieder quälen zu müssen.

    BugFix : Dein Skript habe ich teilweise verstanden. Was ich nicht verstehe ist, warum es auch dann noch funktioniert, wenn ich vor dem Starten des Skripts einen Explorer manuell gestartet habe. Es sind dann 3 Explorer in Winlist gelistet und wenn er dann fix auf 1 und 2 zugreift, dann müsste das erste Explorer-Fenster ja "verändert" werden. Wird es aber nicht. Kapiere ich nicht.

    Was mich natürlich noch mehr interessiert ist, warum die Lösungsansätze davor nicht funktioniert haben. Warum hat der Ansatz von m-obi über die PIDs nicht geklappt. Warum wurde die entsprechende PID nicht gefunden?

    Ich weiß noch nicht, ob ich es jetzt schaffen werde, die Adresse der Explorer zu verändern, ohne dass das Explorer Fenster aktiv wird.

    Falls das nicht anders geht, muss ich eben hoffen, dass das ständige "rumblinken" der Fenster schnell geht und nicht zu sehr stört...

    Vielen Dank!!!

  • Jetzt mal eine ganz blöde Frage! Warum machst du das ganze über den Explorer? Du kannst doch auch Dateien direkt mit AutoIt einsortieren, z.B. mit FileMove.
    Man kann ja eine einfache Gui machen, wo man den Quell und den Zielpfad einstellt, und dann wars das schon. Was hast du eigentlich genau vor?

  • Es sind dann 3 Explorer in Winlist gelistet und wenn er dann fix auf 1 und 2 zugreift, dann müsste das erste Explorer-Fenster ja "verändert" werden. Wird es aber nicht. Kapiere ich nicht.

    Ist auch so wie du vermutest. Wenn das bei dir trotzdem funktioniert ist das reiner Zufall und hängt mit der Array Sortierung zusammen. Denke mal das wird alphabetisch sortiert und deine zwei Fenster landen dann eben vor dem anderen Fenster. Kannst dir das Array von winlist einfach mal mit _arraydisplay ausgeben lassen. Bei mir wird das falsche Fenster bewegt, gerade getestet.

    Um dieses Problem zu umgehen könnte man winlist aber vor und nach den beiden shellexecutes ausführen und dann die Inhalte der Arrays abgleichen um die vorher schon vorhandenen Fenster auszuschliessen.


    Unter Vista muss als Klasse im übrigen "CabinetWClass" verwendet werden.


    EDIT: Die Fenster werden doch nicht alphabetisch sortiert, sondern nach der letzten Aktivität. Daher dürfte das Script wohl in 99% der Fälle funktionieren, sofern keine längeren Pausen zwischen Fenster Erstellung und winlist eingebaut werden.

    2 Mal editiert, zuletzt von misterspeed (2. Dezember 2010 um 21:12)

    • Offizieller Beitrag

    Um sicher die richtigen Fenster zu erwischen, muß man das Skript etwas erweitern. Hab es nicht getestet, aber sollte eigentlich klappen.

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    Opt("WinTitleMatchMode", 4)
    Local $WinList = WinList("CLASSNAME=ExploreWClass")

    [/autoit] [autoit][/autoit] [autoit]

    Local $count = $WinList[0][0], $ListOld, $aHwnd[2], $j = 0
    If $count Then $ListOld = $WinList
    ShellExecute("explorer.exe")
    ShellExecute("explorer.exe")
    Do
    $WinList = WinList("CLASSNAME=ExploreWClass")
    Sleep(50)
    Until $WinList[0][0] = $count +2
    Opt("WinTitleMatchMode", 1) ; wichtig, sonst können die Window Funcs nicht mit dem Handle arbeiten!

    [/autoit] [autoit][/autoit] [autoit]

    If $count Then
    For $i = 1 To $WinList[0][0]
    _ArraySearch($ListOld, $WinList[$i][1], 0, 1, 0, 0, 1, 1)
    If @error Then
    $aHwnd[$j] = $WinList[$i][1]
    $j = 1
    EndIf
    Next
    Else
    $aHwnd[0] = $WinList[1][1]
    $aHwnd[1] = $WinList[2][1]
    EndIf

    [/autoit] [autoit][/autoit] [autoit]

    WinMove($aHwnd[0],"",0,0,@DesktopWidth/2,@DesktopHeight-480-60) ; left
    WinMove($aHwnd[1],"",@DesktopWidth/2,0,@DesktopWidth/2,@DesktopHeight-480-60) ; right

    [/autoit]
  • Juhu, es funktioniert !!!

    Doch bitte bitte:

    Warum funktioniert der Ansatz drüber über PID nicht? (aus einer PID ein Handle erzeugen).

    Falls ihr müde geworden seid, kann ich dieses Problem auch mal unter autoitscript.com erfragen...

    Bin jetzt gespannt, ob ich schaffe, die Explorer Adresse eines der 2 Fenster zu ändern ;)

    Viele Grüße und einen schönen Abend!

    • Offizieller Beitrag

    Warum funktioniert der Ansatz drüber über PID nicht? (aus einer PID ein Handle erzeugen).


    Hast du dir mal die PIDs angesehen? Es ist nur eine. Auch wenn "explorer.exe" mehrfach aufgerufen wird, existiert dazu nur ein Prozeß und somit nur eine PID. Also läßt sich daraus auch nicht auf die Handle schließen.

  • Wäre eine schöne Erklärung gewesen. Ich kriege allerdings auch unter XP zwei verschiedene PIDs.

    Mir ist der Grund nach wie vor unklar, warum es nicht möglich ist, aus dieser PID ein Handle zu erzeugen...

    • Offizieller Beitrag

    Ist der Haken gesetzt, wird für jedes Explorerfenster ein eigener Prozess gestartet.


    Wie sagte meine Oma so richtig: "Kannste alt werd'n, wie ne Kuh - lernste immer noch dazu." :thumbup:

    Edit:
    Kommando zurück - das ist eine Fehlinterpretation.
    Habe es mal durchgetestet. Es gibt max. 2 Explorer-Instanzen zeitgleich. Völlig egal ob der Aufruf mit Run, ShellExecute oder aus der Eingabeaufforderung erfolgt. Einmal läuft sowieso und in der zweiten Instanz werden dann die Fenster geöffnet, sofern die Checkbox aktiviert ist. "Ordnerfenster in einem eigenem Prozeß anzeigen" sagt die Beschreibung, und nicht "jedes Ordnerfenster in einem eigenen Prozeß"

    • Offizieller Beitrag

    Es ist trotzdem verwirrend.
    Hier mal ein Testskript.

    Spoiler anzeigen
    [autoit]

    $PID1 = Run("explorer.exe")
    ; Unter dieser PID sind nachher alle Explorerfenster vereint, obwohl beim Start eine eigene PID vergeben wird.
    ; Aber Windows scheint diese zu verwerfen.
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID1 = ' & $PID1 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $PID2 = Run("explorer.exe")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID2 = ' & $PID2 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $PID3 = Run("explorer.exe")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID3 = ' & $PID3 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $PID4 = Run("explorer.exe")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID4 = ' & $PID4 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    $PID5 = Run("explorer.exe")
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $PID5 = ' & $PID5 & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

    [/autoit] [autoit][/autoit] [autoit]

    Opt("WinTitleMatchMode", 4)
    Local $WinList
    Do
    $WinList = WinList("CLASSNAME=ExploreWClass")
    Sleep(50)
    Until $WinList[0][0] = 5
    Opt("WinTitleMatchMode", 1)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite('Hwnd / PID from Hwnd' & @CRLF)
    For $i = 1 To $WinList[0][0]
    ConsoleWrite('Hwnd / PID : ' & $WinList[$i][1] & ' / ' & WinGetProcess($WinList[$i][1]) & @CRLF & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Local $ProcList = ProcessList('explorer.exe')
    ConsoleWrite('PIDs from ProcessList' & @CRLF)
    For $i = 1 To $ProcList[0][0]
    ConsoleWrite($ProcList[$i][1] & @CRLF)
    Next

    [/autoit]

    Nach dem Starten dieser 5 Explorerfenster erhalte ich folgende Ausgabe:

    Spoiler anzeigen

    Starte ich dann nochmals das Skript und lasse die 5 Fenster offen, erhalte ich folgende Ausgabe:

    Spoiler anzeigen

    D.h. die neuen Prozesse sind in der Prozesslist, werden aber im Taskmanager bei mir nur unter einer Instanz, PID 948 angezeigt und die Handle sind auch alle dieser PID zugeordnet.
    Mir fehlen dazu die tieferen Windows-Kenntnisse, um das zu verstehen. :wacko: