JPS: VBS: ScrollLock-LED soll blinken während Download läuft

Hallo

seid geraumer Zeit schlage ich mich mit folg. Problem herum und
bekomme es nicht gelöst. Hab mich dumm und dämlich gegoogelt und habe
mittlerweile wohl ein Brett vorm Kopf:
Während Download mittels "Wget.exe" im "Hide-Modus" - run(Application, 0, true) - soll
die "ScrollLock-LED" zur optischen Kontrolle blinken. Ich dachte ich könnte
die "Länge des ReturnCode" der Anwendung dazu benutzen -> Solange kein
Rückgabewert "Len(ReturnCode)=0" blinken, bei irgend einem
Rückgabewert "Len(ReturnCode)>0" blinken-stop - aber da ist offensichtlich
ein Denkfehler drin.

Ich hoffe ich hab's einigermaßen verständlich beschrieben.
Bitte keine Vorschläge wie: "Da gibts extra Programme für."

GetFile.vbs
-------------------------- snip --------------------------
Option Explicit

Dim wss          : Set wss      = CreateObject("WScript.Shell")
  Dim zipfile      : zipfile      = "http://downloads1.kaspersky-labs.com/zips/av-i386-weekly.zip"
  Dim downloadpath : downloadpath = "C:\Dokumente und Einstellungen"
  Dim logfile      : logfile      = downloadpath & "\Download.log"
  Dim debug        : debug        = 1   ' 0=Debug auf Konsole; 1=Debug in Logfile
  Dim wndmode      : wndmode      = 3   ' 0=hide; 1=default; 2=minimized; 3=maximized

GetFile zipfile,downloadpath,debug,logfile,wndmode

'.: clear :.
  Set wss          = nothing
  Set zipfile      = nothing
  Set downloadpath = nothing
  Set logfile      = nothing
  Set debug        = nothing
  Set wndmode      = nothing

' Function FlashLight(n,s1,sl1,s2,sl2,mode)
' hier eine vereinfachte
'************************
Function FlashLight()
'************************
  ' solange der Download - Wget - läuft,
  ' soll die Funktion FlashLight() (in einer Schleife?) ausgeführt werden.
  ' Do While Len(ReturnCode) = 0   'funktioniert aber nicht!

' vereinfachte Funktion:
      wscript.sleep 220
      wss.sendkeys "{SCROLLLOCK}"
      wscript.sleep 220
      wss.sendkeys "{SCROLLLOCK}"
      wscript.sleep 220
      wss.sendkeys "{SCROLLLOCK}"

wscript.sleep 850
      wss.sendkeys "{SCROLLLOCK}"
      wscript.sleep 850
      wss.sendkeys "{SCROLLLOCK}"
      wscript.sleep 850
      wss.sendkeys "{SCROLLLOCK}"

wscript.sleep 1000

'If Len(ReturnCode) > 0 Then Exit Do   'siehe oben - funktioniert nicht!
  'Loop
  Exit Function
End Function
'************************

'************************
Function GetFile(sfile,dest,plog,logfile,wndstate)
'************************
  ' plog (0=Debug auf Konsole; 1=Debug in Logfile)

' WGet Parameter
  ' --------------
  ' -t (Number of Tries)
  ' -T (Network "timeout" in sec)
  ' -N (Turn on time-stamping)
  ' -P (Präfix for Downloadpath)
  ' -o (Präfix for Logfile)

Dim appl : appl = "WGet.exe -t 3 -T 10 -N -P "

Dim vt
    Select Case plog
      Case 0  vo  = ""
      Case 1  vo  = "-o "
    End Select

Dim srun : srun = appl & chr(34) & dest & chr(34) & _
                    chr(32) & sfile & chr(32) & _
                    vt & chr(34) & logfile & chr(34)

'Zu Testzwecken nachfolgende Zeile entkommentieren.
  MsgBox srun, vbExclamation + vbOKOnly + vbSystemModal, "Function Wget()"

Set appl = nothing
  Set vt   = nothing

Dim ReturnCode

'hier geht's nicht weiter denn ...steckt in der Schleife fest
  ' und kann somit den Schritt "ReturnCode = wss.run(..." nicht ausführen
  FlashLight

ReturnCode = wss.run(srun, wndstate, true)

Set srun = nothing

Select Case ReturnCode
      Case -1   MsgBox "Abbruch durch Benutzer!", _
                        vbExclamation + vbOKOnly + vbSystemModal, _
                       "ERROR-Code(" & ReturnCode & ")"
                Set ReturnCode = nothing
                Exit Function

Case 0    MsgBox "Download beendet.", _
                        vbExclamation + vbOKOnly + vbSystemModal, _
                       ".:: WGet ::."
                Set ReturnCode = nothing
                Exit Function

