Veröffentlicht: 28. Dez 1999 | Aktualisiert: 17. Jun 2004
Von Mathias Schiffer
.gif)
Installieren oder kopieren Sie Dateien, so können solche vorhandenen Dateien nicht überschrieben werden, die vom Betriebssystem aktuell genutzt werden (auch ein Umbenennen, Löschen oder Verschieben bleibt Ihnen versagt). Bei Installationsprogrammen folgt diesem Umstand zumeist der klassische Windows-Neustart, bevor die Installation als abgeschlossen gelten darf. Die vom Betriebssystem verwendete Datei kann dann unmittelbar vor dem Start von Windows selber überschrieben werden.
Um diesen Mechanismus in Ihren Anwendungen zu nutzen, verwenden Windows 95 / 98 und Windows NT / 2000 verschiedene Möglichkeiten. Gemeinsam ist ihnen jedoch grundsätzlich, dass die Information über Modifikationen vor dem Windows-Ende in einer Datei bzw. der Registry abgelegt wird. Vor dem Windows-Start wird diese Information dann ausgelesen. Die notwendigen Operationen werden schließlich durchgeführt, bevor Windows selber die problematischen Dateien wieder blockieren kann.
Windows NT / 2000
Unter Windows NT / 2000 gestaltet sich die Handhabung dieses Vorgehens vergleichsweise einfach: Die API-Funktion MoveFileEx bietet mit den Werten MOVEFILE_DELAY_UNTIL_REBOOT und MOVEFILE_REPLACE_EXISTING für ihren Parameter dwFlags die Möglichkeit, die notwendigen Einträge in die Registry zu schreiben, so dass der Vorgang selbst erst beim Neustart des Systems ausgeführt wird.
Im Folgenden finden Sie die VB-Deklaration der Funktion und weiterer von ihr unterstützter Konstanter (deren nähere, hier sekundäre Bedeutung Sie bei Bedarf bitte der Dokumentation der Funktion MoveFileEx im Platform SDK der MSDN Library entnehmen möchten):
' Deklaration der Funktion MoveFileEx und untersützter Konstanter:
Declare Function MoveFileEx Lib "kernel32" Alias "MoveFileExA" _
(ByVal lpExistingFileName As String, ByVal lpNewFileName As String, _
ByVal dwFlags As Long) As Boolean
Public Const MOVEFILE_REPLACE_EXISTING = &H1 ' Überschreiben, falls vorhanden
Public Const MOVEFILE_COPY_ALLOWED = &H2 ' Kopieren auf anderes Laufwerk ermöglichen
Public Const MOVEFILE_DELAY_UNTIL_REBOOT = &H4 ' Erst bei Neustart ausführen
Public Const MOVEFILE_WRITE_THROUGH = &H8 ' Erst nach Erfolg zurückkehren
Möchten Sie beispielsweise eine blockierte Datei "c:\winnt\system32\blocked.dll" überschreiben mit einer neuen Version, die Sie auf der Festplatte des Benutzers abgelegt haben unter dem zunächst geänderten Namen "c:\winnt\system32\blocked.new", so verwenden Sie die folgende Syntax für den Aufruf:
Dim Success As Boolean
Success = MoveFileEx("c:\winnt\system32\blocked.new", "c:\winnt\system32\blocked.dll", _
MOVEFILE_REPLACE_EXISTING Or MOVEFILE_DELAY_UNTIL_REBOOT)
If Success = False Then MsgBox "MoveFileEx schlug fehl.", vbCritical, "Fehler"
Die häufigste Fehlerursache beim Scheitern von MoveFileEx ist eine Verwendung der Funktion auf einem Benutzerkonto, das nicht der Administratorengruppe angehört und daher keine Schreibberechtigung für den relevanten Teil der Registry hat.
Nach einem erfolgreichen Aufruf finden Sie in der Registry im binären Schlüssel
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\PendingFileRenameOperations
die Dateioperationen, die beim nächsten Windows-Start durchgeführt werden sollen.
Wollen Sie eine blockierte Datei beim nächsten Start umbennen, so geben Sie im Parameter lpExistingFilename den bisherigen, in lpNewFileName den gewünschten Dateinamen an. Zum Löschen einer Datei geben Sie den Pfad zur Datei im ersten Parameter an, während Sie den zweiten Parameter mit der vordefinierten Konstante vbNullString belegen.
Tipp: Nach der Verwendung von MoveFileEx ist es nicht immer notwendig, Windows neu zu starten. Im Fall einer blockierten DLL beispielsweise wird auf Basis der Registry-Eintragungen bei einem neuen Zugriff bereits Ihre Ersatz-DLL verwendet. Anwendungen, die bereits zuvor auf die blockierte DLL zugriffen, verwenden natürlich nach wie vor die bisherige DLL.
Windows 95 / 98
Windows 95 und Windows 98 bieten eine ähnliche, jedoch nicht kompatible Variante an: Hier werden die bei einem Neustart gewünschten Änderungen nicht in der Registry, sondern in einer Datei Wininit.ini im Windows-Verzeichnis abgelegt. Beim Neustart des Systems wird diese INI-Datei von der Anwendung Wininit.exe abgearbeitet, wobei alle unter der Sektion "[rename]" aufgeführten Operationen durchgeführt werden. Nach der Abarbeitung wird diese Datei von Wininit.exe zu Prüf- und Sicherungszwecken umbenannt in Wininit.bak.
Der Aufbau einer Zeile der "[rename]"-Sektion ist denkbar einfach: Als Name des Eintrags wird die Zieldatei (bzw. der Zielname) verwendet, als Wert des Eintrags wird die Quelldatei (bzw. der Quellname) angegeben:
[rename] Zieldatei=Quelldatei
Hinweis: Es ist notwendig, die Pfade von Quell- und Zieldateien in 8.3-Notation anzugeben, da Wininit.exe zu einem Zeitpunkt ausgeführt wird, zu dem das Dateisystem für lange Dateinamen noch nicht etabliert ist. Für eine entsprechende Umwandlung können Sie die API-Funktion GetShortPathname verwenden.
Möchten Sie eine blockierte Datei löschen, so geben Sie wie aus MS-DOS gewohnt die Zeichenfolge "NUL" als Namen der Zieldatei an, z.B.:
[rename] NUL=c:\windows\system\killme.dat
Tipp: Für die Zusammenstellung einer Wininit.ini nutzen Sie idealerweise nicht die für INI-Dateien übliche API-Funktion WritePrivateProfileString, da mehrere identische Zieldatei-Angaben (z.B. "NUL") auftreten können. Mit WritePrivateProfileString würde nur die jeweils letzte Zuweisung einer Quelldatei zu einem Eintrag verbleiben. Sie sollten die Wininit.ini daher einlesen (bzw. bei Nichtvorhandensein selber erzeugen), die Sektion "[rename]" auffinden (bzw. erzeugen) und neue Einträge zeilenweise anhängen. Achten Sie dabei darauf, die Suche nach dieser Sektion unabhängig von Groß- und Kleinbuchstaben zu gestalten.
Weitere Hinweise zu diesem Thema finden Sie in Ihrer MSDN Library oder im MSDN Online: