HomePC-TrixLogixOptixProxMagixCoolzeuxLinxBeixTräx

Tips zum Windows Scripting Host

Der Windows Scripting Host (WSH) ist eine abgespeckte Variante von Visual Basic. Er ist mächtiger als die guten alten DOS-Batchdateien, aber dementsprechend leider auch weniger leicht zu erlernen.

Nachfolgend einige Module, die ich in unterschiedlichen Scripten immer wieder für die Dateiverwaltung und zur bequemeren Bedienung von Programmen einsetze. Alle Beispiele sind vollständige Scripte, damit diese mit Copy&Paste schnell übertragen und als Scriptdatei (*.vbs) getestet werden können. In einigen Fällen sind evtl. die Pfade anzupassen.

Anwendungen starten

set ws = wscript.createobject("wscript.shell")
ws.Run "Notepad.exe"


Auch Parameter können verwendet werden:

set ws = wscript.createobject("wscript.shell")
ws.Run "Notepad.exe " + "1.txt", 2, vbtrue

Der Parameter vbtrue bewirkt, dass das Script mit der weiteren Ausführung wartet, bis die gestartete Anwendung wieder geschlossen wurde.

Wichtig: Das Leerzeichen zwischen Programmbefehl und dem abschließenden Anführunxzeichen. Dies ist immer dann erforderlich, wenn mit dem Programmbefehl ein Befehlszeilenparameter, im oberen Beispiel also 1.txt, verknüpft wird. Grund: Ohne Leerzeichen kann der WSH die Grenze zwischen Programm und Parametern nicht erkennen und steigt aus. Aus demselben Grund wird ein Leerzeichen auch bei der Verwendung von Parametern unmittelbar hinter dem Programmbefehl, im nachfolgenden Beispiel also vor dem Parameter /n benötigt:

set ws = wscript.createobject("wscript.shell")
ws.Run "explorer.exe /n", 1


Die Zahlen bedeuten:

Fenster ist vollkommen unsichtbar.
Normale Fenstergröße
Minimiertes Fenster (erscheint in der Taskleiste, ist ausgewählt)
Maximiertes Fenster (bildschirmfüllend)
Fenster wird geöffnet, aber vorher aktives Fenster bleibt aktiv
Fenster wird in derselben Größe geöffnet wie beim letzten Mal
Minimiertes Fenster. Nächste Fenster in der Reihenfolge wird aktiv
Minimiertes Fenster. Das vorher aktive Fenster bleibt aktiv
Fenster wird in derselben Größe geöffnet wie beim letzten Mal.
   Vorher aktives Fenster bleibt aktiv
Fenster erscheint in normaler Größe

Verknüpfte Dateitypen können auch direkt gestartet werden:

set ws = wscript.createobject("wscript.shell")
ws.run "C:\Testordner\1.txt", 1

Wenn man nicht mit DOS-Pfaden arbeiten will, muss man Pfad- und Dateinamen, die Leeerzeichen enthalten, mit chr(34) in Anführunxzeichen setzen, z. B.:

set ws = wscript.createobject("wscript.shell")
ws.run chr(34) & "C:\Testordner 103\Datei zum Testen.txt" & chr(34), 1

Arbeitsverzeichnis setzen

Einen "CD"-Befehl ("Change Directory") wie unter DOS gibt es in VBScript zwar nicht, doch lässt sich das aktuelle Arbeitsverzeichnis mit der CurrentDirectory-Eigenschaft setzen oder auslesen:

Set ws = WScript.CreateObject("WScript.Shell")
ws.CurrentDirectory = "H:\Prox" 'Ordner muss existieren, sonst Fehlermeldung
msgbox ws.CurrentDirectory

Ich habe mir angewöhnt, standardmäßig den Ordner, in dem ein Script gestartet wird, als aktuelles Arbeitsverzeichnis zu setzen. Dann kann man Dateien in diesem Ordner mit ihrem Dateinamen aufrufen, ohne den Pfad beachten zu müssen. Interessant für Scripts, die vom USB-Stick laufen.

Set fs= CreateObject("Scripting.FileSystemObject")
Set ws = WScript.CreateObject("WScript.Shell")
Set Scriptdatei = fs.GetFile(WScript.ScriptFullName) 'Scriptordner ermitteln
ws.CurrentDirectory = Scriptdatei.ParentFolder 'Scriptordner als Arbeitsverzeichnis setzen
msgbox ws.CurrentDirectory

