Die folgenden Beispiele stellen Anwendungen eines Skript-Baukastens dar,
der für verschiedene Aufgaben im Zusammenhang mit dem Dateisystem auf
einfache Weise umfunktioniert werden kann.
Die besonderen Merkmale der folgenden Skriptbeispiele sind:
Rekursion: Damit die Operationen der Skripte auf alle Dateien in einem
Verzeichnisbaum angewendet werden können, verfahren sie nach dem Muster
"Durchsuche das Verzeichnis nach Dateien und bearbeite sie. Dann suche
nach Unterverzeichnissen und rufe Dich für jedes Unterverzeichnis selbst
auf". Die Skripte sind also rekursiv, die darin enthaltene Prozedur
DateiSystemDurchsuchen ruft sich jedesmal selbst
auf, wenn sie in einem Verzeichnis weitere Unterverzeichnisse entdeckt.
Include-Dateien: Was bei großen Compilern möglich ist,
geht auch bei VBS mit einem kleinen Trick: Gleichartige Programmteile werden
in eine eigene Datei ausgelagert, die beim Kompilieren und/oder Aufruf
geöffnet und geladen wird. So werden Skripts übersichtlicher, weil
allgemeine Funktionen in einer zentralen Datei stecken. Jede Verbesserung
und Fehlerbereinigung kommt so allen Skripts zu Gute, die auf die zentrale
Datei zugreifen, im Skript stehen nur noch die speziellen Funktionen, welche
die Besonderheit des Skripts ausmachen.
Das funktioniert leider nicht bei allen Versionen von
Windows. Daher wird hier nur der Weg beschrieben.
Funktionen: Die eigentlichen Befehle, die bestimmen, was das Skript
nun mit einzelnen Dateien zu tun hat, wurden in einer eigene Prozedur am
Ende des Skripts zusammengefasst. Diese Prozedur heißt
Bearbeiten und mit ihr wird festgelegt, was mit
einer gefundenen Datei bzw. Ordner zu tun ist. Natürlich kann das ganze
Skript beschleunigt werden, wenn man diese Prozedur in die Funktion
DateiSystemDurchsuchen integriert und optimal an
die jeweilige Funktion des Skripts anpasst. Doch damit sinkt die
Wiederverwendbarkeit und Übersichtlichkeit und Zuverlässigkeit
des Codes, was wegen der beschränkten Debugging-Funktionen bei VBS doppelt
schmerzt.
Die Skripte können auf mehrere Arten aufgerufen werden:
Drag & Drop: Man markiert im Explorer eine oder mehrere Dateien
und/oder Verzeichnisse und zieht sie auf das Skript
Senden an: Im Ordner \Windows\SendTo kann eine
Verknüpfung zum Skript angelegt werden. Dadurch steht das Skript im Kontextmenü
des Explorers unter Senden an... zur Verfügung.
Hinweis: Der Ordner
\Windows\SendTo ist versteckt, und kann nur angezeigt
werden, wenn man im Explorer im Menü Extras ->
Ordneroptionen (je nach Windows-Version) die Registerkarte
Ansicht wählt und bei Versteckte Dateien die
Option Alle Dateien anzeigen wählt.
Dialog: Falls keine Argumente übergeben wurden, öffnet das
Skript beim Aufrufen ein Windows-Dialogfenster, in dem eine Datei oder ein
Verzeichnis ausgewählt werden kann.
Die grünen Texte im unten angegebenen Quellcode sind Kommentare, die
bei der Eingabe ausgelassen werden können. Alle Skripte wurden zum Download
in der Datei wsh3.cab gespeichert. |
Die Include-Datei |
Option Explicit On Error Resume Next
Dim FS, Liste, Nr, Verzeichnis, Objekt
Set Liste = WScript.Arguments Set FS = CreateObject("Scripting.FileSystemObject")
If Liste.Count > 0 Then ' Then wird ausgeführt, wenn aus dem Explorer Dateien ' mit Drag & Drop auf diese Skript-Datei gezogen wurden For Nr = 0 To Liste.Count - 1 DateiSystemDurchsuchen Liste(Nr) Next Else
' Else wird ausgeführt, wenn dieses Skript gestartet ' wurde, ohne dass Argumente übergeben wurden
' Ruft einen Dialog von Windows auf, mit dem eine ' Datei oder ein Ordner ausgewählt werden kann Set Verzeichnis = CreateObject("Shell.Application") _ .BrowseForFolder(0, "Datei oder Verzeichnis wählen" _ , &H4011, 17)
' Skript beenden, falls im Dialog die Schaltfläche ' Abbrechen gedrückt wurde If TypeName(Verzeichnis) = "Nothing" Then WScript.Quit
Objekt = LCase(Left(TypeName(Verzeichnis.ParentFolder), 6))
If (Objekt LIKE "folder*") Then For Each Objekt In Verzeichnis.ParentFolder.Items If Objekt.Name = Verzeichnis.Title Then Exit For Next End If DateiSystemDurchsuchen Objekt.Path End If
' *** Ende des Scripts
' ---------------------------------------------------------- '
' Rekursives Unterprogramm um das Dateisystem zu durchsuchen
' ---------------------------------------------------------- '
Private Sub DateiSystemDurchsuchen(Pfad) Dim Ordner, UnterOrdner, Datei
If FS.FolderExists(Pfad) Then ' Then: Falls Ordner übergeben wurde Set Ordner = FS.GetFolder(Pfad)
' Papierkorb nicht bearbeiten If LCase(Ordner.Name) = "recycled" Then Exit Sub
' Funktion Bearbeiten() für Ordner aufrufen If Not Bearbeiten(Ordner, False) Then Exit Sub
' Alle Dateien im Ordner bearbeiten For Each Datei In Ordner.Files ' Funktion Bearbeiten() für Dateien aufrufen If Not Bearbeiten(Datei, True) Then Exit For Next
' Alle Unterordner rekursiv bearbeiten For Each UnterOrdner In Ordner.SubFolders ' Einstieg In die Rekursion DateiSystemDurchsuchen UnterOrdner Next
ElseIf FS.FileExists(Pfad) Then ' Else: Falls eine einzelne Datei übergeben wurde Bearbeiten FS.GetFile(Pfad), True End If End Sub |
Die Funktionen zur Dateisuche und -verwaltung werden in allen folgenden
Beispielen benutzt, daher wurden sie ausgeleagert. Am Besten speichert man
den folgenden Code in eine Datei namens
#DateiSystem.inc . Die Datei sollte nicht als *.vbs
gespeichert werden, damit sie nicht versehentlich ausgeführt wird. Die
hier wiedergegebene Datei ist harmlos, es könnte jedoch sein, daß
Sie irgend wann einmal eine gefährliche Include-Datei entwickeln, die
nur unter der Kontrolle eines anderen Skripts laufen darf.
Diese Datei bringt im wesentlichen zwei wesentliche Funktionen mit:
Sie fragt ab, ob dem Skript irgend welche Startoptionen übergeben wurden
- falls nicht, öffnet es ein Dialogfenster, in dem Verzeichnisse und
Dateien ausgewählt werden können.
Es durchsucht das Dateisystem nach Deteien und Orndern und ruft eine vom
Anwender konstruierte Funktion namens Bearbeiten für jede
Datei und jedes Verzeichnis auf, welche das Programm in dieser Include-Datei
gefunden hat.
Der Windows-Papierkorb wird von diesem Skript automatisch von der Bearbeitung
ausgeschlossen.
Damit man diese Include-Datei in einem eigenen VB-Skript nutzen kann,
müssen folgende Voraussetzungen gegeben sein:
Im Kopf der VBS-Datei muß der Aufruf der Include-Datei stehen
In den folgenden Beispielen wird angenommen, daß die Include-Datei
#DateiSystem.inc heisst und im gleichen Verzeichnis
wie das aufrufende VBS steht.
Das VBS muß eine Funktion namens Bearbeiten
mit zwei Argumenten enthalten.
Die letzten beiden Punkte können natürlich durch Anpassung des
Skripts geändert werden.
Die Funktion Bearbeiten muss in der VBS-Datei stehen
und wird von der Include-Datei immer dann aufgerufen, wenn eine Datei oder
ein Verzeichnis gefunden wurde. Die Funktion
Bearbeiten muss mit zwei Argumenten und einem
Rückgabewert erstellt werden:
Bearbeiten(Objekt, IstDatei)
Das erste Argument Objekt entspricht dem
Dateisystemobjekt der gefundenen Datei
Das zweite Argument IstDatei ist True
oder False , je nach dem, ob es sich beim ersten Argument um
ein Verzeichnis oder eine Datei handelt.
Der Rückgabewert entscheidet, ob die Bearbeitung fortgesetzt wird. Wenn
der Rückgabewert True ist, wird die Bearbeitung fortgesetzt
und das Dateisystem weiter durchsucht. Wenn der Rückgabewert
False ist, kommt es darauf an, ob
Objekt eine Datei oder ein Verzeichnis ist: Bei
einem Verzeichnis, werden weder dessen Unterverzeichnisse noch dessen Dateien
durchsucht. Bei einer Datei wird die Suche abgebrochen.
Das Verhalten von Punkt 3 ist ein wenig erklärungsbedürftig:
Nehmen wir an, Sie durchsuchen Laufwerk C: nach Dateien vom Typ
*.WAV. Nun wollen Sie aber die Dateien im Verzeichnis
C:\Windows\ und seinen Unterverzeichnissen gerade nicht
suchen. Also prüft Ihre Funktion Bearbeiten ,
ob das übergebene Objekt ein Verzeichnis ist und auch noch
C:\Windows\ heißt. Falls ja, ist der
Rückgabewert von Bearbeiten
False und der Ordner
C:\Windows\ und seine Unterordner werden nicht mehr
durchsucht - alle anderen Ordner, wie z.B.
C:\Programme\ oder C:\Eigene
Dateien\ werden aber weiterhin durchsucht.
Wenn Sie nach der Datei MSCREATE.DIR suchen wollen,
um sie zu löschen, dann prüfen Sie, ob das Objekt eine Datei ist
und MSCREATE.DIR heisst. Falls ja, löschen Sie
die Datei. Da keine zweite Datei namens MSCREATE.DIR
im gleichen Verzeichnis existieren kann, erhält die Funktion
Bearbeiten den Rückgabewert
False , so dass in dem Verzeichnis keine weitere
Datei mehr bearbeitet wird - das beschleunigt die Arbeit des Skripts. Unterordner
werden aber weiterhin durchsucht.
|
' Aktueller Pfad dieses Skripts
SkriptPfad = WScript.ScriptFullName
SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) - Len(WScript.ScriptName))
' Include-Datei zur Dateisystemverwaltung laden
Execute CreateObject("Scripting.FileSystemObject") _
.OpenTextFile(SkriptPfad & "#DateiSystem.inc").ReadAll |
So ruft ein normales VBS die Include-Datei
#DateiSystem.inc auf, wenn sie im gleichen Verzeichnis
wie das VBS liegt: |
Private Function
Bearbeiten(Objekt, IstDatei) ... Bearbeiten = ...
...
End Function |
So muß die Funktion aufgebaut werden, die von der Include-Datei
#DateiSystem.inc mit Dateinamen und Verzeichnissen
gefüttert wird:
|
OrdnerListe = ""
Private Function Bearbeiten(Objekt, IstDatei)
If IstDatei Then
Bearbeiten = False
Else
OrdnerListe = OrdnerListe & Objekt.Name & vbNewLine
Bearbeiten = True
End If
End Function |
Dies ist allerdings die Minimalausstattung. Man kann die Struktur auch ein
wenig anpassen. Die folgende Funktion bearbeitet nur Ordner und sammelt deren
Namen in der Variablen OrdnerListe : |
Doch nun einige Anwendungsfälle für die Include-Datei: |
Schreibschutz entfernen |
Anzahl = 0
' -------- Include-Datei laden -------- ' ' Aktueller Pfad dieses Skripts SkriptPfad = WScript.ScriptFullName SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) _ - Len(WScript.ScriptName)) ' Include-Datei zur Dateisystemverwaltung laden Execute CreateObject("Scripting.FileSystemObject") _ .OpenTextFile(SkriptPfad & "#DateiSystem.inc").ReadAll ' -------- Ende Include-Datei laden -------- '
' Zeigt 5 Sekunden lang die Anzahl der bearbeiteten Dateien
CreateObject("WScript.Shell").PopUp Anzahl & _ " Dateien und Ordner bearbeitet", 5, "Schreibschutz entfernen"
'*** Ende des Skripts
' Hier wird festgelegt, wie Dateien bearbeitet werden sollen. Private Function Bearbeiten(Datei, IstDatei) ' Schreibschutz-Attribut einer/s Datei/Ordners löschen Datei.Attributes = Datei.Attributes And Not 1 Anzahl = Anzahl + 1 Bearbeiten = True End Function |
Wer Dateien von einer CD-ROM auf die Festplatte kopiert, der übernimmt
auch das Schreibschutz-Attribut von Dateien und Ordnern. Dies ist besonders
lästig, wenn man kopierte Dateien bearbeiten will, weil z.B. Datenbanken
schon beim Öffnen wegen dem Schreibschutz eine Warnmeldung ausgeben.
Das folgende Skript entfernt von einem Verzeichnis, den untergeordneten
Verzeichnissen und allen Dateien den Schreibschutz.
Das Skript zeigt zum Abschluss eine Meldung, die angibt, wieviele Dateien
bearbeitet wurden. Diese Meldung verschwindet nach 5 Sekunden automatisch,
so dass das Skript beispielsweise auch von einem Systempflegeprogramm
aufgerufen werden kann, ohne daß es den Prozess des aufrufenden Skripts anhält.
Der Code And Not 1 löscht das Schreibschutz-Attribut der Datei. Ersetzt
man die 1 durch andere Werte, kann man auch andere Attribute zurücksetzen:
And Not 2 = Versteckte Datei (Hidden)
And Not 4 = Systemdatei
And Not 32 = Archiv-Attribut löschen
Die Attribute kann man auch addieren: 34 = 32 + 2 setzt das Archiv- und das
Schreibschutz-Attribut zurück.
Um das Schreibschutz-Attribut zu setzen vwerwendet man Or 1 statt
And Not 1 . Sinngemäß lauten die Werte für die anderen Attribute:
Or 2 = Versteckte Datei (Hidden)
Or 4 = Systemdatei
Or 32 = Archiv-Attribut setzen
Wie man sieht, ist die Datei dank Include angenehm kurz. |
Tote Links
löschen |
Set WshShell = CreateObject("WScript.Shell") Anzahl = 0
' -------- Include-Datei laden -------- ' ' Aktueller Pfad dieses Skripts SkriptPfad = WScript.ScriptFullName SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) _ - Len(WScript.ScriptName)) ' Include-Datei zur Dateisystemverwaltung laden Execute CreateObject("Scripting.FileSystemObject") _ .OpenTextFile(SkriptPfad & "#DateiSystem.inc").ReadAll ' -------- Ende Include-Datei laden -------- '
WshShell.PopUp Anzahl & " Links gelöscht", 5, "Tote Links"
'*** Ende des Skripts
' Diese Prozedur prüft, ob ein Link existiert Private Function Bearbeiten(Objekt, IstDatei) Bearbeiten = True ' In jedem Falle weitermachen
Dim Quelle, LaufWerk, Typ
' Funktion verlassen, wenn ein Ordner übergeben wurde If Not IstDatei Then Exit Function
' Funktion verlassen, wenn die Datei kein Link ist If LCase(FS.GetExtensionName(Objekt)) <> "lnk" _ Then Exit Function
' Auf welche Datei/Verzeichnis zeigt der Link ? Quelle = WshShell.CreateShortcut(Objekt).TargetPath
' Funktion verlassen, wenn die Datei / Ordner, auf ' die der Link zeigt, existiert If FS.FileExists(Quelle) Then Exit Function If FS.FolderExists(Quelle) Then Exit Function
' Laufwerksbuchstaben bestimmen LaufWerk = FS.GetDriveName(Quelle)
' Existiert wenigstens das Laufwerk ? If FS.DriveExists(LaufWerk) Then ' Laufwerkstyp bestimmen Typ = FS.Drives(CStr(LaufWerk)).DriveType
' Falls der Link auf eine Datei/Ordner auf einer ' lokalen Festplatte (2) oder ein Netzlaufwerk (3) ' verweist, dann löschen If (Typ = 2) Or (Typ = 3) Then FS.DeleteFile Objekt Anzahl = Anzahl + 1 End If End If End Function |
Seit Windows 95 gibt es Links im Dateisystem. Auch wenn die vielen
nützlichen Möglichkeiten eines Links kaum in das Bewußtsein
normaler Benutzer dringt, gibt es eine Reihe von automatischen Funktionen,
die Links anlegen. Gelegentlich verschwindet die Datei, auf die ein Link
zeigt, und der Link wird überflüssig, manchmal sogar störend.
Tote Links entstehen z.B. unter folgenden Umständen:
Im Startmenü unter Dokumente wird über die zuletzt
bearbeiteten Dateien Buch geführt. Wenn man eine Datei nach dem Öffnen
löscht, bleibt sie im Menü Dokumente erhalten
Manche Programme sind nicht in der Lage, bei der Deinstallation verschobene
oder umbenannte Einträge im Startmenü zu finden und zu entfernen.
Das Skript durchsucht die angegebenen Verzeichnisse auf Links.
Beim Löschen wird nach folgendem Schema vorgegangen:
Wenn der Link auf ein Laufwerk verweist, das nicht vorhanden ist, dann wird
er nicht gelöscht, denn es könnte sein, daß Sie sich gerade
lokal angemeldet haben, das Netzwerk nicht verfügbar ist oder eine
Festplatte nicht in ihrem Wechselrahmen steckt.
Wenn der Link auf einen Wechseldatenträger (CD-ROM, Floppy, DVD, Iomega ZIP
...) verweist, wird er ebenfalls nicht gelöscht, denn das Skript kann
nicht feststellen, ob gerade genau das Medium im Laufwerk liegt, auf welches
der Link verweist. Diese Art von Links wird z.B. gerne für Lexika auf CD-ROM
im Startmenü angelegt.
Der Link wird also nur gelöscht, wenn er auf ein existierendes Netzlaufwerk
oder eine Festplatte verweist und die zugehörige Datei nicht zu finden ist
Wichtig für das VBS ist, dass die Variable WshShell vor
der Include-Datei geladen wird, denn die Include-Datei ruft ja die Funktion
Bearbeiten auf und dann muss das Objekt WScript.Shell bereits
der Variablen WshShell zugewisesn sein. |
Liste aller
Dateien |
Set FS = CreateObject("Scripting.FileSystemObject")
' Name und Pfad der Ausgabedatei im Temp-Ordner festlegen
DateiName = FS.GetSpecialFolder(2).Path & "\" & _
FS.GetBaseName(FS.GetTempName) & ".html"
' Ausgabedatei erstellen / öffnen
Set AusgabeDatei = FS.CreateTextFile(DateiName, True)
' Dateikopf schreiben
With AusgabeDatei
.Write "<HTML><HEAD><TITLE>"
.Write "Dateiliste ausgeben" ' Titelleiste
.Write "</TITLE></HEAD><BODY><H1>"
.Write "Dateiliste ausgeben" ' Überschrift
.Write "</H1><PRE>"
End With
Anzahl = 0 ' Zähler: Anzahl der Dateien
Bytes = 0 ' Zähler: Anzahl der Bytes
' -------- Include-Datei laden -------- '
' Aktueller Pfad dieses Skripts
SkriptPfad = WScript.ScriptFullName
SkriptPfad = Left(SkriptPfad, Len(SkriptPfad) _
- Len(WScript.ScriptName))
' Include-Datei zur Dateisystemverwaltung laden
Execute CreateObject("Scripting.FileSystemObject") _
.OpenTextFile(SkriptPfad & "#DateiSystem.inc").ReadAll
' -------- Ende Include-Datei laden -------- '
' Ende der Ausgabedatei schreiben
With AusgabeDatei
.Write "</PRE><P>" & Anzahl & " Dateien gefunden"
.Write "<BR>" & FormatNumber(Bytes \ 1024, , , , True)
.Write " kB</BODY></HTML>"
.Close End With
' Ausgabedatei öffnen
CreateObject("WScript.Shell").Run DateiName, True
' ... warten, bis Datei angezeigt wird
WScript.Sleep 1000
' ... und dann unauffällig wieder löschen
FS.DeleteFile DateiName, True
'*** Ende des Skripts
' Funktion, die den Inhalt der Ausgabe bestimmt
Private Function Bearbeiten(Datei, IstDatei)
If IstDatei Then
AusgabeDatei.WriteLine Datei.ParentFolder & "\<B>" & Datei.Name & "</B>"
Bytes = Bytes + Datei.Size
Anzahl = Anzahl + 1
End If Bearbeiten = True
End Function |
Dieses Skript gibt eine Liste aller Dateien aus, die im angegebenen Verzeichnis
und seinen Unterverzeichnissen gefunden wurden. Zur Ausgabe wird der Browser
benutzt, der standardmäßig die Dateien mit der Endung
*.HTML öffnet.
Um die Ausgabe von Pfad und Dateiname übersichtlicher zu gestalten,
wird der Dateiname bei der Ausgabe in den Browser fett hervorgehoben.
Die Include-Datei darf dabei nicht zu früh
geladen werden:
Zuerst muss die Ausgabedatei erzeugt werden, dann erst darf die
Include-Datei beginnen, die Dateinamen über die Funktion
Bearbeiten in die Ausgabedatei zu schreiben. Interessanterweise
gibt es hier auch keine Fehlermeldung, obwohl die Variable FS
sowohl in der Include-Datei, als auch in der VBS-Datei definiert wurde.
Damit das Skript nicht überflüssige HTML-Dateien
zurückläßt, wird die erzeugte HTML-Datei gelöscht, nachdem
der Browser sie dargestellt hat - der Browser zeigt also eine Datei, die
es im Augenblick ihres Erscheinens schon nicht mehr gibt. Um die
Daten in anderen Programmen zu verwenden kann man die Pfade aus dem
Browserfenster in die Zwischenablage kopieren und in andere Programme
übertragen. |