Kann man ein VBScript per Tastendruck beenden?

2 Antworten

Vom Beitragsersteller als hilfreich ausgezeichnet

Heute auf der Gassirunde ist mir noch eingefallen, wie man auf extrem "schräge" Art globalen Hotkey zum abbrechen des Scripts einrichtet.

Eigentlich total simpel. Einfach in einer Desktopverknüpfung den Hotkey einrichten und taskkill für das "BimmelScript" als auszuführendes Programm.

Das Einrichten der Verknüpfung lässt sich wieder mit einem kleinen JavaScript"programm" erledigen. Optional wird die Verknüpfun auch noch unsichtbar gemach, so das nur der HotKey für den Zugriff existiert.

in der Demo wird mit CTRL+Alt+W die Aktion ausgelöst. Aber Achtung, das Script kann auch Tastenkombis in die Ereignisverarbeitung eintragen, welche über das Eigenschaftenfenster einer Verknüpfung unmöglich sind!

"Nackte" Buchstaben können durchaus sehr unerwünschte Reaktionen herbeiführen😅😱

demo.cmd

@echo off
set "HotKey=CTRL+Alt+W"
  rem generiere Script zum erzeugen einer Desktopverküpfung (auch mit Hotkey)
if not exist "%temp%\CreateShortCut.js" echo args=WScript.Arguments;if (args.length^>7){ShCt=new ActiveXObject('WScript.Shell').CreateShortcut(args(0));ShCt.TargetPath=args(1);ShCt.Arguments=args(2).replace(/'/g,String.fromCharCode(34));ShCt.IconLocation=args(3);ShCt.WorkingDirectory=args(4);ShCt.Description=args(5);ShCt.HotKey = args(6);if(args(7).match(/^^\d$/)){ShCt.WindowStyle=args(7)};ShCt.Save()};>"%temp%\CreateShortCut.js"
  rem DesktopShortcut zum Beenden des "Nervscripts" (setzt auch die Globale Tastenkombination)erzeugen.
  rem Parameter: "Shortcut-Datei" "ZielProgramm für den Shortcut" "[optional:Argumente  !!!innere "Gänsefüßchen nicht möglich"!!!]"  "[optional:Icondatei,iconindex]" "[optional:ArbeitsVerzeichnis]" "[optional:Anmerkungen]" "[optional:Tastenkombination (aus:ALT+,CTRL+,SHIFT+,A..Z,0..9,Back,Tab,Clear,Return,Escape,Space,Prior)]" "[optional:Fenstemodus (3=Maximiert,4=normal oder 7=minimiert)]"
  rem Es müssen immer 7 Werte angegeben werden! Leere Werte/default mit "" angeben.
  rem Argumente, welche normalerweise  in "Gänsefüßchen" übergeben würden, stattdessen in 'SingleQuotes' schreiben! zB. "Argument1 'Agument in normalerweise Gänsefüßchen' usw."
  rem Icon-Indexe  für Shell32.dll: https://help4windows.com/windows_8_shell32_dll.shtml
cscript //nologo "%temp%\CreateShortCut.js" "%userprofile%\Desktop\Kill WavLoop.lnk" "taskkill.exe" "/f /fi 'Windowtitle eq WavLoop'" "%SystemRoot%\System32\shell32.dll,131" "" "Killt das Fenster: WavLoop" "%HotKey%" "7" 
  rem shortcut unsichtbar machen (wenn man nur die Tastenkombi Nutzen möchte) 
attrib "%userprofile%\Desktop\Kill WavLoop.lnk" +h

  rem starte den soundloop
set "wavFile=C:\Windows\Media\Ring10.wav"
echo objSPVoice=new ActiveXObject("SAPI.SpVoice");objSPFile=new ActiveXObject("SAPI.SpFileStream");objSPFile.Open('%wavFile:\=\\%');while(true){objSPVoice.SpeakStream(objSPFile)};>"%temp%\wavOutLoop.js"
start "WavLoop" /min cscript //nologo "%temp%\wavOutLoop.js"

Zugegeben , die "Nummer" ist extrem "schmutzig" gedacht, aber mit 6 Zeilen netto in keiner anderen Sprache zu toppen. "Batch as Batch can" 😁

Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren

VBScript kann keine einzelnen Tastendrücke lesen und auswerten.

inkey$ ist ein GWBasic Variable und hat nichts mit VBS zu tun.

Das würde auch keinen Sinn machen, da es standardmäßig über wscript startet welches kein eigenes Fenster besitzt und über Boxen kommuniziert , welche immer warten.

Die Konsolenvariante cscript kann nur von Standardstream lesen. Es gäbe durchaus Verrenkungen um eine abbruchfähige Vbs-Entlosschleife hinzubekommen, aber wäre für sowas pure Zeitverschwendung.

Die Handhabung von VBScript/JScript bezüglich des Dateisystems ist einfach zu umständlich um damit umfangreiche Sachen anzustellen. Deshalb wurden diese schon immer als HilfsScripte verwendet, welche per Batch gesteuert/generiert gezielt Systemnahe Aufgaben übernehmen. dabei lässt sich mit Jscript besser arbeiten, da man das gesamte Script in eine Zeile schreiben kann.

Mit Batch und einem automatisch generiertes Javascript lässt sich schon mal (ein in Endlosschleife laufendes) Script in die Taskleiste minimieren. das gibt die Möglichkeit es auch wieder per Maus zu schließen.

LoopWav.cmd

@echo off
set "wavFile=C:\Windows\Media\Ring10.wav"
echo objSPVoice=new ActiveXObject("SAPI.SpVoice");objSPFile=new ActiveXObject("SAPI.SpFileStream");objSPFile.Open('%wavFile:\=\\%');while(true){objSPVoice.SpeakStream(objSPFile)};>"%temp%\wavOutLoop.js"
start "WavLoop" /min cscript //nologo "%temp%\wavOutLoop.js"

Hier eine billige Variante welche, welche das "Eingabe"-Fenster offen lässt und das minimierte Script per beliebiger Taste beendet:

LoopWav2.cmd

@echo off
chcp 65001 >nul
set "wavFile=C:\Windows\Media\Ring10.wav"
echo objSPVoice=new ActiveXObject("SAPI.SpVoice");objSPFile=new ActiveXObject("SAPI.SpFileStream");objSPFile.Open('%wavFile:\=\\%');while(true){objSPVoice.SpeakStream(objSPFile)};>"%temp%\wavOutLoop.js"
  rem starte unser "Nervscript" minimiert mit dem Fensternamen WavLoop
start "WavLoop" /min cscript //nologo "%temp%\wavOutLoop.js"
echo Drücke eine beliebige Taste um das Gedudel zu beenden.
pause >nul
  rem beende gezielt das Fenster mit dem Namen WavLoop
taskkill /fi "Windowtitle eq WavLoop"

um das Script komplett unsichtbar laufen zu lassen ist das vorgehen fast gleich, nur das wir es mit wscript ausführen. Dies verfügt über kein eigenes Fenster und erscheint nicht in der Taskleiste. Das macht das gezielte beenden schwierig. Da wohl kaum eine weitere Instanz von Wscript laufen dürfte genügt es einfach alles was wscript.exe heist zu killen.

LoopWav3.cmd

@echo off
chcp 65001 >nul
set "wavFile=C:\Windows\Media\Ring10.wav"
echo objSPVoice=new ActiveXObject("SAPI.SpVoice");objSPFile=new ActiveXObject("SAPI.SpFileStream");objSPFile.Open('%wavFile:\=\\%');while(true){objSPVoice.SpeakStream(objSPFile)};>"%temp%\wavOutLoop.js"

  rem da wscript kein Fenster hat, gibts auch  keinen Titel zu setzen
start "" wscript "%temp%\wavOutLoop.js"
echo Drücke eine beliebige Taste um das Gedudel zu beenden.
pause >nul
  rem hier konnen wir nur knallhart jedwede Instanz von wscript.exe abschießen (ginge schon gezielt, aber mit viel mehr Aufwand)
taskkill /im wscript.exe /f

Die Fenster kannst Du auch mit der Maus schließen. Die Scripte werden auch nach dem nächsten Start mit einer beliebigen taste beendet.

Das war die Quick&Dirty-Methode. Natürlich kann man das auch hübsch sauber in C# programmieren, aber mal ehrlich für solchen Kleinkram ist jede Zeile zu schade.

SAPI.SpVoice ist eigentlich gemacht um Text als Sprache auszugeben.

Quasseluhr.cmd

@echo off
 rem Umlaute erlauben
chcp 65001>nul
 rem fenstergröße
mode 50,2
title Quasseluhr

set "sayJS=%temp%\say.js"
set "Speed=-1"
set "Volume=100" 
echo s=new ActiveXObject('SAPI.SpVoice');s.Rate=%Speed%;s.Volume=%Volume%;a='';for (i=0;i^<WScript.Arguments.length;i++){a+=WScript.Arguments(i)+' '};s.Speak(a,0)>"%sayJS%"
set talk=cscript //nologo "%sayJS%"
set talkAsync=start "" /b %talk%
::Ende Sprachausgabe einrichten

%talk% Ich bin Deine Quassel-uhr.
%talk% Schön das du mich die Zeit ansagen lässt

:loop
 rem erzeuge Beep...
start "" /b cmd /c echo ax^|choice /c x ^>nul
cls
echo He Meister, beim Piepton war es %time:~0,8% Uhr
 rem sage die Uhrzeit
%talkAsync% He Meister, beim Piepton war es %time:~0,8% Uhr
 rem warte eine Minute (kleine Zeitverschiebungen sind möglich, cls braucht einige Millisekunden und läuft nicht Asynchron)
timeout 60 >nul
goto :loop

Das abspielen von Adiodateienmit SAPI.SpVoice hat einen entschiedenen Nachteil , es kann nur .wav und auch nicht Parallel.

Das kann WMPlayer.OCX viel besser:

playAudio.cmd

@echo off
chcp 65001 >nul & rem Umlaute anzeigen

if "%~1"=="" (
  echo keine Dateien Übergeben!
  echo Ziehe beliebig viele Audiodateien auf "%~nx0" ...
  timeout 5 >nul
  exit /b
)
 rem das Playerscript muss nur einmal geschrieben werden
if exist "%temp%\PlaySound.js" goto :Play
echo player = new ActiveXObject("WMPlayer.OCX.7");for (i=0; i^<WScript.Arguments.length; i++) {player.URL = WScript.Arguments(i);player.Controls.play();while (player.currentmedia.duration==0) { WScript.sleep(100)};WScript.sleep(player.currentmedia.duration*1000);}>"%temp%\PlaySound.js"
:Play
start "Player" /min cscript //nologo "%temp%\PlaySound.js" %*

Dieses Script spielt sogar IntenetStreams:

start "MDRJump_Player" /min cscript //nologo "%temp%\PlaySound.js" "http://mdr-284320-0.cast.mdr.de/mdr/284320/0/mp3/high/stream.mp3"
Woher ich das weiß:eigene Erfahrung – Ich mach das seit 30 Jahren