Datei als überarbeitete Kopie speichern

Die Datei 103.txt wird geöffnet und zeilenweise ausgelesen. Wenn eine Zeile aus dem Begriff "Duhden" besteht, wird dieser durch "Duden" ersetzt. Alle Zeilen werden in die neu angelegte Datei 103neu.txt eingelesen. Dadurch erhalten wir eine überarbeitete Kopie der Ausganxdatei. Achtung: Falls eine Datei 103neu.txt bereits existiert, wird sie ohne Rückfrage überschrieben.

Set fs= CreateObject("scripting.filesystemobject")
set LeseDatei = fs.opentextfile("C:\Prox\103.txt")
set SchreibeDatei = fs.opentextfile("C:\Prox\103neu.txt", 2, true)

Do Until LeseDatei.AtEndOfStream
  Zeile = LeseDatei.ReadLine
  if zeile = "Duhden" then
    zeile = "Duden"
  end if
  SchreibeDatei.WriteLine(Zeile)
Loop

LeseDatei.Close
SchreibeDatei.Close

DOS Befehle ausführen

Manchmal ist es erheblich einfacher, schnell einen DOS-Befehl in eine Scriptdatei einzufügen, anstatt die entsprechende Funktion mühsam Visual Basic-konform zu programmieren. Durch die DOS-Befehle poppt normalerweise eine Eingabeaufforderung auf. Diese kann man allerdinx unterdrücken, so dass nichts beim Scriptablauf störend wirkt.

Nachfolgendes Beispiel zeigt den Inhalt von C:\ und läuft daher sichtbar ab:

Set ws = CreateObject("WScript.Shell")
ws.Run "%COMSPEC% /K DIR C:\",1


%COMSPEC% ist je nach Betriebssystem die Umgebunxvariable f. command.com oder cmd.exe
%COMSPEC% /K bedeutet: Eingabeaufforderung bleibt geöffnet
%COMSPEC% /C bedeutet: Schließen der Eingabeaufforderung nach Ausführung des Befehls

Das nachfolgende Beispiel läuft unsichtbar ab und löscht unter Windoof 9x den Inhalt eines Ordners ohne Rückfrage:

Set ws = CreateObject("WScript.Shell")
ws.Run "%COMSPEC% /C DELTREE /Y C:\Test\*.*",0


Tip: Gerade beim unsichtbaren Ablauf sollte man das automatische Schließen der Eingabeaufforderung nach Ausführung nicht vergessen, da diese sonst im Hintergrund offen bleibt.

Netzlaufwerke verbinden und trennen

Das nachfolgende Script läuft unsichtbar ab. Es verbindet beispielhaft 3 Netzlaufwerke, davon die ersten beiden dauerhaft und das dritte nur für die aktuelle Sitzung. Im zweiten Beispiel kommt am Ende des Pfades der Ordner "Archiv 103" vor. Da ein Leerzeichen im Pfad Probleme beim Verbinden des Netzlaufwerks verursachen kann, wird hier die DOS-konforme Schreibweise "ARCHIV~1" verwendet.

Set ws = Wscript.CreateObject("Wscript.Shell")
ws.Run "net use G: \\siesr20103\gruppen\sie\abc$ /PERSISTENT:YES", 0, vbtrue
ws.Run "net use H: \\siesr20206\gruppen\ARCHIV~1 /PERSISTENT:YES", 0, vbtrue
ws.Run "net use X: \\server103008\siefahrer.02$ /PERSISTENT:NO", 0

Hier werden die Netzlaufwerke wieder getrennt:

Set ws = Wscript.CreateObject("Wscript.Shell")
ws.Run "net use G: /delete", 0
ws.Run "net use H: /delete", 0
ws.Run "net use X: /delete", 0

Opera Favicons löschen

Beim Surfen speichert Opera automatisch von jeder Webseite ein evtl. vorhandenes Favicon im Ordner \profile\images im Opera-Programmordner ab. Auf diese Weise können sich im Lauf der Zeit Tausende von Icon-Dateien ansammeln. Natürlich kann man den Ordner ab und zu manuell leeren, doch dann sind auch die Favicons der abgespeicherten Lesezeichen erst mal weg.

Das Script schafft hier Abhilfe: Es löscht nur diejenigen Favicons, die nicht als Lesezeichen vorliegen. Datzu vergleicht es die Icons in \profile\images mit den Einträgen in der Bookmarkdatei (opera6.adr). Icons, die nicht als Bookmarks vorliegen, werden gelöscht.

Set fs= CreateObject("scripting.filesystemobject")
Set ws = CreateObject("WScript.Shell")

Set LesezeichenDatei = fs.opentextfile("K:\Prox\OperaUSB\profile\opera6.adr", 1, true)
Set IconOrdner = fs.GetFolder("K:\Prox\OperaUSB\profile\images")

' Einlesen der Lesezeichendatei in einen String
Inhalt = LesezeichenDatei.ReadAll
LesezeichenDatei.close

' Alle Dateien des Ordners \images einlesen u. prüfen, ob sie in Lesezeichendatei vorkommen
Geloeschte = 0
AnzIcons = 0
Set IconArray = IconOrdner.Files

For Each Icon in IconArray
  AnzIcons = AnzIcons + 1
  If Instr(1, Inhalt, Icon.name, 1) = 0 Then
    Icon.delete
    Geloeschte = Geloeschte + 1
  End If
Next

MsgBox Geloeschte & " Icon(s) von " & AnzIcons & " gelöscht", 64, "Opera Favicons löschen"

Popup mit Auswahl

Ein Popup ist eine sich selbst schließende Messagebox.

Set ws = Wscript.CreateObject("Wscript.Shell")
BtnCode = ws.Popup ("Ich bin in 3 Sekunden verschwunden!", 3, "Information", 1 + 64)

Select Case BtnCode
   case 1      msgbox "OK gedrückt"
   case 2      wscript.quit
   case -1     msgbox "Kein Knopf gedrückt" 'Diese Meldung erscheint nach Ablauf der Zeit
End Select

Registry von WinNT/2k/XP sichern mit ERUNT

Das Script öffnet eine Inputbox, in die ein Name für einen Sicherungsordner eingegeben werden kann. Voreingestellt ist ein Ordnername, der aus dem Tagesdatum in der Form "2007-08-28" besteht. Dann startet es ERUNT.EXE, das den neuen Ordner im Pfad E:\103\Erunt\ anlegt und dort hinein die Dateien der Registry (System + aktuell angemeldete Benutzer) kopiert. Ist der Ordner bereits vorhanden, und sind evtl. bereits Dateien darin, werden diese ohne Rückfrage gelöscht. ERUNT lässt sich nur als Administrator einsetzen. Siehe auch unter Win-Tips.

Set ws = CreateObject("WScript.Shell")
Verz = "E:\103\Erunt\"
Tagesdatum = Date ' Form: 28.08.2007
Feld = Split(Tagesdatum, ".") ' Datum in TT MM JJ auftrennen
Datum= Feld(2)&"-"&Feld(1)&"-"&Feld(0) ' Form: 2007-08-28
Ordner = InputBox("Ordnername eingeben:", "Win2k Registry sichern", Verz & Datum)
If Ordner = "" then wscript.quit

ws.Run "K:\Prox\ERU_NT\ERUNT.EXE" & " " & Ordner & " sysreg curuser otherusers /noconfirmdelete"

Runas-Befehl automatisiert

Mit diesem Script kann man ab Win2k ein Programm unter einem anderen Benutzerkonto als dem aktuellen starten, ohne eine Eingabe zu machen. Siehe auch unter Administraitor-Tips.

' Registry-Editor als Administrator starten
' Clientname: SIE103
' Benutzername: admin
' Kennwort: 103103-8

Set ws = CreateObject("WScript.Shell")
Prog = "regedit.exe"

ws.run "runas /user:SIE103\admin " + CHR(34) + Prog + CHR(34)
wscript.sleep 1000
ws.Sendkeys "{1}{0}{3}{1}{0}{3}{-}{8}{ENTER}"


Weitere Beispiele für die Variable "Prog":
"cmd.exe"   Eingabeaufforderung
"mmc.exe compmgmt.msc"   Computerverwaltung
"rundll32 shell32.dll,Control_RunDLL Sysdm.cpl"   Systemsteuerung
"rundll32 shell32.dll,Control_RunDLL Appwiz.cpl"   Systemsteuerung Software
"regedit /s C:\Prox\TEST.REG"   Registrierungsdatei einlesen
"wscript D:\Temp\Tools\Hallo.vbs"   VBScript starten

Scriptordner ermitteln

Aktuelles Verzeichnis ermitteln, in dem das Script liegt

Set fs= CreateObject("Scripting.FileSystemObject")
Set ws = WScript.CreateObject("WScript.Shell")
Set Scriptdatei = fs.GetFile(WScript.ScriptFullName)
msgbox Scriptdatei.ParentFolder

SAP per Script fernsteuern

Automatisiert den SAP-Logon durchführen und eine Transaktion aufrufen. Es ist möglich, dass das SAP-Programmfenster im Hintergrund verbleibt, wenn man in der Zwischenzeit mit anderen Programmen arbeiten möchte.

ws.Run chr(34) & "C:\Program Files\SAP\SapSetup\setup\SAL\SapLogon.s8l" & chr(34)

'Warteschleife Anfang: Warten, bis bis SAP-Logon geladen ist
On error resume next
Do
  err.number = 0
  wscript.sleep 200
  Set SapGuiAuto  = GetObject("SAPGUI")
  If err.number = 0 then
    Exit Do
  End if
Loop
on error goto 0
'Warteschleife Ende

If Not IsObject(application) Then
   Set SapGuiAuto  = GetObject("SAPGUI")
   Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
  'Set connection = application.Children(0) 'Wenn bereits eine Verbindung geöffnet ist
  Set connection = application.OpenConnection("A11 [Werke]") 'Verbindung öffnen
End If
If Not IsObject(session) Then
   Set session    = connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session,     "on"
   WScript.ConnectObject application, "on"
End If

session.findById("wnd[0]/usr/txtRSYST-BNAME").text = "DB0DDC2" 'Benutzer
session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "32323232" 'Passwort
session.findById("wnd[0]").sendVKey 0

If session.Children.Count > 1 then 'Falls hier Fenster Systemnachrichten erscheint
  session.findById("wnd[1]/tbar[0]/btn[12]").press 'Systemnachrichten bestätigen
End If

'Hauptfenster "SAP Easy Access" muss offen sein
session.findById("wnd[0]/tbar[0]/okcd").text = "ZIIS_CO24"
session.findById("wnd[0]/tbar[0]/btn[0]").press 'Häkchen "Weiter" zum Übernehmen der Eingabe

'Maske "ISI Fehlteilinfosystem" erscheint
session.findById("wnd[0]/usr/radE_READ").select '"Gespeicherte Auswertungen"/"Ergebnis laden" wählen
session.findById("wnd[0]/tbar[1]/btn[8]").press '"Button Ausführen(F8)" drücken

'Fenster "Vorhandene Listauswertungen..." erscheint
session.findById("wnd[1]/usr/tblSAPLZPERTABCON01").getAbsoluteRow(0).selected = true '1. Eintrag (Index 0) wählen
session.findById("wnd[1]/tbar[0]/btn[0]").press '"Button Ausführen(Enter)" drücken

'Ergebnisliste "ISI Fehlteilinfosystem" erscheint
session.findById("wnd[0]/mbar/menu[0]/menu[1]/menu[2]").select 'Menüpunkt "Fehlteilinfosystem/Exportieren/Lokale Datei"

'Fenster "Liste sichern in Datei..." erscheint
session.findById("wnd[1]/usr/subSUBSCREEN_STEPLOOP:SAPLSPO5:0150/sub:SAPLSPO5:0150/radSPOPLI-SELFLAG[1,0]").select 'Auswahl "Tabellenkalkulation"
session.findById("wnd[1]/tbar[0]/btn[0]").press '"Button Weiter(Enter)" drücken

'Speicherdialog "ISI Fehlteilinfosystem" erscheint
session.findById("wnd[1]/usr/ctxtDY_PATH").text = "C:\Test\"
session.findById("wnd[1]/usr/ctxtDY_FILENAME").text = Datum & " Fehlteile.xls"
session.findById("wnd[1]/tbar[0]/btn[11]").press 'Button "Ersetzen" drücken

'Ergebnisliste "ISI Fehlteilinfosystem" erscheint
session.findById("wnd[0]/tbar[0]/btn[15]").press 'Button "Abbrechen (F12)" drücken
session.findById("wnd[0]/tbar[0]/btn[15]").press 'Button "Abbrechen (F12)" drücken
'Hauptfenster "SAP Easy Access" erscheint

session.findById("wnd[0]/mbar/menu[4]/menu[12]").select 'Menüpunkt "System/Abmelden"
session.findById("wnd[1]/usr/btnSPOP-OPTION1").press 'Button "Ja" drücken

wscript.sleep 3000
'SAP-Logon-Fenster mit selbstgebasteltem Prog schließen. Mit den beiden Befehlen
'ws.AppActivate("SAP Logon 710") u. ws.sendkeys "%{F4}" geht es nicht, da Fenster meist minimiert ist
ws.run chr(34) & "C:\SAP\CloseWindow.exe" & chr(34) & " " &  chr(34) & "SAP Logon 710" & chr(34)

Timer oder Erinnerungs-Popup

Nach Ablauf einer frei einstellbaren Wartezeit erscheint eine Meldung. Die voreingestellte Ruhezeit des Scripts je Warteschleife beträgt hier 30 Sekunden.

set ws = wscript.createobject("wscript.shell")
Minuten = InputBox("Verbleibende Minuten eingeben:", "Erinnerungspopup")
Zeitpunkt = DateAdd("n", Minuten-1, Now)
While Zeitpunkt > Now
  wscript.sleep 30000
Wend
Msgbox "Zeit abgelaufen!"

Warteschleifen

Ziel: Warten, bis ein Anwendungsfenster geladen ist - alle 200 Millisekunden checken. Wenn Anwendungsfenster da ist, wird es aktiv gesetzt und die Warteschleife verlassen. Immer wieder erforderlich, wenn Tastatureingaben erst dann an ein Anwendungsfenster geschickt werden sollen, wenn dieses auch geladen ist. Im Gegensatz zur Methode wscript.sleep wartet das Script auch dann, wenn das Fenster länger zum Laden braucht.

1. Methode mit WHILE - WEND

set ws = wscript.createobject("wscript.shell")
ws.Run "C:\Programme\Internet Explorer 5\IEXPLORE.EXE"
'Warteschleife
WHILE ws.AppActivate("Google - Microsoft Internet Explorer") = "Falsch"
  wscript.sleep 200
WEND
'Ende der Warteschleife

2. Methode mit DO - LOOP

set ws = wscript.createobject("wscript.shell")
ws.Run "C:\Programme\Internet Explorer 5\IEXPLORE.EXE"
'Warteschleife
DO
  IF ws.AppActivate("Google - Microsoft Internet Explorer") = "Falsch" THEN
    wscript.sleep 200
  ELSE
    EXIT DO
  END IF
LOOP
'Ende der Warteschleife

Anmerkungen:

Die Methoden WHILE - WEND und DO - LOOP sind gleichwertig.

wscript.sleep innerhalb der Warteschleife ist wichtig, damit das Script beim Schleifendrehen immer wieder pausiert und nicht sämtliche Systemressourcen beansprucht. Der Wert 200 ms ist ein Erfahrungswert und kann auch geändert werden; er sollte so hoch gewählt werden, dass das Script möglichst wenig Systemressourcen verbrät, aber so niedrig, dass nicht unnötig lange Pausen entstehen.

Wenn die IF-Bedingung nicht erfüllt wird, eiert das Script unendlich lang im Hintergrund rum. Dies kann man verhindern, wenn man eine definierte Schleifenzahl (= Wartezeit) vorgibt. Optional kann eine Meldung erfolgen, wenn die Bedingung nicht erfüllt wurde. Das funzt folgendermaßen:

3. Methode mit FOR - NEXT

set ws = wscript.createobject("wscript.shell")
ws.Run "C:\PROGRA~1\INTERN~1\IEXPLORE.EXE"
'Warteschleife von 50 x 200 ms = 10 s
FOR i = 1 to 50
  IF ws.AppActivate("Google - Microsoft Internet Explorer") = "Falsch" THEN
    wscript.sleep 200
  ELSE
    i = 50
  END IF
NEXT
'Ende der Warteschleife
IF ws.AppActivate("Google - Microsoft Internet Explorer") = "Falsch" THEN
msgbox "Google wurde nicht geöffnet"
END IF

Anmerkungen:

ELSE
i = 50

setzt den maximalen Schleifenwert, um bei zutreffender Bedingung die Schleife zu verlassen.

Die ws.AppActivate-Methode liefert "Wahr", wenn der Focus auf das Fenster der entsprechenden Anwendung gesetzt werden kann, oder "Falsch", wenn nicht. Eine Abfrage mit "True" und "False" funktioniert nicht zuverlässig.