UDF: Windows Explorer fernsteuern

  • Hallo,

    Ich möchte gerne den Windows Explorer fernsteuern, um Dateien komfortabel einsortieren zu können.

    Das ganze sieht so aus:

    Es öffnen sich 2 Windows Explorer (einer linke Hälfte, einer rechte Hälfte).

    Links sind die noch einzusortierenden Dateien drin. In der unteren Bildhälfte gibt es Vorschläge, wo das ganze hinkönnte.

    Der user akzeptiert dann auf einen Vorschlag unten und rechts springt der Windowsexplorer in das vorgeschlagenen Verzeichnis.

    Das ganze auch per Drag&Drop.

    Das ganze funktioniert schon ganz toll. Jedoch habe ich dabei folgende Probleme:

    - Das ganze soll sowohl auf WinXP als auch auf Win7 lauffähig sein. Die Controlls der Explorer WinXP und Win7 unterscheiden sich wohl leicht...

    - Der Windows Explorer stützt sowohl unter WinXP als auch unter Win7 unregelmäßig ab (jeder 30. Vorgang)


    Wie komme ich vor allem bei dem 2. Problem weiter?

    Gibt es eine UDF zum Fernsteuern des Windows-Explorer. Ich glaube, dass meine Lösung zu stümperhaft programmiert ist.

    Viele Grüße

  • Hallo dost0011,

    ein Beispielcode würde stark weiterhelfen. Schreibe doch eine kleine Verzweigung à la If @OSBuild [i]... Dann könntest du darin die Handle der beiden Fenster, die du haben möchtest, erfragen ([i]WinGetHandle). Über WinMove richtest du sie dann aus.

    Gruß,
    Matthias

  • Hallo Matthias,

    das habe ich schon hingekriegt und das funktioniert auch fehlerfrei.

    Aber es ist alles so umständlich, weil alles über den Titel und nicht über ein Handle laufen kann (zumindest weiß ich nicht wie)

    Problem 1:
    Es gibt keinen Befehl, dass ich ein Fenster mit einem bestimmten Handle aktivieren kann. Alles geht nur über den Titel.
    Also habe ich eine kleine Routine geschrieben: Get_Wintitle(Handle). Ich gebe ihr den Handle, sie gibt mir den Titel zurück.
    In diesem Fall funktioniert das aber nicht, weil ich 2 Fenster offen habe, die erst mal den gleichen Titel haben.
    Direkt nach dem Start heißen sie unter WinXP "Eigene Dateien" und unter Win7 "Bibliotheken".
    Schon das nervt. Weil es also 2 gleichnamige Fenster gibt, aktiviert autoit nun immer das letzte Fenster und nicht das zu dem Handle gehörende.

    Problem 2:
    Man kann Problem 1 stümperhaft umgehen, indem man zuerst den Explorer mit der neuen Adresse aktualisiert und erst dann den zweiten Explorer öffnet.
    Dann klappt das ganze: Links: "c:\windows" und rechts "c:\temp". (soll nur ein Beispiel sein).
    So, wenn man dann aber diese Routine "aktualisiere Explorer" mehrfach aufruft (immer mit verschiedenen Ordnern), dann stürzt irgendwann der Windows-Explorer ab. Sowohl unter WinXP als auch unter Win7. Keine Ahnung warum.

    Könnt ihr mir helfen, da ein wenig Ordnung reinzubringen? Nur das Steuern über Titel ist aufwendig und unangenehm, wenn es doch ein Handle gibt...

    Viele Grüße und Danke.

  • Hallo zurück,

    ich schlage folgendes vor:

    [autoit]

    func Erzeuge_Explorer($links_rechts)
    ShellExecute("explorer.exe")
    if @OSVersion = "WIN_7" Then
    $title = "Bibliotheken"
    Else
    $title = "Eigene Dateien"
    EndIf
    WinWaitActive($title)
    if $links_rechts="links" Then
    ; links
    $Handle_Explorer_links = WinGetHandle($title,"")
    WinWaitActive($title)
    WinMove($title,"",0,0,@DesktopWidth/2,@DesktopHeight-480-60)
    Else
    ; rechts
    $Handle_Explorer_rechts = WinGetHandle($title,"")
    WinWaitActive($title)
    WinMove($title,"",@DesktopWidth/2,0,@DesktopWidth/2,@DesktopHeight-480-60)
    EndIf
    EndFunc

    [/autoit]

    nehmen wir aus der Stelle folgenden Abschnitt genauer unter die Lupe:

    [autoit]

    if $links_rechts="links" Then
    ; links
    $Handle_Explorer_links = WinGetHandle($title,"")
    WinWaitActive($title)
    WinMove($title,"",0,0,@DesktopWidth/2,@DesktopHeight-480-60)

    [/autoit]

    Ich würde das so umschreiben:

    [autoit]

    if $links_rechts="links" Then
    ; links
    $Handle_Explorer_links = WinGetHandle($title,"")
    WinWaitActive($Handle_Explorer_links )
    WinMove($Handle_Explorer_links ,"",0,0,@DesktopWidth/2,@DesktopHeight-480-60)
    WinSetTitle($Handle_Explorer_links, "", "Explorer links" )

    [/autoit]


    Und für rechts analog genau so.

    Ich glaube, dass wenn ich dich richtig verstanden habe, du hier etwas falsch verstanden hast: Schau in der Hilfe mal nach "Fenster-Ttel und -texte (erweitert)". Ich empfehle das Studium mindestens des letzten Absatzes ;)

    Darüber hinaus gebe ich folgenden Tipp: Drücke mal die Tasten Strg+T, so sieht dein Code nachher auch viel schöner aus! :)

    So umgehst du auch das mit dem Öffnen zweier Ordner.

    Gruß,
    Matthias

  • :rock: Jaaaaaa !

    Genauso habe ich es mir gewünscht. Leider habe ich das noch nie gelesen (arbeite eh immer mit der englischen Hilfe (Autoit3.chm) und dort habe ich sowas noch nie gefunden. Auch in der Beschreibung der Befehle findet man sowas nicht...

    Jetzt mal schauen, ob die Abstürze überhaupt noch auftrefen :)

    Was macht den Strg-T ? Bei mir vertauscht das nur 2 Zeilen. Den Sinn habe ich noch erkannt und eine Doku habe ich auch nicht gefunden (liegt aber vermutlich an mir).

    Danke.

  • Hallo nochmal!

    Dafür wirst du erst einmal gesteinigt! Hier geben sich alle die Mühe die Hilfe zu übersetzen, und du nimmst die Englische?!? :rofl:

    Strg-T "löst" in SciTE Tidy aus, ein kleines Skript, was dir deinen Quellcode etwas ordentlicher macht. (Z.B. wird so aus "func" -> "Func").

    Weiterhin viel Erfolg,
    Matthias

  • Nein, bitte nicht steinigen. Das mit dem Englisch ist doch nur eine Übung.

    Jetzt hänge ich aber schon wieder an dem blöden Explorer!
    Ich kriege die Dinger jetzt nicht mehr geschlossen!

    $ret = WinClose($Handle_Explorer_links) liefern mir zwar 1 zurück. Das Ding ist aber immer noch offen.
    Selbst WinKill funktioniert nicht (steht aber schon in der Anleitung :)

    Shit. Bitte jetzt den Windows Explorer nicht über Processclose schließen...

    Und nu??? :whistling:

  • Benutz doch den Fenstertitel für winclose. Du hast ja zuvor den titel mit winsettitle selbst definiert:

    [autoit]


    winclose("Explorer links")
    winclose("Explorer rechts")

    [/autoit]

    EDIT: Ok funktioniert nur wenn man die ordner nicht wechselt. Du müsstest also ggf. bei Ordnerwechseln jedesmal den Titel ermitteln:

    [autoit]

    WinGetTitle("[active]")

    [/autoit]

    oder was vielleicht sinnvoller wäre... den Titel nach jedem Ordnerwechsel wieder per winsettitle auf explorer rechts bzw explorer links ändern.

    EDIT2: Unter Vista musst du btw. "Dokumente" als Titel abfragen anstatt "Eigene Dateien" oder "Bibliotheken"

    5 Mal editiert, zuletzt von misterspeed (27. November 2010 um 16:30)

  • Hallo,

    also jetzt habe ich 6h im Internet gesurft und habe nichts gefunden, was mich weiter bringt.

    Ich bitte euch daher, mir nochmal Tipps zu geben, wie ich das schaffe.

    Ich möchte gerne:

    - Windows Explorer (nicht Internet Explorer) öffnen (mit Addressbar)

    - Navigieren

    - Explorer schliessen.

    Es wäre toll, wenn die Steuerung nicht über den Windows-Titel erfolgen würde, weil ich vor habe mehrere Explorer evtl. mit gleichem Verzeichnis zu steuern.

    Mit "ControlClick" habe ich gar keine guten Erfahrungen gemacht, so dass vielleicht ein COM Objekt die beste Lösung wäre. Da habe ich es aber nicht geschafft eine Addressbar zu erzeugen.

    Bitte helft mir weiter.

    Viele Grüße

  • Wenn du WinClose außerhalb der Func nutzt, musst du $Handle_Explorer_links und $Handle_Explorer_rechts schon Global deklarieren und nicht Lokal.

  • Sorry hab mir dein Script nicht angesehen.

    Edit: Werden denn die Func's beendet? Das Exit kannst du übrigens rausnehmen.

    Einmal editiert, zuletzt von m-obi (1. Dezember 2010 um 12:11)

  • Hallo m-obi,

    danke, dass Du mir wenigstens antwortest, wenn ich auch mit deinen Gegenfragen wenig anfangen kann. Ja die Funcs werden beendet.

    wie würdest Du denn an meiner Stelle vorgehen? Ich finde trotz intensiver Suche keine Hilfe oder Dokumentation die mich weiter bringt. Auch in dem Forum antwortet mir keiner mit sinnvollen Hinweisen, obwohl ich sicher bin, dass dies einige Wissen.

    Viele Grüße

  • Ich würde eine MsgBox vor WinClose setzen, um zu sehen ob das Script überhaupt bis dahin kommt.

  • Hallo m-Obi,

    ich hoffe, ich vergraule jetzt nicht den letzten, der mir antwortet, aber dein Vorschlag hilft mir überhaupt nicht weiter.

    Ich habe das Skript angehängt, damit auch andere das Problem nachvollziehen können (also auch du) und Spekulationen nicht notwendig sind.

    Genau genommen habe ich 3 größere Probleme:

    1. Das mit den Handles scheint nicht zu funktionieren und weil das nicht tut, muss man (wann auch immer) auf die Titel umsteigen. Das finde ich sehr unzufriedenstellend und ich hätte gerne einen Grund, warum das mit den Handles nicht funktioniert - oder zumindest einen Hinweis, wie man es besser machen kann.

    2. ControllClick funktioniert ebenfalls extrem schlecht (es dauert mehrere Sekunden, bis der Befehl Controllclick überhaupt angenommen wird!) und manchmal stürzt sogar der Explorer dabei ab. Es wäre vermutlich viel besser so etwas mit einem COM Objekten zu machen.

    3. Es meldet sich niemand, der sich damit auskennt. Dabei geht es um 3 "Lapalien":

    - 2 Windows Explorer starten (mit Ordneransicht und "Details")

    - gezielt mit jedem navigieren

    - Explorer beenden

    Gruß

    • Offizieller Beitrag

    Ich würde die Explorer nicht per ShellExecute starten sondern mit Run. So erhälst Du die PID und kannst Dir darüber das Handle des Fensters holen:

    Spoiler anzeigen
    [autoit]


    $width = @DesktopWidth / 2
    $height = @DesktopHeight - 90

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

    $ExplorerLeft = Run('Explorer.exe')
    $HwndLeft = WinGetHandle($ExplorerLeft)
    WinWait($HwndLeft)
    WinMove($HwndLeft, '', 0, 0, $width - 1, $height)

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

    $ExplorerRight = Run('Explorer.exe')
    $HwndRight = WinGetHandle($ExplorerRight)
    WinWait($HwndRight)
    WinMove($HwndRight, '', $width, 0, $width - 1, $height)

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

    Sleep(3000)

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

    WinClose($HwndLeft)
    WinClose($HwndRight)

    [/autoit]
  • WinGethandle liefert kein Ergebnis, sondern nur @error 1. In deinem Beispiel klappt das ganze seltsamerweis trotzdem, obwohl garkein handle ermittelt wird. Ich denke das liegt daran, dass der winmove dann einfach auf das derzeit aktuelle (oder letzte) Fenster angewendet wird.
    Hier nochmal mit debug msgboxen:

    [autoit]


    $width = @DesktopWidth / 2
    $height = @DesktopHeight - 60

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

    $ExplorerLeft = Run('Explorer.exe "C:\"')
    $HwndLeft = WinGetHandle($ExplorerLeft)
    MsgBox(0,"",$ExplorerLeft & @LF & $HwndLeft & @LF & @error)
    WinWait($HwndLeft)
    WinMove($HwndLeft, '', 0, 0, $width, $height)

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

    $ExplorerRight = Run('Explorer.exe "C:\Windows"')
    $HwndRight = WinGetHandle($ExplorerRight)
    MsgBox(0,"",$ExplorerRight & @LF & $HwndRight & @LF & @error)
    WinWait($HwndRight)
    WinMove($HwndRight, '', $width, 0, $width, $height)

    [/autoit][autoit][/autoit][autoit][/autoit]
  • Vielen Dank für den Hinweis, dass WinGetHandle überhaupt kein gültiges Ergebnis liefert - das bringt uns ein wenig weiter.

    Schade ist, dass ich keine Idee habe, wie man jetzt zu einem gültigen Handle kommen kann.

    Run liefert zwar eine PID - aber wie komme ich jetzt zu einem Handle? Wingethandle jedenfalls akzeptiert als Argument kein PID.

    WinList hilft auch nicht weiter. Wie macht man das denn nun?

    Oder gibts einfach keinen Weg ausser den über den Fenstertitel? Verändert sich ein Handle eigentlich, wenn sich der Fenstertitel verändert?

    Viele Grüße