minpic01.jpg

Dr. Tobias Weltner

Walten und schalten

Automatische Systempflege beim Herunterfahren von Windows

Nach dem Systemstart kann Windows beliebige Programme ausführen - beim Herunterfahren aber nicht. Dabei wäre eine entsprechende Funktion äußerst hilfreich, um etwa die Festplatte aufzuräumen oder wichtige Daten zu sichern und erst anschließend den Computer auszuschalten. Mit Hilfe des Scripting Host rüstet man solche Wartungsroutinen kurzerhand nach.

Unterthema: Handwerkszeug
Unterthema: Listing 1
Unterthema: Listing 2
Unterthema: Listing 3
Unterthema: Listing 4
Unterthema: Listing 5
Unterthema: Listing 6

Anders als etwa MacOS besitzt Windows keinen Ordner `Ausschaltobjekte´, in dem der Anwender Programme und Skripte seiner Wahl platzieren kann. Es gibt zwar Shareware, die in den Ausschaltprozess einzugreifen vermag (`Shutdown-König´, siehe c't 12/99, S. 134), doch deren Möglichkeiten sind recht eingeschränkt im Vergleich zu jenen, die man sich mit dem Scripting Host von Windows erschließt [2, 3].

Wir haben insgesamt fünf Skriptprogramme fürs Herunterfahren implementiert, die zusammengenommen komfortabler sind als der von Microsoft vorgesehene Befehl. Wer vor dem Ausschalten die Festplatte automatisch defragmentieren, reparieren oder auch wichtige Daten sichern lassen möchte, sollte also in Zukunft sein Windows nicht mehr mit dem bekannten `Beenden´-Aufruf schließen. Genau wie dieser schalten die Skripte den Computer nach dem Herunterfahren sogar aus - sofern er über ein ATX-Netzteil verfügt.

Mehr als Ausschalten

Das Skript HERUNTERFAHREN.VBS fährt jeden Windows-9x-Rechner herunter und bietet nebenbei interessante Alternativen wie einen Kalt- oder Warmstart oder das Abmelden des aktuellen Benutzers, sodass man es auch als Grundlage für ganz andere Projekte verwenden kann. Windows NT lässt sich damit aber leider nicht herunterfahren; hier fehlen dem Scripting Host die entsprechenden Befehle. Immerhin schafft das Utility `Newgina´ Abhilfe [4].

Experimentieren Sie mit den einzelnen Varianten des Skriptes und fügen Sie bei Bedarf eigene Funktionen hinzu. Die entsprechend gekennzeichneten Listings arbeiten nur unter Windows 98. Alle haben eines gemeinsam: In den Skriptkonstanten sind die Herunterfahr-Befehle gespeichert, die mit der Run-Methode des WSHShell-Objekts aufgerufen werden. Die Systemvariable %WINDIR%, die das Windows-Verzeichnis enthält, wird dabei zuvor über ExpandEnvironmentStrings durch den tatsächlichen Ordnernamen ersetzt.

Bemerkenswert ist die undokumentierte Datei SOFTBOOT.EXE, mit der man das System neu starten kann. Sie existiert allerdings nur, wenn der Internet Explorer 4 installiert ist. Unter Windows 9x findet sie sich dann im Verzeichnis `Windows\System´, bei Windows NT unter `WinNT\System32´.

Auf Knopfdruck

Um das Skript in das Startmenü zu integrieren, ziehen Sie sein Icon einfach auf den Startknopf in der Taskleiste (meist links unten). Dort trägt es zunächst noch den Namen HERUNTERFAHREN.VBS und das übliche Skript-Icon. Um ihm einen schöneren Namen und ein passendes Icon zu geben, klicken Sie den Startknopf bei geschlossenem Startmenü mit der rechten Maustaste an und wählen im Kontextmenü, das jetzt aufklappt, `Öffnen´. Ein Explorerfenster zeigt den Inhalt des Startmenü-Ordners an, darunter die neue Verknüpfung auf das Skript. Klicken Sie diese wiederum mit der rechten Maustaste an und wählen Sie `Umbenennen´. Jetzt können Sie einen Namen Ihrer Wahl eingeben, zum Beispiel `Windows herunterfahren´. Ein weiterer Rechtsklick auf die Verknüpfung und die `Eigenschaften´ offenbaren zusätzliche Einstellungen: Man kann dem Skript eine Tastenkombination zuweisen, sodass es beispielsweise auf den Druck von STRG+ENDE ausgeführt wird. `Anderes Symbol´ erlaubt die Auswahl eines anderen Icons. So weit, so gut: Das System lässt sich nun bereits maßgeschneidert per Tastenkombination herunterfahren oder neu starten. Es fehlen nur noch die Wartungsbefehle.

Warten lassen

Das Skript HERUNTERFAHREN2.VBS übernimmt vor dem Herunterfahren die gewünschten Reparatur- und Aufräumarbeiten. Welche Tools zum Zuge kommen sollen, regelt die Prozedur Wartungsprogramme. Sie arbeitet nicht etwa mit der Run-Methode, sondern per Execute, einer weiteren Prozedur des Skripts. Diese verlangt drei Parameter: Den Befehlsaufruf des Tools, das Wartungsintervall in Tagen und einen unverwechselbaren Namen für den Auftrag, den Sie sich selbst aussuchen können. Damit braucht man also Wartungen nicht bei jedem Herunterfahren auszuführen, sondern kann gezielt sinnvolle Intervalle einstellen.

minpic02.jpg

Durch einen eigenen Eintrag im Startmenü erweitert man Windows um nützliche Wartungsfunktionen beim Ausschalten.

Execute prüft zunächst in der Registry, ob für den jeweiligen Auftrag bereits ein Schlüssel eingetragen ist. Falls ja, liest es aus dem Schlüssel das Datum, an dem das Tool zum letzten Mal ausgeführt wurde. Anschließend ermittelt es via DateDiff die Zeitdifferenz zum aktuellen Datum und kann so entscheiden, ob es Zeit ist, diesen Wartungsbefehl auszuführen. Da Windows von Haus aus mit zweistelligen Jahreszahlen arbeitet, wird die Routine beim Jahrtausendwechsel stolpern. Das können Sie verhindern, indem Sie die `Ländereinstellungen´ der Systemsteuerung auf vierstellige Jahreszahlen umstellen.

Ist das Intervall überschritten, ruft die Run-Methode den Wartungsbefehl auf. Der zusätzliche Parameter true lässt das Skript so lange anhalten, bis die Wartung abgeschlossen ist, sodass sich die Tools nicht gegenseitig ins Gehege kommen. Schließlich vermerkt das Skript das aktuelle Ausführungsdatum im Registry-Schlüssel des Tools.

Damit das Skript bequem zu handhaben ist, gibt es einige Meldungen aus. Steht beispielsweise ein Wartungsprogramm zur Ausführung an, so meldet das Skript dies und gibt die Möglichkeit, die Wartung abzubrechen und sofort herunterzufahren. Die Wartung wird dann beim nächsten Herunterfahren automatisch neu angeboten.

Darüber hinaus fragt das Skript nach jedem Wartungsprogramm nach, ob Sie den gesamten Prozess abbrechen wollen. Kommen Sie beispielsweise nach einigen Stunden an den Rechner und stellen fest, dass dieser noch mit Reparatur- oder Aufräumarbeiten beschäftigt ist, dann können Sie auf diese Weise das laufende Wartungsprogramm abbrechen und anschließend den Herunterfahr-Prozess abbrechen. Allerdings erscheint die Abfrage nur für vier Sekunden. So ist gewährleistet, dass das Skript im unbeaufsichtigten Modus nicht ewig wartet.

Das Skript speichert die Ausführungsdaten der einzelnen Wartungstools im Registry-Schlüssel HKEY_CURRENT_USER\Software\CTmagazin\. Das Skript CLEAR.VBS löscht diese Informationen auf Wunsch wieder - nützlich etwa, um das Skript ausgiebig zu testen. Es entfernt alle Eintragungen, sodass beim nächsten Herunterfahren wieder alle Wartungstools unabhängig vom eingestellten Wartungsintervall ausgeführt werden.

Einstellungssache

Das Beispielskript ruft die Wartungsprogramme SCANDSKW (Fehlerkorrektur der Festplatte) und DEFRAG (Optimierung der Festplattendaten) mit der undokumentierten Option /SAGERUN: auf, die speziell für den unbeaufsichtigten Batchbetrieb geschaffen wurde. Bevor Sie die Wartungsprogramme zum ersten Mal so aufrufen, sollten Sie die Optionen für den unbeaufsichtigten Betrieb per /SAGESET: festlegen.

minpic04.jpg

Speichern Sie beim Herunterfahren wichtige Dokumente auf ein anderes Laufwerk. Das hier abgedruckte Skript gibt nach getaner Arbeit eine Statusmeldung aus.

minpic03.jpg

Beim Herunterfahren kann Windows künftig Wartungsarbeiten übernehmen, etwa die Festplatte per Scandisk überprüfen und reparieren.

Durch die Eingabe von SCANDSKW.EXE /SAGESET:5 im Startmenü `Ausführen´ legt man alle Optionen des ScanDisk-Tools fest, die man später per /SAGERUN:5 aufrufen möchte. Wählen Sie als Prüfmethode `Standard´, und aktivieren Sie die Option `Fehler automatisch korrigieren´. Damit das Tool nach vollbrachter Arbeit keine störenden Meldungen anzeigt, die das Herunterfahren stoppen könnten, klickt man anschließend noch auf `Erweitert´ und wählt im Feld `Zusammenfassung anzeigen´ die Option `Nie´.

Rufen Sie als nächstes SCANDSKW.EXE /SAGESET:6 auf, schalten Sie auf `Intensiv´, aktivieren Sie je nach Wunsch weitere Optionen und schalten Sie wiederum `Fehler automatisch korrigieren´ ein. Der Festplatten-Optimierer Defrag lässt sich analog dazu über DEFRAG.EXE /SAGESET:5 konfigurieren. Welche Ziffern Sie hinter /SAGESET: respektive /SAGERUN: verwenden, spielt keine Rolle - nur die 1 sollten Sie vermeiden, denn die verwendet der Windows-98-Wartungsassistent.

Selber machen

Leider kann man einige wichtige Tools wie zum Beispiel das mitgelieferte Backup-Programm nicht über SAGESET/SAGERUN fernsteuern. Was aber nicht allzu tragisch ist: Auch solche Wartungsfunktionen lassen sich mit Skripten nachrüsten, die man anschließend ebenso über Execute aufruft wie die `offiziellen´ Tools. Allerdings kommt die Run-Methode des WSHShell-Objektes mit langen Dateinamen nicht klar. Deshalb sollten Sie den Pfadnamen Ihrer eigenen Wartungsskripte entweder in der DOS-konformen 8.3-Notation angeben oder den gesamten Pfadnamen zwischen Anführungszeichen setzen. Soll beispielsweise das Herunterfahren2-Skript jedes Mal das andere Skript C:\TEST\DOCLEAN.VBS ausführen, so lautet der entsprechende Befehl:

Execute """C:\TEST\DOCLEAN.VBS""", 0, "befehlx"
Wie oben beschrieben, erfordert Execute drei Parameter, nämlich den Befehlsaufruf, das Wartungsintervall (0 steht für `jedes Mal´) sowie einen unverwechselbaren Namen. Anstelle von `befehlx´ können Sie auch einen beliebigen anderen wählen. Da VBScript zwei Anführungszeichen in eins verwandelt, muss man hier drei angeben.

Sicher ist sicher

BACKITUP.VBS sichert beim Herunterfahren wichtige Daten einschließlich Ordnern auf ein Laufwerk Ihrer Wahl. Wie es arbeitet, regeln die im Skript dokumentierten Optionen. Man kann beispielsweise die Auswahl auf bestimmte Dateitypen beschränken, Unterordner mitsichern oder Dateien nur dann sichern, wenn die bereits vorhandenen Sicherungskopien veraltet sind. Freilich kann es mit dem inkrementellen Backup einer teuren Speziallösung nicht mithalten. Vielmehr kopiert es einfach die Dateien. Doch die Lösung funktioniert prächtig. Wer beispielsweise alle DOC-Dateien im Ordner C:\BRIEFE und die darin enthaltenen Unterordner auf D:\BACKUP sichern möchte, schreibt einfach:

BackItUp "C:\BRIEFE", "D:\BACKUP", ";doc;", 1
Nach getaner Arbeit gibt das Skript eine Erfolgsmeldung aus - aber nur für zehn Sekunden, wiederum, um andere Tätigkeiten nicht zu behindern.

Da das BACKITUP-Skript das gesamte Dateisystem durchsuchen kann, eignet es sich auch, um etwa überflüssige Dateien per Dateityp, Name oder letztem Dateizugriff zu sammeln und zu löschen. Das Umschreiben ist in wenigen Minuten erledigt, doch Vorsicht beim rekursiven Löschen - ein falscher Parameter kann zu verheerenden Ergebnissen führen!

Aufräumen

Ein weiteres Beispiel, was man beim Herunterfahren so anstellen kann, zeigt DOCLEAN.VBS. Es entrümpelt automatisch das Dokumente-Menü. Dort vermerkt Windows die 15 zuletzt geöffneten Dateien. Dummerweise sammeln sich schnell auch Dateien an, mit denen Sie gar nicht wirklich arbeiten wollen, die lediglich im Laufe der Zeit geöffnet wurden. DOCLEAN.VBS entfernt all jene Einträge aus dem Menü, die Sie für überflüssig halten - freilich nur die Verweise, nicht etwa die Originaldaten.

In der Variablen typen legt man durch Semikola getrennt fest, mit welchen Dateitypen man tatsächlich regelmäßig arbeitet. Im abgedruckten Skript sind das beispielsweise die Textdokumente .doc und .txt sowie das Bildformat .bmp. Alle Verweise, die nicht auf einen dieser Dateitypen verweisen, werden aus dem Dokumente-Menü entfernt: Nach dem nächsten Systemstart liefert es endlich einen wirklich wertvollen Überblick über alle wichtigen Dateien, mit denen kürzlich gearbeitet wurde.

Fenster zu!

Standardmäßig merkt sich Windows beim Herunterfahren alle geöffneten Explorer-Fenster. Beim nächsten Neustart öffnet es diese automatisch wieder, damit man an der Stelle weiterarbeiten kann, an der man zuletzt aufgehört hat. Doch das zieht den Startprozess nicht nur unnötig in die Länge, es kann auch lästige Fehlermeldungen verursachen: Lässt man beim Herunterfahren ein Explorerfenster mit dem Inhalt einer Diskette offen stehen, so versucht Windows beim nächsten Start erneut, die Diskette zu lesen - obwohl diese schon gar nicht mehr im Laufwerk liegt. Windows-98-Anwendern hilft das Skript AUTOCLOSE.VBS. Es schließt automatisch alle geöffneten Explorerfenster.

Wie schon in den letzten beiden Artikeln zum Scripting Host können wir hier aus Platzgründen nur funktionierende Beispiele ohne größeren Komfort bieten. Experimentieren Sie selbst, sichern Sie Ihre individuellen Dokumenttypen, speichern Sie Ihre Arbeitszeiten in einer Tabelle oder lassen Sie sich eine ganz neue Idee einfallen: Die Skripte bilden das ideale Grundgerüst dafür. (se)

Literatur
[1] Scripting Host zum Download: http://www.microsoft.com/scripting/windowshost/download/en/x86/wsh.exe

[2] Dr. Tobias Weltner: Windows im Griff, Mit dem Scripting Host wird das System erst rund, c't 10/99, S. 96

[3] Dr. Tobias Weltner: Scandruckfaxkopierer, Einlesen, Ausgeben, Bearbeiten mit Windows-Bordmitteln, c't 14/99, S. 192

[4] http://wwwthep.physik.uni-mainz.de/~frink/newgina_pre09.zip

Kasten 1


Handwerkszeug

Die Skripte setzen einen installierten Windows Scripting Host voraus, den Microsoft kostenlos anbietet. Windows-98-Anwender finden ihn auf der Windows-CD: Öffnen Sie in der Systemsteuerung das Software-Modul, klicken Sie auf das Register `Windows-Setup´ und dann in der Lieferliste der CD auf den Eintrag `Zubehör´. Anschließend lässt sich die Zubehörkomponente Windows Scripting Host auswählen. Benutzer von Windows 95 und NT finden den Scripting Host zum Download unter [1].

Kasten 2


Wenn das Dokumente-Menü Dateien beinhaltet, mit denen Sie nicht arbeiten wollen, sollten Sie es entrümpeln: DOCLEAN.VBS.

REM Doclean.VBS (c) c't/Tobias Weltner

typen = ";doc;txt;bmp;"
set fs = CreateObject("Scripting.FileSystemObject")
Set WshShell = Wscript.CreateObject("Wscript.Shell")

set ordner = fs.GetFolder(WshShell.SpecialFolders("Recent"))

for each datei in ordner.files
     if lcase(fs.GetExtensionName(datei.path)) = "lnk" then
          set scut = WshShell.CreateShortcut(datei.path)
          ziel = scut.TargetPath
          extension = ";" & lcase(fs.GetExtensionName(ziel)) & ";"
          if Instr(lcase(typen), extension)=0 then
               datei.delete vbtrue
          end if           
     end if
next
Kasten 3

AUTOCLOSE.VBS schließt alle geöffneten Fenster, was vor dem Ausschalten Probleme vermeiden kann.

REM Autoclose.VBS (c) c't/Tobias Weltner

do 
loop until CloseAllWindows=0
function CloseAllWindows
     set Shell = CreateObject("Shell.Application")
     set shellwindows = Shell.Windows
     for each window in shellwindows
          set parent = window.Application
          parent.Quit
     next
     set shellwindows = Shell.Windows
     CloseAllWindows = shellwindows.Count
end function
Kasten 4

Windows selber herunterfahren - die einfache Version: HERUNTERFAHREN.VBS

REM Herunterfahren.VBS (c) c't/Tobias Weltner

' Dieses Skript fährt den Rechner auf verschiedene Arten herunter

const sd_ausschalten9598 = "rundll32.exe user,ExitWindows"
const sd_kaltstart9598IE4 = "%windir%\system\softboot.exe /s:,60"
const sd_kaltstartNTIE4 = "%windir%\system32\softboot.exe /s:,60"
const sd_warmstart9598 = "rundll.exe user,ExitWindowsExec"
const sd_anmelden98 = "rundll32.exe shell32.dll,SHExitWindowsEx 0"
const sd_ausschalten98 = "rundll32.exe shell32.dll,SHExitWindowsEx 1"
const sd_kaltstart98 = "rundll32.exe shell32.dll,SHExitWindowsEx 2"

frage = "Wollen Sie Windows wirklich beenden?"
header = "Beenden"
antwort = MsgBox(frage, vbQuestion + vbYesNo, header)
if antwort = vbYes then
     ShutDown sd_ausschalten9598
end if

sub ShutDown(variante)
     set WSHShell = CreateObject("WScript.Shell")
     variante = WSHShell.ExpandEnvironmentStrings(variante)
     WSHShell.Run variante
end sub
Kasten 5

Die komfortablere Variante, HERUNTERFAHREN2.VBS, wartet das System und schaltet den Rechner anschließend aus.

REM Herunterfahren2.VBS (c) c't/Tobias Weltner

' Dieses Skript fährt den Rechner auf verschiedene Arten herunter

const sd_ausschalten9598 = "rundll32.exe user,ExitWindows"
const sd_kaltstart9598IE4 = "%windir%\system\softboot.exe /s:,60"
const sd_kaltstartNTIE4 = "%windir%\system32\softboot.exe /s:,60"
const sd_warmstart9598 = "rundll.exe user,ExitWindowsExec"
const sd_anmelden98 = "rundll32.exe shell32.dll,SHExitWindowsEx 0"
const sd_ausschalten98 = "rundll32.exe shell32.dll,SHExitWindowsEx 1"
const sd_kaltstart98 = "rundll32.exe shell32.dll,SHExitWindowsEx 2"

public asked
public wartung
public interrupt
public abbrechen

frage = "Wollen Sie Windows wirklich beenden?"
header = "Beenden"
antwort = MsgBox(frage, vbQuestion + vbYesNo, header)
if antwort = vbYes then
     ShutDown sd_ausschalten9598
end if

sub ShutDown(variante)
     set WSHShell = CreateObject("WScript.Shell")
     variante = WSHShell.ExpandEnvironmentStrings(variante)
     Wartungsprogramme
     if not abbrechen=vbYes then WSHShell.Run variante
end sub

sub Wartungsprogramme
     Execute "SCANDSKW.EXE /SAGERUN:5", 5, "befehl1"
     Execute "SCANDSKW.EXE /SAGERUN:6", 30, "befehl2"
     Execute "DEFRAG.EXE /SAGERUN:5", 14, "befehl3"
end sub

sub Execute(befehl, wann, key)
     set WSHShell = CreateObject("WScript.Shell")
     regkey = "HKCU\Software\CTmagazin\" + key + "\datum\"
     if KeyExists(regkey) then
          lastExec = WSHShell.RegRead(regkey)
          timediff = DateDiff("d", lastExec, Date())
          if timediff>=wann then
               doit = true
          else
               doit = false
          end if
     else
          doit = true
     end if

     if doit then
          if not asked then
               wartung = MsgBox("Es stehen einige Wartungen an. Durchführen?", 
               vbQuestion + vbYesNo)
               asked = true
          end if
          if wartung = vbYes then               
               WSHShell.Run befehl, 1, true
               WSHShell.RegWrite regkey, date()
               abbrechen = WSHShell.Popup("Herunterfahren abbrechen?", 4, 
               "Unterbrechung", vbQuestion + vbYesNo) 
               if abbrechen = vbYes then wartung = vbNo
          end if
     end if
     set WSHShell = Nothing
end sub

function KeyExists(key)
     on error resume next
     set WSHShell = CreateObject("WScript.Shell")
     test = WSHShell.RegRead(key)
     if err.number<>0 then
          err.clear
          KeyExists = false
     else
          KeyExists = true
     end if
     set WSHShell = Nothing
end function
Kasten 6

CLEAR.VBS löscht den Registry-Schlüssel wieder, der das Wartungsintervall speichert.

REM Clear.VBS (c) c't/Tobias Weltner

set WSHShell = CreateObject("WScript.Shell")
on error resume next
WSHShell.RegDelete "HKCU\Software\CTmagazin\"
if err.Number=0 then
     MsgBox "Registry-Einstellungen gelöscht", vbinformation
else
     MsgBox "Keine Registry-Einstellungen vorhanden", vbInformation
end if
Kasten 7

Wichtige Daten beim Ausschalten auf ein anderes Laufwerk sichern - mit BACKITUP.VBS kein Problem.

REM BackItUp.VBS (c) c't/Tobias Weltner

set fs = CreateObject("Scripting.FileSystemObject")
set WSHShell = CreateObject("WScript.Shell")

erneuert = 0
neukopiert = 0
uptodate = 0
unzutreffend = 0
neuordner = 0
problem = 0

' ---------------------------------------------------------------------
' Syntax:      BackItUp quelle, ziel, extensionen, modus
' quelle:      Ordner mit den Originalen
' ziel:        Ordner mit den Sicherheitskopien
' extensionen: Liste der Dateiextensionen, die gesichert werden sollen
'              Extensionen durch Semikola trennen: ";vbs;doc;txt;"
' modus:       1     auch Unterordner sichern
'              2     alle Dateien sichern
'              4     immer neu kopieren

BackItUp "C:\WINDOWS\DESKTOP\CT", "C:\BACKUP1", "", 1+2
' ---------------------------------------------------------------------

' Statusreport für 10 Sekunden anzeigen:
r = neukopiert & " Dateien neu kopiert" + vbCr
r = r &  erneuert & " Dateien aktualisiert" + vbCr
r = r & uptodate & " Dateien befanden sich auf aktuellem Stand" + vbCr
r = r & unzutreffend & " Dateien entsprachen nicht den Auswahlkriterien." + vbCr
r = r & problem & " Dateien konnten aufgrund von Fehlern nicht kopiert werden."
+ vbCr
r = r & neuordner & " neue Ordner angelegt."
WSHShell.Popup r, 10, "Report", vbInformation

sub BackItUp(original, ziel, extensionen, mode)
     ' "\" am Ende des Pfadnamens entfernen, falls vorhanden:
     if right(original,1)="\" then original=left(original, len(original)-1)
     if right(ziel,1)="\" then ziel=left(ziel, len(ziel)-1)

     ' Fehler abfangen:
     if not fs.FolderExists(original) then
          fehler = "Quell-Ordner """ & original & """ existiert nicht!"
     end if
     
     if not fs.FolderExists(ziel) then
          fehler = "Ziel-Ordner """ & ziel & """ existiert nicht!"
     end if
     
     if not fehler="" then
          MsgBox fehler, vbCritical
          WScript.Quit
     end if

     ' Quellordner sichern:
     set ordner = fs.GetFolder(original)
     BackupOrdner ordner, original, ziel, extensionen, mode          
end sub

sub BackupOrdner(folderobj, original, sicherung, extensionen, mode)
     ' Dateien in diesem Ordner sichern
     BackupFiles folderobj, original, sicherung, extensionen, mode

     ' Unterordner in diesem Ordner sichern
     ' (rekursiver Aufruf)
     if (mode and 1) then
          for each unterordner in folderobj.subfolders
               BackupOrdner unterordner, original, sicherung, extensionen, mode
          next
     end if
end sub

sub BackupFiles(ordner, original, sicherung, extensionen, mode)
     ' alle Dateien in diesem Ordner auflisten
     for each datei in ordner.files
          ' Dateiextension der aktuellen Datei ermitteln:
          extension = ";" & lcase(fs.GetExtensionName(datei.Path)) & ";"

          ' bei mode=2 oder passender Extension sichern:
          if (mode and 2) or (Instr(lcase(extensionen), extension) >0) then
               ' Original wann zuletzt geändert?
               alteroriginal = datei.DateLastModified

               ' liegt die Originaldatei in einem Unterordner?
               ' Pfad der Datei bestimmen:
               dateipfad = datei.path
               ' Dateinamen vom Pfad entfernen:
               dateipfad = left(dateipfad, InstrRev(dateipfad, "\"))
               ' nur das Unterverzeichnis des Originale-Ordners übriglassen:
               dateipfad = mid(dateipfad, len(original)+1)
               ' Sicherungsordner + evtl. Unterordner:
               sicherungsordner = sicherung + dateipfad
               
               ' Zieldateiname:
               zieldatei = sicherungsordner & datei.Name
               ' Existiert bereits die Sicherungskopie?
               zieldateiexist = fs.FileExists(zieldatei)
               if zieldateiexist then
                    ' von wann ist die Sicherungskopie?
                    alterziel = fs.GetFile(zieldatei).DateLastModified
               else
                    alterziel = CDate("1.1.80")
                    flag = true
               end if
               ' Sicherungskopie ist veraltet oder mode=4:
               if (alteroriginal>alterziel) or (mode and 4) then
                    ok = CopyIt(datei,sicherungsordner)
                    if flag and ok then
                         neukopiert = neukopiert + 1
                    elseif ok then
                         erneuert = erneuert + 1
                    else
                         problem = problem + 1
                    end if
               else
                    uptodate = uptodate + 1
               end if
          else
               unzutreffend = unzutreffend + 1
          end if
     next
end sub
          
function CopyIt(filehandle, zielordner)
     ' kopiert die Datei
     on error resume next
     if not fs.FolderExists(zielordner) then
          fs.CreateFolder zielordner
          neuordner = neuordner + 1
     end if
     ziel = zielordner & filehandle.name
     filehandle.copy ziel, true
     if err.number=0 then
          CopyIt = true
     else
          CopyIt = false
          err.clear
     end if
end function

Zu diesem Artikel existieren Programmbeispiele
1699_168.zip

1699_168.txt