Case 1    MsgBox "Server-Fehler!", _
                        vbExclamation + vbOKOnly + vbSystemModal, _
                       "ERROR-Code(" & ReturnCode & ")"
                Set ReturnCode = nothing
                Exit Function

Case Else MsgBox "Unbekannter Fehler!", _
                        vbExclamation + vbOKOnly + vbSystemModal, _
                       "ERROR-Code(" & ReturnCode & ")"
                Set ReturnCode = nothing
                Exit Function
    End Select

End Function
'************************
-------------------------- snip --------------------------

  1. Hoppla, da hat sich eine Fehler eingeschlichen:

    Dim vt
        Select Case plog
          Case 0  vo  = ""
          Case 1  vo  = "-o "
        End Select

    Dim vt
        Select Case plog
          Case 0  vt  = ""
          Case 1  vt  = "-o "
        End Select

    "vo" muss natürlich "vt" sein

  2. Hi,

    Während Download mittels "Wget.exe" im "Hide-Modus" - run(Application, 0, true) - soll die "ScrollLock-LED" zur optischen Kontrolle blinken.

    dazu müsstest du wget als Kind-Prozess asynchron ausführen können, also das Programm starten, so dass dein VB-Script "nebenher" weiterläuft. Kann VBS das?

    Ich dachte ich könnte die "Länge des ReturnCode" der Anwendung dazu benutzen -> Solange kein Rückgabewert "Len(ReturnCode)=0" blinken, bei irgend einem Rückgabewert "Len(ReturnCode)>0" blinken-stop - aber da ist offensichtlich ein Denkfehler drin.

    Ja. Der Denkfehler besteht vermutlich darin, dass du den zeitlichen Ablauf nicht klar siehst:

    FlashLight
      ReturnCode = wss.run(srun, wndstate, true)

    Diese beiden Anweisungen laufen streng sequentiell (nacheinander). Erst wird deine Funktion FlashLight aufgerufen, und erst wenn die beendet ist, kommt wss.run() mit dem externen Programm dran. Allerdings -wie du schon richtig andeutest- läuft FlashLight dabei endlos, denn die Funktion wartet darauf, dass der ReturnCode sich ändert; das kann er aber erst, wenn das Script weiterläuft. Eine Variante des Henne-Ei-Problems (Ohne Henne kein Ei, ohne Ei aber auch keine Henne).
    Du kannst die beiden Zeilen tauschen. Dann läuft dein Script zwar durch; die LED blinkt dann aber nicht WÄHREND des Downloads, sondern nur mal kurz, wenn er beendet ist.

    Wie gesagt: Du brauchst eine Möglichkeit, ein externes Programm (wget.exe) zu starten, und dein VBS weiterlaufen zu lassen, WÄHREND das externe Programm läuft. Ich weiß nicht, ob VBS das kann.

    So long,
     Martin

    --
    Die letzten Worte des stotternden Beifahrers:
    Frei... frei... frei... freilich kommt da was!!
    1. Wie gesagt: Du brauchst eine Möglichkeit, ein externes Programm (wget.exe) zu starten, und dein VBS weiterlaufen zu lassen, WÄHREND das externe Programm läuft. Ich weiß nicht, ob VBS das kann.

      So long,
      Martin

      Hi Martin,

      so weit bin ich gedanklich auch schon gekommen, nur hab ich - so wie du - noch keine Lösung gefunden.
      Eine Möglichkeit, die mir gerade "in den Kopf geschossen" ist, kommt auf's Gleiche raus: in der FlashLight() eine Abfrageschleife für die Download.log einbauen - Abfrage: suche String "100%", dann blinken-stop. Aber ich muss beide Funktionen parallel starten.

      Gruss JPS

    2. Hallo,

      Wie gesagt: Du brauchst eine Möglichkeit, ein externes Programm (wget.exe) zu starten, und dein VBS weiterlaufen zu lassen, WÄHREND das externe Programm läuft. Ich weiß nicht, ob VBS das kann.

      ich kann mir vorstellen, dass die Execute-Methode des Windows Scripting Host hier helfen kann.

      Freundliche Grüße

      Vinzenz

      1. Hallo,
        ich kann mir vorstellen, dass die Execute-Methode des Windows Scripting Host hier helfen kann.

        Hallo Vinzenz,

        wieso sollte mir die Execute-Methode hier helfen? Kannst Du mir Deine "Vorstellung" etwas näher bringen?

        Gruss JPS

        1. Hallo,

          ich kann mir vorstellen, dass die Execute-Methode des Windows Scripting Host hier helfen kann.

          wieso sollte mir die Execute-Methode hier helfen? Kannst Du mir Deine "Vorstellung" etwas näher bringen?

          weil sie es ermöglicht, einen Prozess asynchron auszuführen und auf sein Ende zu reagieren - und es die erste war, die mir eine Suche präsentierte.

          Die Run-Methode des WScript.Shell-Objektes erlaubt Dir ebenfalls, einen Prozess asynchron auszuführen, ich hab' allerdings auf die Schnelle keine Möglichkeit gesehen, wie man auf das Ende des Prozesses reagieren kann. Du verhinderst die asynchrone Ausführung explizit mit Deinem dritten Parameter, dem Du den Wert true zuweist.

          Allerdings ist die Remote-Ausführung etwas trickreich und standardmäßig nicht erlaubt.

          Am einfachsten erreichst Du das *erste* Ziel, das Blinken der Scroll-Lock-Anzeige mit der Exec-Methode.

          In Deinem Code vereinfacht sich die Funktion Flashlight() zu:

          Function FlashLight()
                wscript.sleep 220
                wss.sendkeys "{SCROLLLOCK}"
          End Function

          die Aufrufstelle ändert sich (mit der jetzt unpassend benannten Variablen ReturnCode) zu:

          Dim ReturnCode

          ' Starte den Download asynchron
          Set ReturnCode = wss.Exec(srun)

          ' Lasse während der Download läuft, die Scroll-Lock-Taste blinken.
          Do While ReturnCode.Status = 0
              FlashLight
          Loop

          ' TODO: Zähler einbauen, um am Ende Scroll-Lock wieder auszuschalten,
          '       wenn die Anzahl der Aufrufe von Flashlight() ungerade war.

          Nachteil dieses ersten Schrittes ist, dass Dir bei Exec() keine Parameter zur Fenstersteuerung zur Verfügung stehen. Das kriegst Du aber sicher selbst hin.

          Freundliche Grüße

          Vinzenz

          1. Hallo,

            ...die Execute-Methode des Windows Scripting Host ...
            weil sie es ermöglicht, einen Prozess asynchron auszuführen und auf sein Ende zu reagieren - und es die erste war, die mir eine Suche präsentierte.

            Der Sinn des ScrollLock-Blinkens ist - wie schon Eingangs erwähnt - (Zitat: "Während Download ... im "Hide-Modus ..."), dass eine optische Kontrolle vorhanden ist, während das Programm ohne Ausgabe auf dem Monitor läuft - da scheidet die Execute-Methode wohl aus.

            Die Run-Methode des WScript.Shell-Objektes erlaubt Dir ebenfalls, einen Prozess asynchron auszuführen, ich hab' allerdings auf die Schnelle keine Möglichkeit gesehen, wie man auf das Ende des Prozesses reagieren kann. Du verhinderst die asynchrone Ausführung explizit mit Deinem dritten Parameter, dem Du den Wert true zuweist.

            Ich weiss, den Wert true muss ich jedoch zwangsweise zuweisen, da ich bei false sonst keinen Rückgabewert bekomme, den ich jedoch zum Abbrechen der FlashLight-Schleife benötigen würde.

            ' TODO: Zähler einbauen, um am Ende Scroll-Lock wieder auszuschalten,
            '       wenn die Anzahl der Aufrufe von Flashlight() ungerade war.

            ...danke, ist in der ausfühlichen Flashlight() Funktion natürlich berücksichtigt.

            Nachteil dieses ersten Schrittes ist, dass Dir bei Exec() keine Parameter zur Fenstersteuerung zur Verfügung stehen. Das kriegst Du aber sicher selbst hin.

            Genau das macht die Execute-Methode für mein Vorhaben unbrauchbar.

            Mein jetziger Lösungsansatz:
            Starte vor dem Ausführen des Downloads mit der Run-Methode im Hide-Modus asynchron (3. Parameter false) FlashLight.vbs .
            Das Script FlashLight.vbs überprüft die Download-Logdatei von WGet auf Vorhandensein, startet das Blinken, überprüft im Sekundentakt ob die Zeichenfolge "FINISHED" gefunden wird und beendet dann die Schleife.

            Mit Freundlichem Gruß und
            großem Dank für die Lösungsvorschläge

            JPS

            1. Hallo,

              ...die Execute-Methode des Windows Scripting Host ...
              weil sie es ermöglicht, einen Prozess asynchron auszuführen und auf sein Ende zu reagieren - und es die erste war, die mir eine Suche präsentierte.

              Der Sinn des ScrollLock-Blinkens ist - wie schon Eingangs erwähnt - (Zitat: "Während Download ... im "Hide-Modus ..."), dass eine optische Kontrolle vorhanden ist, während das Programm ohne Ausgabe auf dem Monitor läuft - da scheidet die Execute-Methode wohl aus.

              Nö. Klappt wunderbar. Execute() ist *nicht* Exec()!

              Die Run-Methode des WScript.Shell-Objektes erlaubt Dir ebenfalls, einen Prozess asynchron auszuführen, ich hab' allerdings auf die Schnelle keine Möglichkeit gesehen, wie man auf das Ende des Prozesses reagieren kann. Du verhinderst die asynchrone Ausführung explizit mit Deinem dritten Parameter, dem Du den Wert true zuweist.

              Ich weiss, den Wert true muss ich jedoch zwangsweise zuweisen, da ich bei false sonst keinen Rückgabewert bekomme, den ich jedoch zum Abbrechen der FlashLight-Schleife benötigen würde.

              ' TODO: Zähler einbauen, um am Ende Scroll-Lock wieder auszuschalten,
              '       wenn die Anzahl der Aufrufe von Flashlight() ungerade war.

              ...danke, ist in der ausfühlichen Flashlight() Funktion natürlich berücksichtigt.

              Dachte ich mir. Ist nur überflüssig. Der Zähler kommt außenrum, um den Aufruf.
              Flashlight() braucht nicht mehr zu können, als die von mir skizzierte Geschichte:

              schlafen
                Taste drücken

              Mein jetziger Lösungsansatz:

              ist unschön. Was nach Anlaufproblemen wunderbar funktionierte war eine Aufteilung in zwei Skripte:

              a) Steuerskript
              b) Downloadskript

              a) Steuerskript (jps.vbs)

              ' --------------------------------------------------------------------------
              Option Explicit

              Dim WshShell     : Set WshShell = WScript.CreateObject("WScript.Shell")
              Dim Controller   : Set Controller   = WScript.CreateObject("WSHController")

              ' Starte Downloadskript
              Dim RemoteScript : Set RemoteScript = Controller.CreateScript("download.vbs")
              RemoteScript.Execute

              Dim LightOn      : LightOn = False

              ' Lass es blinken, solange das Downloadskript läuft
              Do While RemoteScript.Status <> 2
              wscript.sleep 200
              WshShell.sendkeys "{SCROLLLOCK}"
              LightOn = Not LightOn
              Loop

              ' Schalte, falls nötig Scroll-Lock aus
              If LightOn = True Then
                  WshShell.sendkeys "{SCROLLLOCK}"
              End If
              ' --------------------------------------------------------------------------

              b) Downloadskript (download.vbs)

              ' --------------------------------------------------------------------------
              Option Explicit

              Dim WshShell     : Set WshShell = WScript.CreateObject("WScript.Shell")
              Dim downloadpath : downloadpath = "K:\test"
              Dim logfile      : logfile      = downloadpath & "\Download.log"
              Dim debug        : debug        = 1   ' 0=Debug auf Konsole; 1=Debug in Logfile
              Dim wndmode      : wndmode      = 3   ' 0=hide; 1=default; 2=minimized; 3=maximized
              Dim zipfile      :zipfile      = "http://downloads1.kaspersky-labs.com/zips/av-i386-weekly.zip"

              GetFile zipfile, downloadpath, debug, logfile, wndmode

              '************************
              Function GetFile(sfile,dest,plog,logfile,wndstate)
              '************************
                  ' plog (0=Debug auf Konsole; 1=Debug in Logfile)

              ' WGet Parameter
                  ' --------------
                  ' -t (Number of Tries)
                  ' -T (Network "timeout" in sec)
                  ' -N (Turn on time-stamping)
                  ' -P (Präfix for Downloadpath)
                  ' -o (Präfix for Logfile)

              Dim appl
              appl = "K:\Test\WGet.exe -t 3 -T 10 -N -P "

              Dim vt

              Select Case plog  
              

              Case 0  vt  = ""
                      Case 1  vt  = "-o "
                  End Select

              Dim srun
              srun = appl & chr(34) & dest & chr(34) & _
                                  chr(32) & sfile & chr(32) & _
                                  vt & chr(34) & logfile & chr(34)

              WshShell.run srun, wndstate, true
              End Function
              ' --------------------------------------------------------------------------

              und nun kannst Du wieder wunderbar den Fensterstatus beeinflussen.
              Vergleichbar könntest Du bestimmt mit Exec() ein Skript aufrufen, statt wget direkt. Hab' ich nicht ausprobiert.

              Freundliche Grüße

              Vinzenz

              1. Hallo Vincent,

                vielen Dank für Deine Mühe.

                Nö. Klappt wunderbar. Execute() ist *nicht* Exec()!

                Oh, habe da offensichtlich wohl was verwechselt. Werde Deinen Vorschlag sobald wie möglich mal umsetzen. Komme aber erst Anfang nächster Woche dazu. Gebe dann gern nochmal eine Rückmeldung.

                Nochmals vielen Dank, dass Du mir "auf die Sprünge geholfen" :) hast.

                Freundlichen Gruss

                JPS