2006. augusztus 5., szombat

Deleting or renaming open files


Problem/Question/Abstract:

Sometimes I need to handle files that are used by windows before they are loaded in the boot process, like a DLL or a VxD for example. How do I do that?

Answer:

Windows NT have a function called MoveFileEx that deletes files at reboot if used with the MOVEFILE_DELAY_UNTIL_REBOOT flag. Unfortunately, Windows 9x doesn't support this flag. So what do we do?

Every time you reboot, windows look for a file called WININIT.INI in the Windows directory. This file can contains Delete / Rename / Copy directives that will be excuted before anything is loaded (or almost). You can place commands in the [Rename] section using the syntax DESTINATION=SOURCE. If Destination is NUL, then the file will be deleted. Filenames and paths must use SHORT FILENAMES (because this file is processed before long filenames support is even loaded).

Please note that contrary to the example found in win32.hlp, you cannot use WritePrivateProfileString() or TIniFile to access this file because there might be duplicates values. If there is already one NUL value, TIniFile would overwrite it instead of creating a new one. So you better use TStringList instead.

Here are some example entries:

[rename]
NUL=C:\TEMP.TXT
NUL=C:\TEMP2.TXT
C:\NEW_DIR\EXISTING.TXT=C:\EXISTING.TXT
C:\NEW_DIR\NEWNAME.TXT=C:\OLDNAME.TXT
C:\EXISTING.TXT=C:\TEMP\NEWFILE.TXT

Below is the function DeleteLater that will just add NUL=Filename to wininit.ini, create the file if it doesn't exist, and also create the section if needed.

procedure DeleteLater(Filename: string);
var
  Wininit: string;
  Buffer: array[0..MAX_PATH] of char;
  I, J: integer;
  Ini: TStringList;
begin
  FillChar(Buffer, SizeOf(Buffer), 0);
  GetWindowsDirectory(Buffer, SizeOf(Buffer));
  Wininit := IncludeTrailingBackslash(Buffer) + 'Wininit.ini';

  Ini := TStringList.Create;
  try
    if FileExists(Wininit) then
      Ini.LoadFromFile(Wininit);
    for I := 0 to Ini.Count - 1 do
      Ini[I] := Uppercase(Ini[I]);

    J := Ini.IndexOf('[RENAME]');
    if J = -1 then
    begin
      Ini.Add('[Rename]');
      J := 0;
    end;
    FillChar(Buffer, SizeOf(Buffer), 0);
    GetShortPathName(PChar(Filename), Buffer, SizeOf(Buffer));
    Ini.Insert(J + 1, 'NUL=' + Buffer);
    Ini.SaveToFile(Wininit);
  finally
    Ini.Free;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése